From 75099b9404ed89c094b5c4bbd7bc405f399dec52 Mon Sep 17 00:00:00 2001 From: Tad Date: Sun, 29 Oct 2017 01:48:53 -0400 Subject: [PATCH] Add patches for many Linux CVEs, and overhaul script paths --- Patches/Linux_CVEs/CVE-2012-6657/0.patch | 34 + Patches/Linux_CVEs/CVE-2012-6689/0.patch | 73 + Patches/Linux_CVEs/CVE-2012-6701/0.patch | 106 + Patches/Linux_CVEs/CVE-2012-6703/0.patch | 31 + Patches/Linux_CVEs/CVE-2012-6703/1.patch | 31 + Patches/Linux_CVEs/CVE-2012-6703/2.patch | 66 + Patches/Linux_CVEs/CVE-2012-6704/0.patch | 97 + Patches/Linux_CVEs/CVE-2013-2015/0.patch | 48 + Patches/Linux_CVEs/CVE-2013-4312/0.patch | 141 + Patches/Linux_CVEs/CVE-2013-4312/1.patch | 162 + Patches/Linux_CVEs/CVE-2013-4312/2.patch | 140 + Patches/Linux_CVEs/CVE-2013-4312/3.patch | 158 + Patches/Linux_CVEs/CVE-2014-0196/0.patch | 80 + Patches/Linux_CVEs/CVE-2014-0196/1.patch | 84 + Patches/Linux_CVEs/CVE-2014-0196/2.patch | 83 + Patches/Linux_CVEs/CVE-2014-0206/0.patch | 45 + Patches/Linux_CVEs/CVE-2014-1739/0.patch | 33 + Patches/Linux_CVEs/CVE-2014-2523/0.patch | 59 + Patches/Linux_CVEs/CVE-2014-2523/1.patch | 64 + Patches/Linux_CVEs/CVE-2014-2706/0.patch | 160 + Patches/Linux_CVEs/CVE-2014-2851/0.patch | 64 + Patches/Linux_CVEs/CVE-2014-3145/0.patch | 90 + Patches/Linux_CVEs/CVE-2014-3145/1.patch | 91 + Patches/Linux_CVEs/CVE-2014-3145/2.patch | 92 + Patches/Linux_CVEs/CVE-2014-4014/0.patch | 206 + Patches/Linux_CVEs/CVE-2014-4323/0.patch | 33 + Patches/Linux_CVEs/CVE-2014-4655/0.patch | 85 + Patches/Linux_CVEs/CVE-2014-4655/1.patch | 90 + Patches/Linux_CVEs/CVE-2014-4655/2.patch | 27 + Patches/Linux_CVEs/CVE-2014-4656/0.patch | 37 + Patches/Linux_CVEs/CVE-2014-4656/1.patch | 39 + Patches/Linux_CVEs/CVE-2014-4943/0.patch | 51 + Patches/Linux_CVEs/CVE-2014-4943/1.patch | 56 + Patches/Linux_CVEs/CVE-2014-5206/0.patch | 52 + Patches/Linux_CVEs/CVE-2014-7822/0.patch | 72 + Patches/Linux_CVEs/CVE-2014-7825/0.patch | 50 + Patches/Linux_CVEs/CVE-2014-7825/1.patch | 91 + Patches/Linux_CVEs/CVE-2014-7825/2.patch | 85 + Patches/Linux_CVEs/CVE-2014-7970/0.patch | 47 + Patches/Linux_CVEs/CVE-2014-7970/1.patch | 54 + Patches/Linux_CVEs/CVE-2014-7970/2.patch | 50 + Patches/Linux_CVEs/CVE-2014-8160/0.patch | 88 + Patches/Linux_CVEs/CVE-2014-8160/1.patch | 94 + Patches/Linux_CVEs/CVE-2014-8173/0.patch | 51 + Patches/Linux_CVEs/CVE-2014-8709/0.patch | 53 + Patches/Linux_CVEs/CVE-2014-8709/1.patch | 56 + Patches/Linux_CVEs/CVE-2014-9420/0.patch | 52 + Patches/Linux_CVEs/CVE-2014-9420/1.patch | 57 + Patches/Linux_CVEs/CVE-2014-9529/0.patch | 44 + Patches/Linux_CVEs/CVE-2014-9529/1.patch | 51 + Patches/Linux_CVEs/CVE-2014-9683/0.patch | 32 + Patches/Linux_CVEs/CVE-2014-9683/1.patch | 37 + Patches/Linux_CVEs/CVE-2014-9715/0.patch | 50 + Patches/Linux_CVEs/CVE-2014-9715/1.patch | 56 + Patches/Linux_CVEs/CVE-2014-9731/0.patch | 236 + Patches/Linux_CVEs/CVE-2014-9777/0.patch | 48 + Patches/Linux_CVEs/CVE-2014-9778/0.patch | 48 + Patches/Linux_CVEs/CVE-2014-9780/0.patch | 30 + Patches/Linux_CVEs/CVE-2014-9781/0.patch | 37 + Patches/Linux_CVEs/CVE-2014-9782/0.patch | 135 + Patches/Linux_CVEs/CVE-2014-9783/0.patch | 218 + Patches/Linux_CVEs/CVE-2014-9784/0.patch | 203 + Patches/Linux_CVEs/CVE-2014-9785/0.patch | 66 + Patches/Linux_CVEs/CVE-2014-9786/0.patch | 48 + Patches/Linux_CVEs/CVE-2014-9787/0.patch | 43 + Patches/Linux_CVEs/CVE-2014-9788/0.patch | 194 + Patches/Linux_CVEs/CVE-2014-9789/0.patch | 105 + Patches/Linux_CVEs/CVE-2014-9790/0.patch | 64 + Patches/Linux_CVEs/CVE-2014-9792/0.patch | 34 + Patches/Linux_CVEs/CVE-2014-9803/0.patch | 70 + Patches/Linux_CVEs/CVE-2014-9863/0.patch | 123 + Patches/Linux_CVEs/CVE-2014-9864/0.patch | 343 + Patches/Linux_CVEs/CVE-2014-9865/0.patch | 91 + Patches/Linux_CVEs/CVE-2014-9866/0.patch | 45 + Patches/Linux_CVEs/CVE-2014-9867/0.patch | 108 + Patches/Linux_CVEs/CVE-2014-9868/0.patch | 60 + Patches/Linux_CVEs/CVE-2014-9869/0.patch | 74 + Patches/Linux_CVEs/CVE-2014-9869/1.patch | 145 + Patches/Linux_CVEs/CVE-2014-9870/0.patch | 216 + Patches/Linux_CVEs/CVE-2014-9871/0.patch | 146 + Patches/Linux_CVEs/CVE-2014-9872/0.patch | 99 + Patches/Linux_CVEs/CVE-2014-9873/0.patch | 35 + Patches/Linux_CVEs/CVE-2014-9874/0.patch | 64 + Patches/Linux_CVEs/CVE-2014-9874/1.patch | 44 + Patches/Linux_CVEs/CVE-2014-9875/0.patch | 246 + Patches/Linux_CVEs/CVE-2014-9876/0.patch | 51 + Patches/Linux_CVEs/CVE-2014-9876/1.patch | 30 + Patches/Linux_CVEs/CVE-2014-9877/0.patch | 94 + Patches/Linux_CVEs/CVE-2014-9878/0.patch | 103 + Patches/Linux_CVEs/CVE-2014-9879/0.patch | 155 + Patches/Linux_CVEs/CVE-2014-9880/0.patch | 35 + Patches/Linux_CVEs/CVE-2014-9881/0.patch | 63 + Patches/Linux_CVEs/CVE-2014-9882/0.patch | 54 + Patches/Linux_CVEs/CVE-2014-9882/1.patch | 48 + Patches/Linux_CVEs/CVE-2014-9883/0.patch | 58 + Patches/Linux_CVEs/CVE-2014-9884/0.patch | 151 + Patches/Linux_CVEs/CVE-2014-9885/0.patch | 30 + Patches/Linux_CVEs/CVE-2014-9886/0.patch | 178 + Patches/Linux_CVEs/CVE-2014-9887/0.patch | 35 + Patches/Linux_CVEs/CVE-2014-9888/0.patch | 37 + Patches/Linux_CVEs/CVE-2014-9888/1.patch | 35 + Patches/Linux_CVEs/CVE-2014-9889/0.patch | 85 + Patches/Linux_CVEs/CVE-2014-9889/1.patch | 155 + Patches/Linux_CVEs/CVE-2014-9890/0.patch | 39 + Patches/Linux_CVEs/CVE-2014-9891/0.patch | 64 + Patches/Linux_CVEs/CVE-2014-9892/0.patch | 35 + Patches/Linux_CVEs/CVE-2014-9893/0.patch | 78 + Patches/Linux_CVEs/CVE-2014-9894/0.patch | 39 + Patches/Linux_CVEs/CVE-2014-9895/0.patch | 33 + Patches/Linux_CVEs/CVE-2014-9895/1.patch | 36 + Patches/Linux_CVEs/CVE-2014-9896/0.patch | 86 + Patches/Linux_CVEs/CVE-2014-9897/0.patch | 32 + Patches/Linux_CVEs/CVE-2014-9898/0.patch | 178 + Patches/Linux_CVEs/CVE-2014-9899/0.patch | 43 + Patches/Linux_CVEs/CVE-2014-9900/0.patch | 36 + Patches/Linux_CVEs/CVE-2014-9901/0.patch | 294 + Patches/Linux_CVEs/CVE-2014-9902/0.patch | 61 + Patches/Linux_CVEs/CVE-2014-9903/0.patch | 44 + Patches/Linux_CVEs/CVE-2014-9904/0.patch | 36 + Patches/Linux_CVEs/CVE-2014-9914/0.patch | 178 + Patches/Linux_CVEs/CVE-2014-9922/0.patch | 92 + Patches/Linux_CVEs/CVE-2014-9940/0.patch | 31 + Patches/Linux_CVEs/CVE-2015-0569/0.patch | 34 + Patches/Linux_CVEs/CVE-2015-0569/1.patch | 32 + Patches/Linux_CVEs/CVE-2015-0569/2.patch | 33 + Patches/Linux_CVEs/CVE-2015-0570/0.patch | 178 + Patches/Linux_CVEs/CVE-2015-0570/1.patch | 175 + Patches/Linux_CVEs/CVE-2015-0570/2.patch | 185 + Patches/Linux_CVEs/CVE-2015-1420/0.patch | 45 + Patches/Linux_CVEs/CVE-2015-1465/0.patch | 97 + Patches/Linux_CVEs/CVE-2015-1593/0.patch | 111 + Patches/Linux_CVEs/CVE-2015-1805/0.patch | 185 + Patches/Linux_CVEs/CVE-2015-2041/0.patch | 52 + Patches/Linux_CVEs/CVE-2015-2041/1.patch | 58 + Patches/Linux_CVEs/CVE-2015-2686/0.patch | 38 + Patches/Linux_CVEs/CVE-2015-2922/0.patch | 45 + Patches/Linux_CVEs/CVE-2015-3288/0.patch | 76 + Patches/Linux_CVEs/CVE-2015-3288/1.patch | 73 + Patches/Linux_CVEs/CVE-2015-3339/0.patch | 114 + Patches/Linux_CVEs/CVE-2015-3339/1.patch | 116 + Patches/Linux_CVEs/CVE-2015-3636/0.patch | 29 + Patches/Linux_CVEs/CVE-2015-4170/0.patch | 121 + Patches/Linux_CVEs/CVE-2015-4177/0.patch | 46 + Patches/Linux_CVEs/CVE-2015-5366/0.patch | 62 + Patches/Linux_CVEs/CVE-2015-5697/0.patch | 45 + Patches/Linux_CVEs/CVE-2015-5706/0.patch | 39 + Patches/Linux_CVEs/CVE-2015-5707/0.patch | 36 + Patches/Linux_CVEs/CVE-2015-5707/1.patch | 44 + Patches/Linux_CVEs/CVE-2015-7509/0.patch | 51 + Patches/Linux_CVEs/CVE-2015-7515/0.patch | 45 + Patches/Linux_CVEs/CVE-2015-7515/1.patch | 51 + Patches/Linux_CVEs/CVE-2015-7550/0.patch | 112 + Patches/Linux_CVEs/CVE-2015-8019/0.patch | 99 + Patches/Linux_CVEs/CVE-2015-8019/1.patch | 99 + Patches/Linux_CVEs/CVE-2015-8019/2.patch | 94 + Patches/Linux_CVEs/CVE-2015-8539/0.patch | 125 + Patches/Linux_CVEs/CVE-2015-8543/0.patch | 139 + Patches/Linux_CVEs/CVE-2015-8575/0.patch | 27 + Patches/Linux_CVEs/CVE-2015-8785/0.patch | 61 + Patches/Linux_CVEs/CVE-2015-8830/0.patch | 84 + Patches/Linux_CVEs/CVE-2015-8830/1.patch | 106 + Patches/Linux_CVEs/CVE-2015-8839/0.patch | 442 + Patches/Linux_CVEs/CVE-2015-8839/1.patch | 37 + Patches/Linux_CVEs/CVE-2015-8937/0.patch | 36 + Patches/Linux_CVEs/CVE-2015-8938/0.patch | 255 + Patches/Linux_CVEs/CVE-2015-8939/0.patch | 67 + Patches/Linux_CVEs/CVE-2015-8940/0.patch | 48 + Patches/Linux_CVEs/CVE-2015-8941/0.patch | 159 + Patches/Linux_CVEs/CVE-2015-8942/0.patch | 31 + Patches/Linux_CVEs/CVE-2015-8943/0.patch | 62 + Patches/Linux_CVEs/CVE-2015-8944/0.patch | 33 + Patches/Linux_CVEs/CVE-2015-8951/0.patch | 76 + Patches/Linux_CVEs/CVE-2015-8955/0.patch | 110 + Patches/Linux_CVEs/CVE-2015-8961/0.patch | 44 + Patches/Linux_CVEs/CVE-2015-8962/0.patch | 67 + Patches/Linux_CVEs/CVE-2015-8963/0.patch | 96 + Patches/Linux_CVEs/CVE-2015-8964/0.patch | 78 + Patches/Linux_CVEs/CVE-2015-8964/1.patch | 80 + Patches/Linux_CVEs/CVE-2015-8966/0.patch | 112 + Patches/Linux_CVEs/CVE-2015-8967/0.patch | 34 + Patches/Linux_CVEs/CVE-2015-9004/0.patch | 91 + Patches/Linux_CVEs/CVE-2016-0723/0.patch | 69 + Patches/Linux_CVEs/CVE-2016-0728/0.patch | 81 + Patches/Linux_CVEs/CVE-2016-0758/0.patch | 88 + Patches/Linux_CVEs/CVE-2016-0774/0.patch | 63 + Patches/Linux_CVEs/CVE-2016-0774/1.patch | 60 + Patches/Linux_CVEs/CVE-2016-0805/0.patch | 58 + Patches/Linux_CVEs/CVE-2016-0806/0.patch | 6574 +++++++++++ Patches/Linux_CVEs/CVE-2016-0806/1.patch | 6570 +++++++++++ Patches/Linux_CVEs/CVE-2016-0819/0.patch | 35 + Patches/Linux_CVEs/CVE-2016-0821/0.patch | 48 + Patches/Linux_CVEs/CVE-2016-0823/0.patch | 45 + Patches/Linux_CVEs/CVE-2016-10044/0.patch | 66 + Patches/Linux_CVEs/CVE-2016-10088/0.patch | 48 + Patches/Linux_CVEs/CVE-2016-10153/0.patch | 144 + Patches/Linux_CVEs/CVE-2016-10154/0.patch | 93 + Patches/Linux_CVEs/CVE-2016-10200/0.patch | 167 + Patches/Linux_CVEs/CVE-2016-10208/0.patch | 67 + Patches/Linux_CVEs/CVE-2016-10208/1.patch | 71 + Patches/Linux_CVEs/CVE-2016-10208/2.patch | 31 + Patches/Linux_CVEs/CVE-2016-10208/3.patch | 37 + Patches/Linux_CVEs/CVE-2016-10229/0.patch | 94 + Patches/Linux_CVEs/CVE-2016-10230/0.patch | 35 + Patches/Linux_CVEs/CVE-2016-10231/0.patch | 37 + Patches/Linux_CVEs/CVE-2016-10231/1.patch | 38 + Patches/Linux_CVEs/CVE-2016-10232/0.patch | 111 + Patches/Linux_CVEs/CVE-2016-10232/1.patch | 83 + Patches/Linux_CVEs/CVE-2016-10233/0.patch | 102 + Patches/Linux_CVEs/CVE-2016-10233/1.patch | 37 + Patches/Linux_CVEs/CVE-2016-10234/0.patch | 382 + Patches/Linux_CVEs/CVE-2016-10234/1.patch | 287 + Patches/Linux_CVEs/CVE-2016-10235/0.patch | 35 + Patches/Linux_CVEs/CVE-2016-10235/1.patch | 35 + Patches/Linux_CVEs/CVE-2016-10236/0.patch | 41 + Patches/Linux_CVEs/CVE-2016-10283/0.patch | 42 + Patches/Linux_CVEs/CVE-2016-10283/1.patch | 44 + Patches/Linux_CVEs/CVE-2016-10285/0.patch | 143 + Patches/Linux_CVEs/CVE-2016-10286/0.patch | 50 + Patches/Linux_CVEs/CVE-2016-10287/0.patch | 48 + Patches/Linux_CVEs/CVE-2016-10288/0.patch | 206 + Patches/Linux_CVEs/CVE-2016-10289/0.patch | 80 + Patches/Linux_CVEs/CVE-2016-10290/0.patch | 88 + Patches/Linux_CVEs/CVE-2016-10291/0.patch | 74 + Patches/Linux_CVEs/CVE-2016-10293/0.patch | 184 + Patches/Linux_CVEs/CVE-2016-10294/0.patch | 122 + Patches/Linux_CVEs/CVE-2016-10295/0.patch | 238 + Patches/Linux_CVEs/CVE-2016-10296/0.patch | 88 + Patches/Linux_CVEs/CVE-2016-1583/0.patch | 57 + Patches/Linux_CVEs/CVE-2016-2053/0.patch | 125 + Patches/Linux_CVEs/CVE-2016-2059/0.patch | 41 + Patches/Linux_CVEs/CVE-2016-2061/0.patch | 239 + Patches/Linux_CVEs/CVE-2016-2063/0.patch | 41 + Patches/Linux_CVEs/CVE-2016-2068/0.patch | 69 + Patches/Linux_CVEs/CVE-2016-2185/0.patch | 109 + Patches/Linux_CVEs/CVE-2016-2185/1.patch | 109 + Patches/Linux_CVEs/CVE-2016-2186/0.patch | 38 + Patches/Linux_CVEs/CVE-2016-2186/1.patch | 38 + Patches/Linux_CVEs/CVE-2016-2187/0.patch | 56 + Patches/Linux_CVEs/CVE-2016-2187/1.patch | 59 + Patches/Linux_CVEs/CVE-2016-2188/0.patch | 41 + Patches/Linux_CVEs/CVE-2016-2188/1.patch | 46 + Patches/Linux_CVEs/CVE-2016-2188/2.patch | 56 + Patches/Linux_CVEs/CVE-2016-2384/0.patch | 34 + Patches/Linux_CVEs/CVE-2016-2465/0.patch | 173 + Patches/Linux_CVEs/CVE-2016-2467/0.patch | 91 + Patches/Linux_CVEs/CVE-2016-2468/0.patch | 44 + Patches/Linux_CVEs/CVE-2016-2488/0.patch | 40 + Patches/Linux_CVEs/CVE-2016-2503/0.patch | 102 + Patches/Linux_CVEs/CVE-2016-2504/0.patch | 180 + Patches/Linux_CVEs/CVE-2016-2544/0.patch | 38 + Patches/Linux_CVEs/CVE-2016-2545/0.patch | 37 + Patches/Linux_CVEs/CVE-2016-2546/0.patch | 122 + Patches/Linux_CVEs/CVE-2016-2547/0.patch | 101 + Patches/Linux_CVEs/CVE-2016-2549/0.patch | 54 + Patches/Linux_CVEs/CVE-2016-2847/0.patch | 250 + Patches/Linux_CVEs/CVE-2016-3070/0.patch | 163 + Patches/Linux_CVEs/CVE-2016-3134/0.patch | 115 + Patches/Linux_CVEs/CVE-2016-3135/0.patch | 34 + Patches/Linux_CVEs/CVE-2016-3136/0.patch | 49 + Patches/Linux_CVEs/CVE-2016-3136/1.patch | 53 + Patches/Linux_CVEs/CVE-2016-3137/0.patch | 49 + Patches/Linux_CVEs/CVE-2016-3137/1.patch | 53 + Patches/Linux_CVEs/CVE-2016-3138/0.patch | 34 + Patches/Linux_CVEs/CVE-2016-3138/1.patch | 39 + Patches/Linux_CVEs/CVE-2016-3140/0.patch | 54 + Patches/Linux_CVEs/CVE-2016-3140/1.patch | 57 + Patches/Linux_CVEs/CVE-2016-3156/0.patch | 97 + Patches/Linux_CVEs/CVE-2016-3672/0.patch | 95 + Patches/Linux_CVEs/CVE-2016-3689/0.patch | 40 + Patches/Linux_CVEs/CVE-2016-3689/1.patch | 40 + Patches/Linux_CVEs/CVE-2016-3768/0.patch | 52 + Patches/Linux_CVEs/CVE-2016-3775/0.patch | 53 + Patches/Linux_CVEs/CVE-2016-3775/1.patch | 48 + Patches/Linux_CVEs/CVE-2016-3775/2.patch | 108 + Patches/Linux_CVEs/CVE-2016-3813/0.patch | 51 + Patches/Linux_CVEs/CVE-2016-3841/0.patch | 557 + Patches/Linux_CVEs/CVE-2016-3841/1.patch | 574 + Patches/Linux_CVEs/CVE-2016-3841/2.patch | 572 + Patches/Linux_CVEs/CVE-2016-3842/0.patch | 208 + Patches/Linux_CVEs/CVE-2016-3842/1.patch | 163 + Patches/Linux_CVEs/CVE-2016-3842/2.patch | 77 + Patches/Linux_CVEs/CVE-2016-3843/0.patch | 132 + Patches/Linux_CVEs/CVE-2016-3843/1.patch | 119 + Patches/Linux_CVEs/CVE-2016-3843/2.patch | 30 + Patches/Linux_CVEs/CVE-2016-3843/3.patch | 35 + Patches/Linux_CVEs/CVE-2016-3854/0.patch | 34 + Patches/Linux_CVEs/CVE-2016-3855/0.patch | 41 + Patches/Linux_CVEs/CVE-2016-3857/0.patch | 52 + Patches/Linux_CVEs/CVE-2016-3857/1.patch | 32 + Patches/Linux_CVEs/CVE-2016-3859/0.patch | 36 + Patches/Linux_CVEs/CVE-2016-3865/0.patch | 86 + Patches/Linux_CVEs/CVE-2016-3865/1.patch | 86 + Patches/Linux_CVEs/CVE-2016-3867/0.patch | 505 + Patches/Linux_CVEs/CVE-2016-3867/1.patch | 1026 ++ Patches/Linux_CVEs/CVE-2016-3893/0.patch | 37 + Patches/Linux_CVEs/CVE-2016-3894/0.patch | 26 + Patches/Linux_CVEs/CVE-2016-3894/1.patch | 31 + Patches/Linux_CVEs/CVE-2016-3902/0.patch | 44 + Patches/Linux_CVEs/CVE-2016-3903/0.patch | 57 + Patches/Linux_CVEs/CVE-2016-3904/0.patch | 39 + Patches/Linux_CVEs/CVE-2016-3906/0.patch | 143 + Patches/Linux_CVEs/CVE-2016-3907/0.patch | 33 + Patches/Linux_CVEs/CVE-2016-3931/0.patch | 134 + Patches/Linux_CVEs/CVE-2016-3934/0.patch | 74 + Patches/Linux_CVEs/CVE-2016-3935/0.patch | 59 + Patches/Linux_CVEs/CVE-2016-4486/0.patch | 50 + Patches/Linux_CVEs/CVE-2016-4569/0.patch | 33 + Patches/Linux_CVEs/CVE-2016-4578/0.patch | 33 + Patches/Linux_CVEs/CVE-2016-4794/0.patch | 107 + Patches/Linux_CVEs/CVE-2016-4794/1.patch | 156 + Patches/Linux_CVEs/CVE-2016-4805/0.patch | 149 + Patches/Linux_CVEs/CVE-2016-4805/1.patch | 55 + Patches/Linux_CVEs/CVE-2016-4998/0.patch | 91 + Patches/Linux_CVEs/CVE-2016-5195/0.patch | 148 + Patches/Linux_CVEs/CVE-2016-5195/1.patch | 101 + Patches/Linux_CVEs/CVE-2016-5195/2.patch | 101 + Patches/Linux_CVEs/CVE-2016-5340/0.patch | 82 + Patches/Linux_CVEs/CVE-2016-5342/0.patch | 32 + Patches/Linux_CVEs/CVE-2016-5343/0.patch | 100 + Patches/Linux_CVEs/CVE-2016-5345/0.patch | 55 + Patches/Linux_CVEs/CVE-2016-5346/0.patch | 48 + Patches/Linux_CVEs/CVE-2016-5347/0.patch | 31 + Patches/Linux_CVEs/CVE-2016-5349/0.patch | 774 ++ Patches/Linux_CVEs/CVE-2016-5349/1.patch | 630 ++ Patches/Linux_CVEs/CVE-2016-5349/2.patch | 47 + Patches/Linux_CVEs/CVE-2016-5349/3.patch | 61 + Patches/Linux_CVEs/CVE-2016-5829/0.patch | 55 + Patches/Linux_CVEs/CVE-2016-5853/0.patch | 35 + Patches/Linux_CVEs/CVE-2016-5854/0.patch | 35 + Patches/Linux_CVEs/CVE-2016-5855/0.patch | 57 + Patches/Linux_CVEs/CVE-2016-5856/0.patch | 57 + Patches/Linux_CVEs/CVE-2016-5857/0.patch | 83 + Patches/Linux_CVEs/CVE-2016-5858/0.patch | 38 + Patches/Linux_CVEs/CVE-2016-5858/1.patch | 37 + Patches/Linux_CVEs/CVE-2016-5859/0.patch | 51 + Patches/Linux_CVEs/CVE-2016-5860/0.patch | 36 + Patches/Linux_CVEs/CVE-2016-5861/0.patch | 40 + Patches/Linux_CVEs/CVE-2016-5861/1.patch | 34 + Patches/Linux_CVEs/CVE-2016-5861/2.patch | 78 + Patches/Linux_CVEs/CVE-2016-5862/0.patch | 31 + Patches/Linux_CVEs/CVE-2016-5863/0.patch | 53 + Patches/Linux_CVEs/CVE-2016-5864/0.patch | 132 + Patches/Linux_CVEs/CVE-2016-5867/0.patch | 51 + Patches/Linux_CVEs/CVE-2016-5868/0.patch | 525 + Patches/Linux_CVEs/CVE-2016-5870/0.patch | 44 + Patches/Linux_CVEs/CVE-2016-6136/0.patch | 416 + Patches/Linux_CVEs/CVE-2016-6672/0.patch | 65 + Patches/Linux_CVEs/CVE-2016-6679/0.patch | 480 + Patches/Linux_CVEs/CVE-2016-6679/1.patch | 478 + Patches/Linux_CVEs/CVE-2016-6679/2.patch | 476 + Patches/Linux_CVEs/CVE-2016-6680/0.patch | 480 + Patches/Linux_CVEs/CVE-2016-6680/1.patch | 479 + Patches/Linux_CVEs/CVE-2016-6681/0.patch | 46 + Patches/Linux_CVEs/CVE-2016-6682/0.patch | 46 + Patches/Linux_CVEs/CVE-2016-6698/0.patch | 253 + Patches/Linux_CVEs/CVE-2016-6725/0.patch | 40 + Patches/Linux_CVEs/CVE-2016-6728/0.patch | 47 + Patches/Linux_CVEs/CVE-2016-6728/1.patch | 326 + Patches/Linux_CVEs/CVE-2016-6728/2.patch | 38 + Patches/Linux_CVEs/CVE-2016-6738/0.patch | 104 + Patches/Linux_CVEs/CVE-2016-6739/0.patch | 62 + Patches/Linux_CVEs/CVE-2016-6739/1.patch | 62 + Patches/Linux_CVEs/CVE-2016-6740/0.patch | 54 + Patches/Linux_CVEs/CVE-2016-6740/1.patch | 138 + Patches/Linux_CVEs/CVE-2016-6741/0.patch | 137 + Patches/Linux_CVEs/CVE-2016-6742/0.patch | 33 + Patches/Linux_CVEs/CVE-2016-6745/0.patch | 62 + Patches/Linux_CVEs/CVE-2016-6745/1.patch | 444 + Patches/Linux_CVEs/CVE-2016-6745/2.patch | 71 + Patches/Linux_CVEs/CVE-2016-6745/3.patch | 386 + Patches/Linux_CVEs/CVE-2016-6745/4.patch | 1 + Patches/Linux_CVEs/CVE-2016-6748/0.patch | 1739 +++ Patches/Linux_CVEs/CVE-2016-6748/1.patch | 2158 ++++ Patches/Linux_CVEs/CVE-2016-6750/0.patch | 101 + Patches/Linux_CVEs/CVE-2016-6751/0.patch | 35 + Patches/Linux_CVEs/CVE-2016-6752/0.patch | 109 + Patches/Linux_CVEs/CVE-2016-6753/0.patch | 32 + Patches/Linux_CVEs/CVE-2016-6755/0.patch | 58 + Patches/Linux_CVEs/CVE-2016-6756/0.patch | 53 + Patches/Linux_CVEs/CVE-2016-6757/0.patch | 683 ++ Patches/Linux_CVEs/CVE-2016-6786/0.patch | 505 + Patches/Linux_CVEs/CVE-2016-6787/0.patch | 505 + Patches/Linux_CVEs/CVE-2016-6791/0.patch | 97 + Patches/Linux_CVEs/CVE-2016-6828/0.patch | 55 + Patches/Linux_CVEs/CVE-2016-7042/0.patch | 74 + Patches/Linux_CVEs/CVE-2016-7097/0.patch | 436 + Patches/Linux_CVEs/CVE-2016-7912/0.patch | 37 + Patches/Linux_CVEs/CVE-2016-7913/0.patch | 162 + Patches/Linux_CVEs/CVE-2016-7913/1.patch | 45 + Patches/Linux_CVEs/CVE-2016-7913/2.patch | 131 + Patches/Linux_CVEs/CVE-2016-7914/0.patch | 109 + Patches/Linux_CVEs/CVE-2016-7915/0.patch | 47 + Patches/Linux_CVEs/CVE-2016-7916/0.patch | 56 + Patches/Linux_CVEs/CVE-2016-7917/0.patch | 76 + Patches/Linux_CVEs/CVE-2016-8391/0.patch | 97 + Patches/Linux_CVEs/CVE-2016-8393/0.patch | 444 + Patches/Linux_CVEs/CVE-2016-8393/1.patch | 61 + Patches/Linux_CVEs/CVE-2016-8393/2.patch | 62 + Patches/Linux_CVEs/CVE-2016-8394/0.patch | 32 + Patches/Linux_CVEs/CVE-2016-8399/0.patch | 71 + Patches/Linux_CVEs/CVE-2016-8399/1.patch | 64 + Patches/Linux_CVEs/CVE-2016-8401/0.patch | 42 + Patches/Linux_CVEs/CVE-2016-8402/0.patch | 176 + Patches/Linux_CVEs/CVE-2016-8402/1.patch | 394 + Patches/Linux_CVEs/CVE-2016-8404/0.patch | 32 + Patches/Linux_CVEs/CVE-2016-8405/0.patch | 82 + Patches/Linux_CVEs/CVE-2016-8406/0.patch | 102 + Patches/Linux_CVEs/CVE-2016-8407/0.patch | 157 + Patches/Linux_CVEs/CVE-2016-8410/0.patch | 1747 +++ Patches/Linux_CVEs/CVE-2016-8412/0.patch | 36 + Patches/Linux_CVEs/CVE-2016-8413/0.patch | 33 + Patches/Linux_CVEs/CVE-2016-8414/0.patch | 52 + Patches/Linux_CVEs/CVE-2016-8415/0.patch | 48 + Patches/Linux_CVEs/CVE-2016-8415/1.patch | 47 + Patches/Linux_CVEs/CVE-2016-8416/0.patch | 73 + Patches/Linux_CVEs/CVE-2016-8417/0.patch | 32 + Patches/Linux_CVEs/CVE-2016-8418/0.patch | 42 + Patches/Linux_CVEs/CVE-2016-8419/0.patch | 117 + Patches/Linux_CVEs/CVE-2016-8419/1.patch | 102 + Patches/Linux_CVEs/CVE-2016-8420/0.patch | 56 + Patches/Linux_CVEs/CVE-2016-8420/1.patch | 55 + Patches/Linux_CVEs/CVE-2016-8421/0.patch | 76 + Patches/Linux_CVEs/CVE-2016-8421/1.patch | 75 + Patches/Linux_CVEs/CVE-2016-8434/0.patch | 58 + Patches/Linux_CVEs/CVE-2016-8436/0.patch | 31 + Patches/Linux_CVEs/CVE-2016-8444/0.patch | 31 + Patches/Linux_CVEs/CVE-2016-8450/0.patch | 86 + Patches/Linux_CVEs/CVE-2016-8452/0.patch | 105 + Patches/Linux_CVEs/CVE-2016-8452/1.patch | 98 + Patches/Linux_CVEs/CVE-2016-8452/2.patch | 102 + Patches/Linux_CVEs/CVE-2016-8453/0.patch | 30 + Patches/Linux_CVEs/CVE-2016-8454/0.patch | 264 + Patches/Linux_CVEs/CVE-2016-8455/0.patch | 120 + Patches/Linux_CVEs/CVE-2016-8456/0.patch | 143 + Patches/Linux_CVEs/CVE-2016-8457/0.patch | 348 + Patches/Linux_CVEs/CVE-2016-8458/0.patch | 394 + Patches/Linux_CVEs/CVE-2016-8458/1.patch | 454 + Patches/Linux_CVEs/CVE-2016-8463/0.patch | 35 + Patches/Linux_CVEs/CVE-2016-8463/1.patch | 32 + Patches/Linux_CVEs/CVE-2016-8463/2.patch | 35 + Patches/Linux_CVEs/CVE-2016-8464/0.patch | 146 + Patches/Linux_CVEs/CVE-2016-8465/0.patch | 155 + Patches/Linux_CVEs/CVE-2016-8465/1.patch | 101 + Patches/Linux_CVEs/CVE-2016-8465/2.patch | 156 + Patches/Linux_CVEs/CVE-2016-8465/3.patch | 103 + Patches/Linux_CVEs/CVE-2016-8466/0.patch | 57 + Patches/Linux_CVEs/CVE-2016-8466/1.patch | 59 + Patches/Linux_CVEs/CVE-2016-8468/0.patch | 36 + Patches/Linux_CVEs/CVE-2016-8473/0.patch | 46 + Patches/Linux_CVEs/CVE-2016-8474/0.patch | 46 + Patches/Linux_CVEs/CVE-2016-8475/0.patch | 27 + Patches/Linux_CVEs/CVE-2016-8476/0.patch | 51 + Patches/Linux_CVEs/CVE-2016-8476/1.patch | 50 + Patches/Linux_CVEs/CVE-2016-8477/0.patch | 65 + Patches/Linux_CVEs/CVE-2016-8477/1.patch | 92 + Patches/Linux_CVEs/CVE-2016-8478/0.patch | 73 + Patches/Linux_CVEs/CVE-2016-8479/0.patch | 87 + Patches/Linux_CVEs/CVE-2016-8480/0.patch | 56 + Patches/Linux_CVEs/CVE-2016-8480/1.patch | 55 + Patches/Linux_CVEs/CVE-2016-8481/0.patch | 185 + Patches/Linux_CVEs/CVE-2016-8481/1.patch | 26 + Patches/Linux_CVEs/CVE-2016-8483/0.patch | 34 + Patches/Linux_CVEs/CVE-2016-8483/1.patch | 48 + Patches/Linux_CVEs/CVE-2016-8650/0.patch | 100 + Patches/Linux_CVEs/CVE-2016-8655/0.patch | 92 + Patches/Linux_CVEs/CVE-2016-9120/0.patch | 178 + Patches/Linux_CVEs/CVE-2016-9120/1.patch | 89 + Patches/Linux_CVEs/CVE-2016-9191/0.patch | 87 + Patches/Linux_CVEs/CVE-2016-9555/0.patch | 54 + Patches/Linux_CVEs/CVE-2016-9576/0.patch | 39 + Patches/Linux_CVEs/CVE-2016-9604/0.patch | 82 + Patches/Linux_CVEs/CVE-2016-9754/0.patch | 89 + Patches/Linux_CVEs/CVE-2016-9793/0.patch | 49 + Patches/Linux_CVEs/CVE-2016-9794/0.patch | 44 + Patches/Linux_CVEs/CVE-2016-9794/1.patch | 103 + Patches/Linux_CVEs/CVE-2016-9806/0.patch | 50 + Patches/Linux_CVEs/CVE-2017-0403/0.patch | 42 + Patches/Linux_CVEs/CVE-2017-0404/0.patch | 41 + Patches/Linux_CVEs/CVE-2017-0427/0.patch | 76 + Patches/Linux_CVEs/CVE-2017-0427/1.patch | 76 + Patches/Linux_CVEs/CVE-2017-0430/0.patch | 30 + Patches/Linux_CVEs/CVE-2017-0433/0.patch | 181 + Patches/Linux_CVEs/CVE-2017-0433/1.patch | 210 + Patches/Linux_CVEs/CVE-2017-0434/0.patch | 34 + Patches/Linux_CVEs/CVE-2017-0435/0.patch | 185 + Patches/Linux_CVEs/CVE-2017-0435/1.patch | 26 + Patches/Linux_CVEs/CVE-2017-0436/0.patch | 185 + Patches/Linux_CVEs/CVE-2017-0437/0.patch | 128 + Patches/Linux_CVEs/CVE-2017-0437/1.patch | 127 + Patches/Linux_CVEs/CVE-2017-0438/0.patch | 128 + Patches/Linux_CVEs/CVE-2017-0438/1.patch | 127 + Patches/Linux_CVEs/CVE-2017-0439/0.patch | 57 + Patches/Linux_CVEs/CVE-2017-0439/1.patch | 56 + Patches/Linux_CVEs/CVE-2017-0440/0.patch | 88 + Patches/Linux_CVEs/CVE-2017-0440/1.patch | 71 + Patches/Linux_CVEs/CVE-2017-0440/2.patch | 96 + Patches/Linux_CVEs/CVE-2017-0441/0.patch | 90 + Patches/Linux_CVEs/CVE-2017-0441/1.patch | 93 + Patches/Linux_CVEs/CVE-2017-0442/0.patch | 128 + Patches/Linux_CVEs/CVE-2017-0442/1.patch | 127 + Patches/Linux_CVEs/CVE-2017-0443/0.patch | 128 + Patches/Linux_CVEs/CVE-2017-0443/1.patch | 127 + Patches/Linux_CVEs/CVE-2017-0444/0.patch | 60 + Patches/Linux_CVEs/CVE-2017-0445/0.patch | 34 + Patches/Linux_CVEs/CVE-2017-0445/1.patch | 373 + Patches/Linux_CVEs/CVE-2017-0445/2.patch | 210 + Patches/Linux_CVEs/CVE-2017-0445/3.patch | 181 + Patches/Linux_CVEs/CVE-2017-0446/0.patch | 34 + Patches/Linux_CVEs/CVE-2017-0447/0.patch | 34 + Patches/Linux_CVEs/CVE-2017-0449/0.patch | 124 + Patches/Linux_CVEs/CVE-2017-0451/0.patch | 101 + Patches/Linux_CVEs/CVE-2017-0451/1.patch | 106 + Patches/Linux_CVEs/CVE-2017-0452/0.patch | 55 + Patches/Linux_CVEs/CVE-2017-0453/0.patch | 38 + Patches/Linux_CVEs/CVE-2017-0453/1.patch | 38 + Patches/Linux_CVEs/CVE-2017-0454/0.patch | 119 + Patches/Linux_CVEs/CVE-2017-0457/0.patch | 33 + Patches/Linux_CVEs/CVE-2017-0457/1.patch | 68 + Patches/Linux_CVEs/CVE-2017-0457/2.patch | 57 + Patches/Linux_CVEs/CVE-2017-0458/0.patch | 62 + Patches/Linux_CVEs/CVE-2017-0459/0.patch | 84 + Patches/Linux_CVEs/CVE-2017-0459/1.patch | 55 + Patches/Linux_CVEs/CVE-2017-0460/0.patch | 42 + Patches/Linux_CVEs/CVE-2017-0461/0.patch | 53 + Patches/Linux_CVEs/CVE-2017-0461/1.patch | 53 + Patches/Linux_CVEs/CVE-2017-0462/0.patch | 63 + Patches/Linux_CVEs/CVE-2017-0463/0.patch | 35 + Patches/Linux_CVEs/CVE-2017-0464/0.patch | 1101 ++ Patches/Linux_CVEs/CVE-2017-0464/1.patch | 2021 ++++ Patches/Linux_CVEs/CVE-2017-0465/0.patch | 68 + Patches/Linux_CVEs/CVE-2017-0507/0.patch | 67 + Patches/Linux_CVEs/CVE-2017-0509/0.patch | 4341 ++++++++ Patches/Linux_CVEs/CVE-2017-0510/0.patch | 206 + Patches/Linux_CVEs/CVE-2017-0510/1.patch | 206 + Patches/Linux_CVEs/CVE-2017-0516/0.patch | 37 + Patches/Linux_CVEs/CVE-2017-0518/0.patch | 39 + Patches/Linux_CVEs/CVE-2017-0518/1.patch | 138 + Patches/Linux_CVEs/CVE-2017-0519/0.patch | 123 + Patches/Linux_CVEs/CVE-2017-0520/0.patch | 304 + Patches/Linux_CVEs/CVE-2017-0521/0.patch | 46 + Patches/Linux_CVEs/CVE-2017-0523/0.patch | 75 + Patches/Linux_CVEs/CVE-2017-0524/0.patch | 118 + Patches/Linux_CVEs/CVE-2017-0524/1.patch | 85 + Patches/Linux_CVEs/CVE-2017-0524/2.patch | 91 + Patches/Linux_CVEs/CVE-2017-0525/0.patch | 663 ++ Patches/Linux_CVEs/CVE-2017-0531/0.patch | 275 + Patches/Linux_CVEs/CVE-2017-0533/0.patch | 73 + Patches/Linux_CVEs/CVE-2017-0534/0.patch | 73 + Patches/Linux_CVEs/CVE-2017-0536/0.patch | 91 + Patches/Linux_CVEs/CVE-2017-0537/0.patch | 94 + Patches/Linux_CVEs/CVE-2017-0564/0.patch | 157 + Patches/Linux_CVEs/CVE-2017-0568/0.patch | 79 + Patches/Linux_CVEs/CVE-2017-0568/1.patch | 35 + Patches/Linux_CVEs/CVE-2017-0569/0.patch | 79 + Patches/Linux_CVEs/CVE-2017-0570/0.patch | 79 + Patches/Linux_CVEs/CVE-2017-0571/0.patch | 27 + Patches/Linux_CVEs/CVE-2017-0572/0.patch | 60 + Patches/Linux_CVEs/CVE-2017-0573/0.patch | 53 + Patches/Linux_CVEs/CVE-2017-0574/0.patch | 69 + Patches/Linux_CVEs/CVE-2017-0575/0.patch | 84 + Patches/Linux_CVEs/CVE-2017-0575/1.patch | 91 + Patches/Linux_CVEs/CVE-2017-0576/0.patch | 48 + Patches/Linux_CVEs/CVE-2017-0583/0.patch | 45 + Patches/Linux_CVEs/CVE-2017-0584/0.patch | 54 + Patches/Linux_CVEs/CVE-2017-0584/1.patch | 54 + Patches/Linux_CVEs/CVE-2017-0586/0.patch | 54 + Patches/Linux_CVEs/CVE-2017-0604/0.patch | 81 + Patches/Linux_CVEs/CVE-2017-0606/0.patch | 130 + Patches/Linux_CVEs/CVE-2017-0607/0.patch | 74 + Patches/Linux_CVEs/CVE-2017-0608/0.patch | 52 + Patches/Linux_CVEs/CVE-2017-0609/0.patch | 137 + Patches/Linux_CVEs/CVE-2017-0610/0.patch | 34 + Patches/Linux_CVEs/CVE-2017-0610/1.patch | 59 + Patches/Linux_CVEs/CVE-2017-0611/0.patch | 59 + Patches/Linux_CVEs/CVE-2017-0612/0.patch | 43 + Patches/Linux_CVEs/CVE-2017-0613/0.patch | 217 + Patches/Linux_CVEs/CVE-2017-0614/0.patch | 122 + Patches/Linux_CVEs/CVE-2017-0619/0.patch | 113 + Patches/Linux_CVEs/CVE-2017-0620/0.patch | 60 + Patches/Linux_CVEs/CVE-2017-0621/0.patch | 33 + Patches/Linux_CVEs/CVE-2017-0622/0.patch | 51 + Patches/Linux_CVEs/CVE-2017-0626/0.patch | 159 + Patches/Linux_CVEs/CVE-2017-0627/0.patch | 37 + Patches/Linux_CVEs/CVE-2017-0628/0.patch | 56 + Patches/Linux_CVEs/CVE-2017-0629/0.patch | 56 + Patches/Linux_CVEs/CVE-2017-0631/0.patch | 41 + Patches/Linux_CVEs/CVE-2017-0632/0.patch | 85 + Patches/Linux_CVEs/CVE-2017-0633/0.patch | 128 + Patches/Linux_CVEs/CVE-2017-0650/0.patch | 154 + Patches/Linux_CVEs/CVE-2017-0705/0.patch | 84 + Patches/Linux_CVEs/CVE-2017-0740/0.patch | 110 + Patches/Linux_CVEs/CVE-2017-0746/0.patch | 43 + Patches/Linux_CVEs/CVE-2017-0748/0.patch | 41 + Patches/Linux_CVEs/CVE-2017-0750/0.patch | 44 + Patches/Linux_CVEs/CVE-2017-0751/0.patch | 47 + Patches/Linux_CVEs/CVE-2017-0786/0.patch | 41 + Patches/Linux_CVEs/CVE-2017-0787/0.patch | 60 + Patches/Linux_CVEs/CVE-2017-0788/0.patch | 60 + Patches/Linux_CVEs/CVE-2017-0789/0.patch | 661 ++ Patches/Linux_CVEs/CVE-2017-0790/0.patch | 173 + Patches/Linux_CVEs/CVE-2017-0791/0.patch | 53 + Patches/Linux_CVEs/CVE-2017-0792/0.patch | 45 + Patches/Linux_CVEs/CVE-2017-0794/0.patch | 164 + Patches/Linux_CVEs/CVE-2017-0824/0.patch | 105 + Patches/Linux_CVEs/CVE-2017-0825/0.patch | 129 + Patches/Linux_CVEs/CVE-2017-1000251/0.patch | 357 + Patches/Linux_CVEs/CVE-2017-1000364/0.patch | 874 ++ Patches/Linux_CVEs/CVE-2017-1000364/1.patch | 51 + Patches/Linux_CVEs/CVE-2017-1000364/2.patch | 52 + Patches/Linux_CVEs/CVE-2017-1000364/3.patch | 1549 +++ Patches/Linux_CVEs/CVE-2017-1000364/4.patch | 51 + Patches/Linux_CVEs/CVE-2017-1000365/0.patch | 91 + Patches/Linux_CVEs/CVE-2017-1000380/0.patch | 56 + Patches/Linux_CVEs/CVE-2017-1000380/1.patch | 73 + Patches/Linux_CVEs/CVE-2017-10661/0.patch | 99 + Patches/Linux_CVEs/CVE-2017-10662/0.patch | 56 + Patches/Linux_CVEs/CVE-2017-10663/0.patch | 57 + Patches/Linux_CVEs/CVE-2017-10663/1.patch | 52 + Patches/Linux_CVEs/CVE-2017-10996/0.patch | 63 + Patches/Linux_CVEs/CVE-2017-10997/0.patch | 48 + Patches/Linux_CVEs/CVE-2017-10998/0.patch | 45 + Patches/Linux_CVEs/CVE-2017-10998/1.patch | 43 + Patches/Linux_CVEs/CVE-2017-10999/0.patch | 76 + Patches/Linux_CVEs/CVE-2017-11000/0.patch | 33 + Patches/Linux_CVEs/CVE-2017-11001/0.patch | 49 + Patches/Linux_CVEs/CVE-2017-11002/0.patch | 88 + Patches/Linux_CVEs/CVE-2017-11040/0.patch | 35 + Patches/Linux_CVEs/CVE-2017-11046/0.patch | 48 + Patches/Linux_CVEs/CVE-2017-11048/0.patch | 38 + Patches/Linux_CVEs/CVE-2017-11050/0.patch | 45 + Patches/Linux_CVEs/CVE-2017-11050/1.patch | 45 + Patches/Linux_CVEs/CVE-2017-11051/0.patch | 31 + Patches/Linux_CVEs/CVE-2017-11051/1.patch | 30 + Patches/Linux_CVEs/CVE-2017-11052/0.patch | 42 + Patches/Linux_CVEs/CVE-2017-11052/1.patch | 41 + Patches/Linux_CVEs/CVE-2017-11053/0.patch | 40 + Patches/Linux_CVEs/CVE-2017-11053/1.patch | 41 + Patches/Linux_CVEs/CVE-2017-11054/0.patch | 90 + Patches/Linux_CVEs/CVE-2017-11054/1.patch | 87 + Patches/Linux_CVEs/CVE-2017-11055/0.patch | 30 + Patches/Linux_CVEs/CVE-2017-11055/1.patch | 30 + Patches/Linux_CVEs/CVE-2017-11056/0.patch | 93 + Patches/Linux_CVEs/CVE-2017-11057/0.patch | 84 + Patches/Linux_CVEs/CVE-2017-11059/0.patch | 83 + Patches/Linux_CVEs/CVE-2017-11060/0.patch | 116 + Patches/Linux_CVEs/CVE-2017-11060/1.patch | 97 + Patches/Linux_CVEs/CVE-2017-11060/2.patch | 36 + Patches/Linux_CVEs/CVE-2017-11061/0.patch | 110 + Patches/Linux_CVEs/CVE-2017-11061/1.patch | 109 + Patches/Linux_CVEs/CVE-2017-11062/0.patch | 74 + Patches/Linux_CVEs/CVE-2017-11062/1.patch | 68 + Patches/Linux_CVEs/CVE-2017-11064/0.patch | 63 + Patches/Linux_CVEs/CVE-2017-11064/1.patch | 62 + Patches/Linux_CVEs/CVE-2017-11067/0.patch | 147 + Patches/Linux_CVEs/CVE-2017-11067/1.patch | 139 + Patches/Linux_CVEs/CVE-2017-11600/0.patch | 44 + Patches/Linux_CVEs/CVE-2017-12146/0.patch | 63 + Patches/Linux_CVEs/CVE-2017-12153/0.patch | 43 + Patches/Linux_CVEs/CVE-2017-15265/0.patch | 142 + Patches/Linux_CVEs/CVE-2017-2618/0.patch | 67 + Patches/Linux_CVEs/CVE-2017-2636/0.patch | 313 + Patches/Linux_CVEs/CVE-2017-2671/0.patch | 55 + Patches/Linux_CVEs/CVE-2017-5546/0.patch | 64 + Patches/Linux_CVEs/CVE-2017-5547/0.patch | 144 + Patches/Linux_CVEs/CVE-2017-5550/0.patch | 108 + Patches/Linux_CVEs/CVE-2017-5551/0.patch | 45 + Patches/Linux_CVEs/CVE-2017-5669/0.patch | 70 + Patches/Linux_CVEs/CVE-2017-5669/1.patch | 75 + Patches/Linux_CVEs/CVE-2017-5897/0.patch | 91 + Patches/Linux_CVEs/CVE-2017-5967/0.patch | 939 ++ Patches/Linux_CVEs/CVE-2017-5970/0.patch | 47 + Patches/Linux_CVEs/CVE-2017-5972/0.patch | 112 + Patches/Linux_CVEs/CVE-2017-5986/0.patch | 39 + Patches/Linux_CVEs/CVE-2017-6001/0.patch | 159 + Patches/Linux_CVEs/CVE-2017-6074/0.patch | 44 + Patches/Linux_CVEs/CVE-2017-6074/1.patch | 47 + Patches/Linux_CVEs/CVE-2017-6214/0.patch | 42 + Patches/Linux_CVEs/CVE-2017-6214/1.patch | 45 + Patches/Linux_CVEs/CVE-2017-6345/0.patch | 58 + Patches/Linux_CVEs/CVE-2017-6346/0.patch | 126 + Patches/Linux_CVEs/CVE-2017-6347/0.patch | 48 + Patches/Linux_CVEs/CVE-2017-6348/0.patch | 87 + Patches/Linux_CVEs/CVE-2017-6353/0.patch | 65 + Patches/Linux_CVEs/CVE-2017-6421/0.patch | 2398 ++++ Patches/Linux_CVEs/CVE-2017-6423/0.patch | 67 + Patches/Linux_CVEs/CVE-2017-6424/0.patch | 40 + Patches/Linux_CVEs/CVE-2017-6424/1.patch | 50 + Patches/Linux_CVEs/CVE-2017-6425/0.patch | 46 + Patches/Linux_CVEs/CVE-2017-6426/0.patch | 124 + Patches/Linux_CVEs/CVE-2017-6874/0.patch | 89 + Patches/Linux_CVEs/CVE-2017-6951/0.patch | 49 + Patches/Linux_CVEs/CVE-2017-7184/0.patch | 48 + Patches/Linux_CVEs/CVE-2017-7184/1.patch | 38 + Patches/Linux_CVEs/CVE-2017-7187/0.patch | 54 + Patches/Linux_CVEs/CVE-2017-7277/0.patch | 121 + Patches/Linux_CVEs/CVE-2017-7277/1.patch | 95 + Patches/Linux_CVEs/CVE-2017-7364/0.patch | 49 + Patches/Linux_CVEs/CVE-2017-7366/0.patch | 457 + Patches/Linux_CVEs/CVE-2017-7366/1.patch | 254 + Patches/Linux_CVEs/CVE-2017-7368/0.patch | 368 + Patches/Linux_CVEs/CVE-2017-7369/0.patch | 50 + Patches/Linux_CVEs/CVE-2017-7369/1.patch | 50 + Patches/Linux_CVEs/CVE-2017-7370/0.patch | 50 + Patches/Linux_CVEs/CVE-2017-7371/0.patch | 45 + Patches/Linux_CVEs/CVE-2017-7371/1.patch | 45 + Patches/Linux_CVEs/CVE-2017-7372/0.patch | 127 + Patches/Linux_CVEs/CVE-2017-7373/0.patch | 34 + Patches/Linux_CVEs/CVE-2017-7373/1.patch | 33 + Patches/Linux_CVEs/CVE-2017-7374/0.patch | 251 + Patches/Linux_CVEs/CVE-2017-7472/0.patch | 182 + Patches/Linux_CVEs/CVE-2017-7487/0.patch | 38 + Patches/Linux_CVEs/CVE-2017-7495/0.patch | 87 + Patches/Linux_CVEs/CVE-2017-7616/0.patch | 76 + Patches/Linux_CVEs/CVE-2017-7618/0.patch | 234 + Patches/Linux_CVEs/CVE-2017-7618/1.patch | 1 + Patches/Linux_CVEs/CVE-2017-7889/0.patch | 210 + Patches/Linux_CVEs/CVE-2017-7979/0.patch | 130 + Patches/Linux_CVEs/CVE-2017-8233/0.patch | 60 + Patches/Linux_CVEs/CVE-2017-8234/0.patch | 74 + Patches/Linux_CVEs/CVE-2017-8235/0.patch | 118 + Patches/Linux_CVEs/CVE-2017-8236/0.patch | 147 + Patches/Linux_CVEs/CVE-2017-8237/0.patch | 476 + Patches/Linux_CVEs/CVE-2017-8239/0.patch | 75 + Patches/Linux_CVEs/CVE-2017-8240/0.patch | 31 + Patches/Linux_CVEs/CVE-2017-8241/0.patch | 42 + Patches/Linux_CVEs/CVE-2017-8242/0.patch | 34 + Patches/Linux_CVEs/CVE-2017-8244/0.patch | 185 + Patches/Linux_CVEs/CVE-2017-8244/1.patch | 175 + Patches/Linux_CVEs/CVE-2017-8244/2.patch | 165 + Patches/Linux_CVEs/CVE-2017-8245/0.patch | 106 + Patches/Linux_CVEs/CVE-2017-8245/1.patch | 99 + Patches/Linux_CVEs/CVE-2017-8245/2.patch | 106 + Patches/Linux_CVEs/CVE-2017-8246/0.patch | 116 + Patches/Linux_CVEs/CVE-2017-8246/1.patch | 124 + Patches/Linux_CVEs/CVE-2017-8246/2.patch | 93 + Patches/Linux_CVEs/CVE-2017-8247/0.patch | 35 + Patches/Linux_CVEs/CVE-2017-8250/0.patch | 40 + Patches/Linux_CVEs/CVE-2017-8251/0.patch | 64 + Patches/Linux_CVEs/CVE-2017-8253/0.patch | 69 + Patches/Linux_CVEs/CVE-2017-8254/0.patch | 41 + Patches/Linux_CVEs/CVE-2017-8256/0.patch | 32 + Patches/Linux_CVEs/CVE-2017-8257/0.patch | 182 + Patches/Linux_CVEs/CVE-2017-8259/0.patch | 50 + Patches/Linux_CVEs/CVE-2017-8260/0.patch | 82 + Patches/Linux_CVEs/CVE-2017-8261/0.patch | 33 + Patches/Linux_CVEs/CVE-2017-8262/0.patch | 107 + Patches/Linux_CVEs/CVE-2017-8264/0.patch | 235 + Patches/Linux_CVEs/CVE-2017-8264/1.patch | 316 + Patches/Linux_CVEs/CVE-2017-8265/0.patch | 62 + Patches/Linux_CVEs/CVE-2017-8266/0.patch | 52 + Patches/Linux_CVEs/CVE-2017-8266/1.patch | 182 + Patches/Linux_CVEs/CVE-2017-8268/0.patch | 79 + Patches/Linux_CVEs/CVE-2017-8269/0.patch | 38 + Patches/Linux_CVEs/CVE-2017-8277/0.patch | 43 + Patches/Linux_CVEs/CVE-2017-8280/0.patch | 191 + Patches/Linux_CVEs/CVE-2017-8281/0.patch | 95 + Patches/Linux_CVEs/CVE-2017-8281/1.patch | 34 + Patches/Linux_CVEs/CVE-2017-9074/0.patch | 231 + Patches/Linux_CVEs/CVE-2017-9074/1.patch | 229 + Patches/Linux_CVEs/CVE-2017-9074/2.patch | 97 + Patches/Linux_CVEs/CVE-2017-9075/0.patch | 33 + Patches/Linux_CVEs/CVE-2017-9076/0.patch | 64 + Patches/Linux_CVEs/CVE-2017-9077/0.patch | 64 + Patches/Linux_CVEs/CVE-2017-9150/0.patch | 75 + Patches/Linux_CVEs/CVE-2017-9242/0.patch | 63 + Patches/Linux_CVEs/CVE-2017-9676/0.patch | 347 + Patches/Linux_CVEs/CVE-2017-9676/1.patch | 272 + Patches/Linux_CVEs/CVE-2017-9677/0.patch | 1858 ++++ Patches/Linux_CVEs/CVE-2017-9677/1.patch | 1774 +++ Patches/Linux_CVEs/CVE-2017-9678/0.patch | 42 + Patches/Linux_CVEs/CVE-2017-9679/0.patch | 45 + Patches/Linux_CVEs/CVE-2017-9680/0.patch | 36 + Patches/Linux_CVEs/CVE-2017-9682/0.patch | 31 + Patches/Linux_CVEs/CVE-2017-9684/0.patch | 38 + Patches/Linux_CVEs/CVE-2017-9684/1.patch | 60 + Patches/Linux_CVEs/CVE-2017-9684/2.patch | 259 + Patches/Linux_CVEs/CVE-2017-9686/0.patch | 193 + Patches/Linux_CVEs/CVE-2017-9687/0.patch | 58 + Patches/Linux_CVEs/CVE-2017-9691/0.patch | 42 + Patches/Linux_CVEs/CVE-2017-9691/1.patch | 9751 +++++++++++++++++ Patches/Linux_CVEs/CVE-2017-9692/0.patch | 31 + Patches/Linux_CVEs/CVE-2017-9693/0.patch | 44 + Patches/Linux_CVEs/CVE-2017-9694/0.patch | 35 + Patches/Linux_CVEs/CVE-2017-9697/0.patch | 55 + Patches/Linux_CVEs/CVE-2017-9706/0.patch | 35 + Patches/Linux_CVEs/CVE-2017-9714/0.patch | 62 + Patches/Linux_CVEs/CVE-2017-9714/1.patch | 62 + Patches/Linux_CVEs/CVE-2017-9715/0.patch | 50 + Patches/Linux_CVEs/CVE-2017-9715/1.patch | 49 + Patches/Linux_CVEs/CVE-2017-9717/0.patch | 31 + Patches/Linux_CVEs/CVE-2017-9717/1.patch | 31 + Patches/Linux_CVEs/CVE-2017-9720/0.patch | 30 + Patches/Linux_CVEs/CVE-2017-9724/0.patch | 69 + Patches/Linux_CVEs/CVE-2017-9725/0.patch | 79 + Scripts/LineageOS-14.1/00init.sh | 21 + .../Deblob.sh} | 3 - .../Optimize.sh} | 2 - .../Patch.sh} | 12 +- Scripts/LineageOS-14.1/Patch_CVE.sh | 10 + .../Rebrand.sh} | 2 - .../Theme.sh} | 2 - 801 files changed, 123220 insertions(+), 16 deletions(-) create mode 100644 Patches/Linux_CVEs/CVE-2012-6657/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2012-6689/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2012-6701/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2012-6703/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2012-6703/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2012-6703/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2012-6704/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2013-2015/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2013-4312/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2013-4312/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2013-4312/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2013-4312/3.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-0196/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-0196/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-0196/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-0206/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-1739/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-2523/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-2523/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-2706/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-2851/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-3145/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-3145/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-3145/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4014/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4323/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4655/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4655/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4655/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4656/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4656/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4943/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-4943/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-5206/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-7822/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-7825/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-7825/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-7825/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-7970/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-7970/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-7970/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-8160/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-8160/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-8173/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-8709/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-8709/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9420/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9420/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9529/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9529/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9683/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9683/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9715/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9715/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9731/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9777/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9778/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9780/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9781/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9782/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9783/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9784/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9785/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9786/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9787/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9788/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9789/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9790/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9792/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9803/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9863/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9864/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9865/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9866/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9867/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9868/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9869/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9869/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9870/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9871/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9872/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9873/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9874/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9874/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9875/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9876/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9876/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9877/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9878/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9879/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9880/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9881/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9882/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9882/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9883/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9884/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9885/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9886/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9887/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9888/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9888/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9889/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9889/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9890/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9891/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9892/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9893/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9894/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9895/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9895/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9896/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9897/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9898/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9899/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9900/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9901/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9902/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9903/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9904/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9914/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9922/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2014-9940/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-0569/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-0569/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-0569/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-0570/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-0570/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-0570/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-1420/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-1465/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-1593/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-1805/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-2041/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-2041/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-2686/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-2922/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-3288/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-3288/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-3339/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-3339/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-3636/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-4170/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-4177/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-5366/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-5697/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-5706/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-5707/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-5707/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-7509/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-7515/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-7515/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-7550/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8019/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8019/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8019/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8539/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8543/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8575/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8785/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8830/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8830/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8839/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8839/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8937/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8938/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8939/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8940/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8941/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8942/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8943/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8944/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8951/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8955/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8961/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8962/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8963/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8964/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8964/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8966/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-8967/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2015-9004/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0723/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0728/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0758/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0774/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0774/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0805/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0806/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0806/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0819/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0821/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-0823/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10044/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10088/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10153/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10154/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10200/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10208/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10208/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10208/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10208/3.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10229/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10230/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10231/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10231/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10232/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10232/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10233/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10233/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10234/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10234/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10235/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10235/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10236/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10283/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10283/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10285/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10286/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10287/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10288/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10289/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10290/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10291/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10293/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10294/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10295/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-10296/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-1583/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2053/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2059/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2061/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2063/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2068/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2185/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2185/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2186/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2186/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2187/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2187/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2188/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2188/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2188/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2384/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2465/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2467/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2468/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2488/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2503/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2504/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2544/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2545/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2546/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2547/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2549/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-2847/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3070/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3134/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3135/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3136/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3136/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3137/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3137/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3138/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3138/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3140/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3140/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3156/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3672/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3689/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3689/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3768/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3775/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3775/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3775/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3813/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3841/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3841/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3841/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3842/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3842/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3842/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3843/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3843/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3843/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3843/3.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3854/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3855/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3857/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3857/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3859/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3865/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3865/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3867/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3867/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3893/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3894/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3894/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3902/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3903/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3904/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3906/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3907/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3931/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3934/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-3935/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-4486/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-4569/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-4578/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-4794/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-4794/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-4805/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-4805/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-4998/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5195/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5195/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5195/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5340/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5342/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5343/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5345/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5346/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5347/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5349/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5349/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5349/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5349/3.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5829/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5853/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5854/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5855/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5856/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5857/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5858/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5858/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5859/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5860/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5861/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5861/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5861/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5862/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5863/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5864/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5867/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5868/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-5870/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6136/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6672/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6679/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6679/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6679/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6680/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6680/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6681/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6682/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6698/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6725/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6728/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6728/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6728/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6738/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6739/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6739/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6740/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6740/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6741/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6742/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6745/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6745/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6745/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6745/3.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6745/4.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6748/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6748/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6750/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6751/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6752/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6753/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6755/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6756/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6757/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6786/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6787/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6791/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-6828/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7042/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7097/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7912/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7913/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7913/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7913/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7914/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7915/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7916/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-7917/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8391/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8393/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8393/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8393/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8394/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8399/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8399/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8401/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8402/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8402/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8404/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8405/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8406/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8407/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8410/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8412/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8413/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8414/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8415/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8415/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8416/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8417/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8418/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8419/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8419/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8420/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8420/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8421/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8421/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8434/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8436/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8444/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8450/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8452/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8452/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8452/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8453/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8454/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8455/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8456/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8457/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8458/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8458/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8463/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8463/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8463/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8464/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8465/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8465/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8465/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8465/3.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8466/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8466/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8468/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8473/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8474/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8475/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8476/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8476/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8477/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8477/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8478/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8479/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8480/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8480/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8481/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8481/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8483/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8483/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8650/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-8655/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9120/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9120/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9191/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9555/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9576/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9604/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9754/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9793/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9794/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9794/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2016-9806/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0403/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0404/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0427/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0427/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0430/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0433/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0433/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0434/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0435/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0435/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0436/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0437/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0437/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0438/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0438/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0439/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0439/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0440/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0440/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0440/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0441/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0441/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0442/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0442/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0443/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0443/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0444/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0445/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0445/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0445/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0445/3.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0446/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0447/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0449/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0451/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0451/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0452/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0453/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0453/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0454/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0457/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0457/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0457/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0458/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0459/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0459/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0460/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0461/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0461/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0462/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0463/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0464/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0464/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0465/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0507/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0509/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0510/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0510/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0516/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0518/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0518/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0519/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0520/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0521/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0523/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0524/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0524/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0524/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0525/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0531/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0533/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0534/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0536/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0537/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0564/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0568/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0568/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0569/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0570/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0571/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0572/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0573/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0574/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0575/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0575/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0576/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0583/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0584/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0584/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0586/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0604/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0606/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0607/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0608/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0609/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0610/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0610/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0611/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0612/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0613/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0614/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0619/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0620/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0621/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0622/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0626/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0627/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0628/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0629/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0631/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0632/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0633/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0650/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0705/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0740/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0746/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0748/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0750/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0751/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0786/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0787/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0788/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0789/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0790/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0791/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0792/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0794/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0824/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-0825/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000251/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000364/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000364/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000364/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000364/3.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000364/4.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000365/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000380/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-1000380/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10661/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10662/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10663/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10663/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10996/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10997/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10998/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10998/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-10999/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11000/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11001/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11002/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11040/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11046/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11048/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11050/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11050/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11051/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11051/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11052/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11052/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11053/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11053/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11054/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11054/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11055/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11055/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11056/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11057/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11059/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11060/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11060/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11060/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11061/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11061/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11062/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11062/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11064/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11064/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11067/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11067/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-11600/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-12146/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-12153/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-15265/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-2618/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-2636/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-2671/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5546/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5547/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5550/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5551/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5669/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5669/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5897/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5967/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5970/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5972/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-5986/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6001/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6074/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6074/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6214/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6214/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6345/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6346/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6347/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6348/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6353/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6421/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6423/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6424/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6424/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6425/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6426/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6874/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-6951/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7184/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7184/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7187/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7277/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7277/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7364/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7366/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7366/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7368/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7369/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7369/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7370/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7371/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7371/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7372/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7373/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7373/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7374/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7472/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7487/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7495/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7616/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7618/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7618/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7889/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-7979/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8233/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8234/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8235/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8236/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8237/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8239/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8240/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8241/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8242/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8244/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8244/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8244/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8245/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8245/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8245/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8246/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8246/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8246/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8247/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8250/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8251/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8253/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8254/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8256/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8257/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8259/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8260/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8261/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8262/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8264/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8264/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8265/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8266/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8266/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8268/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8269/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8277/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8280/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8281/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-8281/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9074/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9074/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9074/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9075/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9076/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9077/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9150/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9242/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9676/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9676/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9677/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9677/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9678/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9679/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9680/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9682/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9684/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9684/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9684/2.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9686/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9687/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9691/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9691/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9692/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9693/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9694/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9697/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9706/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9714/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9714/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9715/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9715/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9717/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9717/1.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9720/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9724/0.patch create mode 100644 Patches/Linux_CVEs/CVE-2017-9725/0.patch create mode 100644 Scripts/LineageOS-14.1/00init.sh rename Scripts/{Generic_Deblob.sh => LineageOS-14.1/Deblob.sh} (99%) rename Scripts/{LAOS-14.1_Optimize.sh => LineageOS-14.1/Optimize.sh} (96%) rename Scripts/{LAOS-14.1_Patches.sh => LineageOS-14.1/Patch.sh} (95%) create mode 100644 Scripts/LineageOS-14.1/Patch_CVE.sh rename Scripts/{LAOS-14.1_Rebrand.sh => LineageOS-14.1/Rebrand.sh} (94%) rename Scripts/{LAOS-14.1_Theme.sh => LineageOS-14.1/Theme.sh} (97%) diff --git a/Patches/Linux_CVEs/CVE-2012-6657/0.patch b/Patches/Linux_CVEs/CVE-2012-6657/0.patch new file mode 100644 index 00000000..3011c22d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2012-6657/0.patch @@ -0,0 +1,34 @@ +From 3e10986d1d698140747fcfc2761ec9cb64c1d582 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 24 Sep 2012 07:00:11 +0000 +Subject: net: guard tcp_set_keepalive() to tcp sockets + +Its possible to use RAW sockets to get a crash in +tcp_set_keepalive() / sk_reset_timer() + +Fix is to make sure socket is a SOCK_STREAM one. + +Reported-by: Dave Jones +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/core/sock.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index 3057920..a6000fb 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -691,7 +691,8 @@ set_rcvbuf: + + case SO_KEEPALIVE: + #ifdef CONFIG_INET +- if (sk->sk_protocol == IPPROTO_TCP) ++ if (sk->sk_protocol == IPPROTO_TCP && ++ sk->sk_type == SOCK_STREAM) + tcp_set_keepalive(sk, valbool); + #endif + sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2012-6689/0.patch b/Patches/Linux_CVEs/CVE-2012-6689/0.patch new file mode 100644 index 00000000..5cc076af --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2012-6689/0.patch @@ -0,0 +1,73 @@ +From 20e1db19db5d6b9e4e83021595eab0dc8f107bef Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Thu, 23 Aug 2012 02:09:11 +0000 +Subject: netlink: fix possible spoofing from non-root processes + +Non-root user-space processes can send Netlink messages to other +processes that are well-known for being subscribed to Netlink +asynchronous notifications. This allows ilegitimate non-root +process to send forged messages to Netlink subscribers. + +The userspace process usually verifies the legitimate origin in +two ways: + +a) Socket credentials. If UID != 0, then the message comes from + some ilegitimate process and the message needs to be dropped. + +b) Netlink portID. In general, portID == 0 means that the origin + of the messages comes from the kernel. Thus, discarding any + message not coming from the kernel. + +However, ctnetlink sets the portID in event messages that has +been triggered by some user-space process, eg. conntrack utility. +So other processes subscribed to ctnetlink events, eg. conntrackd, +know that the event was triggered by some user-space action. + +Neither of the two ways to discard ilegitimate messages coming +from non-root processes can help for ctnetlink. + +This patch adds capability validation in case that dst_pid is set +in netlink_sendmsg(). This approach is aggressive since existing +applications using any Netlink bus to deliver messages between +two user-space processes will break. Note that the exception is +NETLINK_USERSOCK, since it is reserved for netlink-to-netlink +userspace communication. + +Still, if anyone wants that his Netlink bus allows netlink-to-netlink +userspace, then they can set NL_NONROOT_SEND. However, by default, +I don't think it makes sense to allow to use NETLINK_ROUTE to +communicate two processes that are sending no matter what information +that is not related to link/neighbouring/routing. They should be using +NETLINK_USERSOCK instead for that. + +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: David S. Miller +--- + net/netlink/af_netlink.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 1445d73..5270238 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1373,7 +1373,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, + dst_pid = addr->nl_pid; + dst_group = ffs(addr->nl_groups); + err = -EPERM; +- if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) ++ if ((dst_group || dst_pid) && ++ !netlink_capable(sock, NL_NONROOT_SEND)) + goto out; + } else { + dst_pid = nlk->dst_pid; +@@ -2147,6 +2148,7 @@ static void __init netlink_add_usersock_entry(void) + rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners); + nl_table[NETLINK_USERSOCK].module = THIS_MODULE; + nl_table[NETLINK_USERSOCK].registered = 1; ++ nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND; + + netlink_table_ungrab(); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2012-6701/0.patch b/Patches/Linux_CVEs/CVE-2012-6701/0.patch new file mode 100644 index 00000000..7b75df93 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2012-6701/0.patch @@ -0,0 +1,106 @@ +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/Linux_CVEs/CVE-2012-6703/0.patch b/Patches/Linux_CVEs/CVE-2012-6703/0.patch new file mode 100644 index 00000000..1ae40584 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2012-6703/0.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; diff --git a/Patches/Linux_CVEs/CVE-2012-6703/1.patch b/Patches/Linux_CVEs/CVE-2012-6703/1.patch new file mode 100644 index 00000000..a93bedec --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2012-6703/1.patch @@ -0,0 +1,31 @@ +From 81ce573830e9d5531531b3ec778c58e6b9167bcd 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; diff --git a/Patches/Linux_CVEs/CVE-2012-6703/2.patch b/Patches/Linux_CVEs/CVE-2012-6703/2.patch new file mode 100644 index 00000000..d3ff0972 --- /dev/null +++ b/Patches/Linux_CVEs/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; diff --git a/Patches/Linux_CVEs/CVE-2012-6704/0.patch b/Patches/Linux_CVEs/CVE-2012-6704/0.patch new file mode 100644 index 00000000..494c9003 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2012-6704/0.patch @@ -0,0 +1,97 @@ +From 82981930125abfd39d7c8378a9cfdf5e1be2002b Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 26 Apr 2012 20:07:59 +0000 +Subject: [PATCH] net: cleanups in sock_setsockopt() + +Use min_t()/max_t() macros, reformat two comments, use !!test_bit() to +match !!sock_flag() + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/core/sock.c | 42 +++++++++++++++--------------------------- + 1 file changed, 15 insertions(+), 27 deletions(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index 0431aaf7473a2..10605d2ec8606 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -577,23 +577,15 @@ int sock_setsockopt(struct socket *sock, int level, int optname, + break; + case SO_SNDBUF: + /* Don't error on this BSD doesn't and if you think +- about it this is right. Otherwise apps have to +- play 'guess the biggest size' games. RCVBUF/SNDBUF +- are treated in BSD as hints */ +- +- if (val > sysctl_wmem_max) +- val = sysctl_wmem_max; ++ * about it this is right. Otherwise apps have to ++ * play 'guess the biggest size' games. RCVBUF/SNDBUF ++ * are treated in BSD as hints ++ */ ++ val = min_t(u32, val, sysctl_wmem_max); + set_sndbuf: + sk->sk_userlocks |= SOCK_SNDBUF_LOCK; +- if ((val * 2) < SOCK_MIN_SNDBUF) +- sk->sk_sndbuf = SOCK_MIN_SNDBUF; +- else +- sk->sk_sndbuf = val * 2; +- +- /* +- * Wake up sending tasks if we +- * upped the value. +- */ ++ sk->sk_sndbuf = max_t(u32, val * 2, SOCK_MIN_SNDBUF); ++ /* Wake up sending tasks if we upped the value. */ + sk->sk_write_space(sk); + break; + +@@ -606,12 +598,11 @@ int sock_setsockopt(struct socket *sock, int level, int optname, + + case SO_RCVBUF: + /* Don't error on this BSD doesn't and if you think +- about it this is right. Otherwise apps have to +- play 'guess the biggest size' games. RCVBUF/SNDBUF +- are treated in BSD as hints */ +- +- if (val > sysctl_rmem_max) +- val = sysctl_rmem_max; ++ * about it this is right. Otherwise apps have to ++ * play 'guess the biggest size' games. RCVBUF/SNDBUF ++ * are treated in BSD as hints ++ */ ++ val = min_t(u32, val, sysctl_rmem_max); + set_rcvbuf: + sk->sk_userlocks |= SOCK_RCVBUF_LOCK; + /* +@@ -629,10 +620,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, + * returning the value we actually used in getsockopt + * is the most desirable behavior. + */ +- if ((val * 2) < SOCK_MIN_RCVBUF) +- sk->sk_rcvbuf = SOCK_MIN_RCVBUF; +- else +- sk->sk_rcvbuf = val * 2; ++ sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF); + break; + + case SO_RCVBUFFORCE: +@@ -975,7 +963,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, + break; + + case SO_PASSCRED: +- v.val = test_bit(SOCK_PASSCRED, &sock->flags) ? 1 : 0; ++ v.val = !!test_bit(SOCK_PASSCRED, &sock->flags); + break; + + case SO_PEERCRED: +@@ -1010,7 +998,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, + break; + + case SO_PASSSEC: +- v.val = test_bit(SOCK_PASSSEC, &sock->flags) ? 1 : 0; ++ v.val = !!test_bit(SOCK_PASSSEC, &sock->flags); + break; + + case SO_PEERSEC: diff --git a/Patches/Linux_CVEs/CVE-2013-2015/0.patch b/Patches/Linux_CVEs/CVE-2013-2015/0.patch new file mode 100644 index 00000000..fd44f2cf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2013-2015/0.patch @@ -0,0 +1,48 @@ +From 016a3592cc34fa349235b5a8b48af5cece2cbfeb Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 27 Dec 2012 01:42:50 -0500 +Subject: [PATCH] ext4: avoid hang when mounting non-journal filesystems with + orphan list + +commit 0e9a9a1ad619e7e987815d20262d36a2f95717ca upstream. + +When trying to mount a file system which does not contain a journal, +but which does have a orphan list containing an inode which needs to +be truncated, the mount call with hang forever in +ext4_orphan_cleanup() because ext4_orphan_del() will return +immediately without removing the inode from the orphan list, leading +to an uninterruptible loop in kernel code which will busy out one of +the CPU's on the system. + +This can be trivially reproduced by trying to mount the file system +found in tests/f_orphan_extents_inode/image.gz from the e2fsprogs +source tree. If a malicious user were to put this on a USB stick, and +mount it on a Linux desktop which has automatic mounts enabled, this +could be considered a potential denial of service attack. (Not a big +deal in practice, but professional paranoids worry about such things, +and have even been known to allocate CVE numbers for such problems.) + +-js: This is a fix for CVE-2013-2015. + +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Zheng Liu +Acked-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/namei.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 9fb3fae4898a..54ad9a54cd89 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2054,7 +2054,8 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) + int err = 0; + + /* ext4_handle_valid() assumes a valid handle_t pointer */ +- if (handle && !ext4_handle_valid(handle)) ++ if (handle && !ext4_handle_valid(handle) && ++ !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) + return 0; + + mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock); diff --git a/Patches/Linux_CVEs/CVE-2013-4312/0.patch b/Patches/Linux_CVEs/CVE-2013-4312/0.patch new file mode 100644 index 00000000..3cb07295 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2013-4312/0.patch @@ -0,0 +1,141 @@ +From a5a6cf8c405e826ff7ed1308dde72560c0ed4854 Mon Sep 17 00:00:00 2001 +From: willy tarreau +Date: Sun, 10 Jan 2016 07:54:56 +0100 +Subject: unix: properly account for FDs passed over unix sockets + +commit 712f4aad406bb1ed67f3f98d04c044191f0ff593 upstream. + +It is possible for a process to allocate and accumulate far more FDs than +the process' limit by sending them over a unix socket then closing them +to keep the process' fd count low. + +This change addresses this problem by keeping track of the number of FDs +in flight per user and preventing non-privileged processes from having +more FDs in flight than their configured FD limit. + +Reported-by: socketpair@gmail.com +Reported-by: Tetsuo Handa +Mitigates: CVE-2013-4312 (Linux 2.0+) +Suggested-by: Linus Torvalds +Acked-by: Hannes Frederic Sowa +Signed-off-by: Willy Tarreau +Signed-off-by: David S. Miller +[carnil: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings +--- + include/linux/sched.h | 1 + + net/unix/af_unix.c | 24 ++++++++++++++++++++---- + net/unix/garbage.c | 14 ++++++++++---- + 3 files changed, 31 insertions(+), 8 deletions(-) + +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 9b9ac29..2bffa8a 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -709,6 +709,7 @@ struct user_struct { + unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */ + #endif + unsigned long locked_shm; /* How many pages of mlocked shm ? */ ++ unsigned long unix_inflight; /* How many files in flight in unix sockets */ + + #ifdef CONFIG_KEYS + struct key *uid_keyring; /* UID specific keyring */ +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 6cb363d..6798b3c 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1472,6 +1472,21 @@ static void unix_destruct_scm(struct sk_buff *skb) + sock_wfree(skb); + } + ++/* ++ * The "user->unix_inflight" variable is protected by the garbage ++ * collection lock, and we just read it locklessly here. If you go ++ * over the limit, there might be a tiny race in actually noticing ++ * it across threads. Tough. ++ */ ++static inline bool too_many_unix_fds(struct task_struct *p) ++{ ++ struct user_struct *user = current_user(); ++ ++ if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE))) ++ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); ++ return false; ++} ++ + #define MAX_RECURSION_LEVEL 4 + + static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) +@@ -1480,6 +1495,9 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + unsigned char max_level = 0; + int unix_sock_count = 0; + ++ if (too_many_unix_fds(current)) ++ return -ETOOMANYREFS; ++ + for (i = scm->fp->count - 1; i >= 0; i--) { + struct sock *sk = unix_get_socket(scm->fp->fp[i]); + +@@ -1501,10 +1519,8 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + if (!UNIXCB(skb).fp) + return -ENOMEM; + +- if (unix_sock_count) { +- for (i = scm->fp->count - 1; i >= 0; i--) +- unix_inflight(scm->fp->fp[i]); +- } ++ for (i = scm->fp->count - 1; i >= 0; i--) ++ unix_inflight(scm->fp->fp[i]); + return max_level; + } + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 00d3e56..fd1a840 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -125,9 +125,11 @@ struct sock *unix_get_socket(struct file *filp) + void unix_inflight(struct file *fp) + { + struct sock *s = unix_get_socket(fp); ++ ++ spin_lock(&unix_gc_lock); ++ + if (s) { + struct unix_sock *u = unix_sk(s); +- spin_lock(&unix_gc_lock); + if (atomic_long_inc_return(&u->inflight) == 1) { + BUG_ON(!list_empty(&u->link)); + list_add_tail(&u->link, &gc_inflight_list); +@@ -135,22 +137,26 @@ void unix_inflight(struct file *fp) + BUG_ON(list_empty(&u->link)); + } + unix_tot_inflight++; +- spin_unlock(&unix_gc_lock); + } ++ fp->f_cred->user->unix_inflight++; ++ spin_unlock(&unix_gc_lock); + } + + void unix_notinflight(struct file *fp) + { + struct sock *s = unix_get_socket(fp); ++ ++ spin_lock(&unix_gc_lock); ++ + if (s) { + struct unix_sock *u = unix_sk(s); +- spin_lock(&unix_gc_lock); + BUG_ON(list_empty(&u->link)); + if (atomic_long_dec_and_test(&u->inflight)) + list_del_init(&u->link); + unix_tot_inflight--; +- spin_unlock(&unix_gc_lock); + } ++ fp->f_cred->user->unix_inflight--; ++ spin_unlock(&unix_gc_lock); + } + + static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2013-4312/1.patch b/Patches/Linux_CVEs/CVE-2013-4312/1.patch new file mode 100644 index 00000000..ad02c976 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2013-4312/1.patch @@ -0,0 +1,162 @@ +From 5ea820046ee399214221c0bb817eb35d304c9604 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Wed, 3 Feb 2016 02:11:03 +0100 +Subject: unix: correctly track in-flight fds in sending process user_struct + +commit 415e3d3e90ce9e18727e8843ae343eda5a58fad6 upstream. + +The commit referenced in the Fixes tag incorrectly accounted the number +of in-flight fds over a unix domain socket to the original opener +of the file-descriptor. This allows another process to arbitrary +deplete the original file-openers resource limit for the maximum of +open files. Instead the sending processes and its struct cred should +be credited. + +To do so, we add a reference counted struct user_struct pointer to the +scm_fp_list and use it to account for the number of inflight unix fds. + +Fixes: 712f4aad406bb1 ("unix: properly account for FDs passed over unix sockets") +Reported-by: David Herrmann +Cc: David Herrmann +Cc: Willy Tarreau +Cc: Linus Torvalds +Suggested-by: Linus Torvalds +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +--- + include/net/af_unix.h | 4 ++-- + include/net/scm.h | 1 + + net/core/scm.c | 7 +++++++ + net/unix/af_unix.c | 4 ++-- + net/unix/garbage.c | 8 ++++---- + 5 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/include/net/af_unix.h b/include/net/af_unix.h +index f4842f7..a69bfee 100644 +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -6,8 +6,8 @@ + #include + #include + +-extern void unix_inflight(struct file *fp); +-extern void unix_notinflight(struct file *fp); ++extern void unix_inflight(struct user_struct *user, struct file *fp); ++extern void unix_notinflight(struct user_struct *user, struct file *fp); + extern void unix_gc(void); + extern void wait_for_unix_gc(void); + extern struct sock *unix_get_socket(struct file *filp); +diff --git a/include/net/scm.h b/include/net/scm.h +index 5da0a7b..9822a68 100644 +--- a/include/net/scm.h ++++ b/include/net/scm.h +@@ -16,6 +16,7 @@ struct scm_fp_list { + struct list_head list; + short count; + short max; ++ struct user_struct *user; + struct file *fp[SCM_MAX_FD]; + }; + +diff --git a/net/core/scm.c b/net/core/scm.c +index 51b4d52..9adabed 100644 +--- a/net/core/scm.c ++++ b/net/core/scm.c +@@ -80,6 +80,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + *fplp = fpl; + fpl->count = 0; + fpl->max = SCM_MAX_FD; ++ fpl->user = NULL; + } + fpp = &fpl->fp[fpl->count]; + +@@ -100,6 +101,10 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + *fpp++ = file; + fpl->count++; + } ++ ++ if (!fpl->user) ++ fpl->user = get_uid(current_user()); ++ + return num; + } + +@@ -124,6 +129,7 @@ void __scm_destroy(struct scm_cookie *scm) + list_del(&fpl->list); + for (i=fpl->count-1; i>=0; i--) + fput(fpl->fp[i]); ++ free_uid(fpl->user); + kfree(fpl); + } + +@@ -342,6 +348,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) + for (i = 0; i < fpl->count; i++) + get_file(fpl->fp[i]); + new_fpl->max = new_fpl->count; ++ new_fpl->user = get_uid(fpl->user); + } + return new_fpl; + } +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 6798b3c..390e079 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1454,7 +1454,7 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) + UNIXCB(skb).fp = NULL; + + for (i = scm->fp->count-1; i >= 0; i--) +- unix_notinflight(scm->fp->fp[i]); ++ unix_notinflight(scm->fp->user, scm->fp->fp[i]); + } + + static void unix_destruct_scm(struct sk_buff *skb) +@@ -1520,7 +1520,7 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + return -ENOMEM; + + for (i = scm->fp->count - 1; i >= 0; i--) +- unix_inflight(scm->fp->fp[i]); ++ unix_inflight(scm->fp->user, scm->fp->fp[i]); + return max_level; + } + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index fd1a840..33a21260 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -122,7 +122,7 @@ struct sock *unix_get_socket(struct file *filp) + * descriptor if it is for an AF_UNIX socket. + */ + +-void unix_inflight(struct file *fp) ++void unix_inflight(struct user_struct *user, struct file *fp) + { + struct sock *s = unix_get_socket(fp); + +@@ -138,11 +138,11 @@ void unix_inflight(struct file *fp) + } + unix_tot_inflight++; + } +- fp->f_cred->user->unix_inflight++; ++ user->unix_inflight++; + spin_unlock(&unix_gc_lock); + } + +-void unix_notinflight(struct file *fp) ++void unix_notinflight(struct user_struct *user, struct file *fp) + { + struct sock *s = unix_get_socket(fp); + +@@ -155,7 +155,7 @@ void unix_notinflight(struct file *fp) + list_del_init(&u->link); + unix_tot_inflight--; + } +- fp->f_cred->user->unix_inflight--; ++ user->unix_inflight--; + spin_unlock(&unix_gc_lock); + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2013-4312/2.patch b/Patches/Linux_CVEs/CVE-2013-4312/2.patch new file mode 100644 index 00000000..0d2161ce --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2013-4312/2.patch @@ -0,0 +1,140 @@ +From 712f4aad406bb1ed67f3f98d04c044191f0ff593 Mon Sep 17 00:00:00 2001 +From: willy tarreau +Date: Sun, 10 Jan 2016 07:54:56 +0100 +Subject: unix: properly account for FDs passed over unix sockets + +It is possible for a process to allocate and accumulate far more FDs than +the process' limit by sending them over a unix socket then closing them +to keep the process' fd count low. + +This change addresses this problem by keeping track of the number of FDs +in flight per user and preventing non-privileged processes from having +more FDs in flight than their configured FD limit. + +Reported-by: socketpair@gmail.com +Reported-by: Tetsuo Handa +Mitigates: CVE-2013-4312 (Linux 2.0+) +Suggested-by: Linus Torvalds +Acked-by: Hannes Frederic Sowa +Signed-off-by: Willy Tarreau +Signed-off-by: David S. Miller +--- + include/linux/sched.h | 1 + + net/unix/af_unix.c | 24 ++++++++++++++++++++---- + net/unix/garbage.c | 13 ++++++++----- + 3 files changed, 29 insertions(+), 9 deletions(-) + +diff --git a/include/linux/sched.h b/include/linux/sched.h +index edad7a4..fbf25f1 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -830,6 +830,7 @@ struct user_struct { + unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */ + #endif + unsigned long locked_shm; /* How many pages of mlocked shm ? */ ++ unsigned long unix_inflight; /* How many files in flight in unix sockets */ + + #ifdef CONFIG_KEYS + struct key *uid_keyring; /* UID specific keyring */ +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index ef05cd9..e3f85bc 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1513,6 +1513,21 @@ static void unix_destruct_scm(struct sk_buff *skb) + sock_wfree(skb); + } + ++/* ++ * The "user->unix_inflight" variable is protected by the garbage ++ * collection lock, and we just read it locklessly here. If you go ++ * over the limit, there might be a tiny race in actually noticing ++ * it across threads. Tough. ++ */ ++static inline bool too_many_unix_fds(struct task_struct *p) ++{ ++ struct user_struct *user = current_user(); ++ ++ if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE))) ++ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); ++ return false; ++} ++ + #define MAX_RECURSION_LEVEL 4 + + static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) +@@ -1521,6 +1536,9 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + unsigned char max_level = 0; + int unix_sock_count = 0; + ++ if (too_many_unix_fds(current)) ++ return -ETOOMANYREFS; ++ + for (i = scm->fp->count - 1; i >= 0; i--) { + struct sock *sk = unix_get_socket(scm->fp->fp[i]); + +@@ -1542,10 +1560,8 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + if (!UNIXCB(skb).fp) + return -ENOMEM; + +- if (unix_sock_count) { +- for (i = scm->fp->count - 1; i >= 0; i--) +- unix_inflight(scm->fp->fp[i]); +- } ++ for (i = scm->fp->count - 1; i >= 0; i--) ++ unix_inflight(scm->fp->fp[i]); + return max_level; + } + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index a73a226..8fcdc22 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -120,11 +120,11 @@ void unix_inflight(struct file *fp) + { + struct sock *s = unix_get_socket(fp); + ++ spin_lock(&unix_gc_lock); ++ + if (s) { + struct unix_sock *u = unix_sk(s); + +- spin_lock(&unix_gc_lock); +- + if (atomic_long_inc_return(&u->inflight) == 1) { + BUG_ON(!list_empty(&u->link)); + list_add_tail(&u->link, &gc_inflight_list); +@@ -132,25 +132,28 @@ void unix_inflight(struct file *fp) + BUG_ON(list_empty(&u->link)); + } + unix_tot_inflight++; +- spin_unlock(&unix_gc_lock); + } ++ fp->f_cred->user->unix_inflight++; ++ spin_unlock(&unix_gc_lock); + } + + void unix_notinflight(struct file *fp) + { + struct sock *s = unix_get_socket(fp); + ++ spin_lock(&unix_gc_lock); ++ + if (s) { + struct unix_sock *u = unix_sk(s); + +- spin_lock(&unix_gc_lock); + BUG_ON(list_empty(&u->link)); + + if (atomic_long_dec_and_test(&u->inflight)) + list_del_init(&u->link); + unix_tot_inflight--; +- spin_unlock(&unix_gc_lock); + } ++ fp->f_cred->user->unix_inflight--; ++ spin_unlock(&unix_gc_lock); + } + + static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2013-4312/3.patch b/Patches/Linux_CVEs/CVE-2013-4312/3.patch new file mode 100644 index 00000000..660997e9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2013-4312/3.patch @@ -0,0 +1,158 @@ +From 415e3d3e90ce9e18727e8843ae343eda5a58fad6 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Wed, 3 Feb 2016 02:11:03 +0100 +Subject: unix: correctly track in-flight fds in sending process user_struct + +The commit referenced in the Fixes tag incorrectly accounted the number +of in-flight fds over a unix domain socket to the original opener +of the file-descriptor. This allows another process to arbitrary +deplete the original file-openers resource limit for the maximum of +open files. Instead the sending processes and its struct cred should +be credited. + +To do so, we add a reference counted struct user_struct pointer to the +scm_fp_list and use it to account for the number of inflight unix fds. + +Fixes: 712f4aad406bb1 ("unix: properly account for FDs passed over unix sockets") +Reported-by: David Herrmann +Cc: David Herrmann +Cc: Willy Tarreau +Cc: Linus Torvalds +Suggested-by: Linus Torvalds +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + include/net/af_unix.h | 4 ++-- + include/net/scm.h | 1 + + net/core/scm.c | 7 +++++++ + net/unix/af_unix.c | 4 ++-- + net/unix/garbage.c | 8 ++++---- + 5 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/include/net/af_unix.h b/include/net/af_unix.h +index 2a91a05..9b4c418 100644 +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -6,8 +6,8 @@ + #include + #include + +-void unix_inflight(struct file *fp); +-void unix_notinflight(struct file *fp); ++void unix_inflight(struct user_struct *user, struct file *fp); ++void unix_notinflight(struct user_struct *user, struct file *fp); + void unix_gc(void); + void wait_for_unix_gc(void); + struct sock *unix_get_socket(struct file *filp); +diff --git a/include/net/scm.h b/include/net/scm.h +index 262532d..59fa93c 100644 +--- a/include/net/scm.h ++++ b/include/net/scm.h +@@ -21,6 +21,7 @@ struct scm_creds { + struct scm_fp_list { + short count; + short max; ++ struct user_struct *user; + struct file *fp[SCM_MAX_FD]; + }; + +diff --git a/net/core/scm.c b/net/core/scm.c +index 14596fb..2696aef 100644 +--- a/net/core/scm.c ++++ b/net/core/scm.c +@@ -87,6 +87,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + *fplp = fpl; + fpl->count = 0; + fpl->max = SCM_MAX_FD; ++ fpl->user = NULL; + } + fpp = &fpl->fp[fpl->count]; + +@@ -107,6 +108,10 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + *fpp++ = file; + fpl->count++; + } ++ ++ if (!fpl->user) ++ fpl->user = get_uid(current_user()); ++ + return num; + } + +@@ -119,6 +124,7 @@ void __scm_destroy(struct scm_cookie *scm) + scm->fp = NULL; + for (i=fpl->count-1; i>=0; i--) + fput(fpl->fp[i]); ++ free_uid(fpl->user); + kfree(fpl); + } + } +@@ -336,6 +342,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) + for (i = 0; i < fpl->count; i++) + get_file(fpl->fp[i]); + new_fpl->max = new_fpl->count; ++ new_fpl->user = get_uid(fpl->user); + } + return new_fpl; + } +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 49d5093..29be035 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1496,7 +1496,7 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) + UNIXCB(skb).fp = NULL; + + for (i = scm->fp->count-1; i >= 0; i--) +- unix_notinflight(scm->fp->fp[i]); ++ unix_notinflight(scm->fp->user, scm->fp->fp[i]); + } + + static void unix_destruct_scm(struct sk_buff *skb) +@@ -1561,7 +1561,7 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + return -ENOMEM; + + for (i = scm->fp->count - 1; i >= 0; i--) +- unix_inflight(scm->fp->fp[i]); ++ unix_inflight(scm->fp->user, scm->fp->fp[i]); + return max_level; + } + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 8fcdc22..6a0d485 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -116,7 +116,7 @@ struct sock *unix_get_socket(struct file *filp) + * descriptor if it is for an AF_UNIX socket. + */ + +-void unix_inflight(struct file *fp) ++void unix_inflight(struct user_struct *user, struct file *fp) + { + struct sock *s = unix_get_socket(fp); + +@@ -133,11 +133,11 @@ void unix_inflight(struct file *fp) + } + unix_tot_inflight++; + } +- fp->f_cred->user->unix_inflight++; ++ user->unix_inflight++; + spin_unlock(&unix_gc_lock); + } + +-void unix_notinflight(struct file *fp) ++void unix_notinflight(struct user_struct *user, struct file *fp) + { + struct sock *s = unix_get_socket(fp); + +@@ -152,7 +152,7 @@ void unix_notinflight(struct file *fp) + list_del_init(&u->link); + unix_tot_inflight--; + } +- fp->f_cred->user->unix_inflight--; ++ user->unix_inflight--; + spin_unlock(&unix_gc_lock); + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-0196/0.patch b/Patches/Linux_CVEs/CVE-2014-0196/0.patch new file mode 100644 index 00000000..2b19f407 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-0196/0.patch @@ -0,0 +1,80 @@ +From 4291086b1f081b869c6d79e5b7441633dc3ace00 Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Sat, 3 May 2014 14:04:59 +0200 +Subject: [PATCH] n_tty: Fix n_tty_write crash when echoing in raw mode + +The tty atomic_write_lock does not provide an exclusion guarantee for +the tty driver if the termios settings are LECHO & !OPOST. And since +it is unexpected and not allowed to call TTY buffer helpers like +tty_insert_flip_string concurrently, this may lead to crashes when +concurrect writers call pty_write. In that case the following two +writers: +* the ECHOing from a workqueue and +* pty_write from the process +race and can overflow the corresponding TTY buffer like follows. + +If we look into tty_insert_flip_string_fixed_flag, there is: + int space = __tty_buffer_request_room(port, goal, flags); + struct tty_buffer *tb = port->buf.tail; + ... + memcpy(char_buf_ptr(tb, tb->used), chars, space); + ... + tb->used += space; + +so the race of the two can result in something like this: + A B +__tty_buffer_request_room + __tty_buffer_request_room +memcpy(buf(tb->used), ...) +tb->used += space; + memcpy(buf(tb->used), ...) ->BOOM + +B's memcpy is past the tty_buffer due to the previous A's tb->used +increment. + +Since the N_TTY line discipline input processing can output +concurrently with a tty write, obtain the N_TTY ldisc output_lock to +serialize echo output with normal tty writes. This ensures the tty +buffer helper tty_insert_flip_string is not called concurrently and +everything is fine. + +Note that this is nicely reproducible by an ordinary user using +forkpty and some setup around that (raw termios + ECHO). And it is +present in kernels at least after commit +d945cb9cce20ac7143c2de8d88b187f62db99bdc (pty: Rework the pty layer to +use the normal buffering logic) in 2.6.31-rc3. + +js: add more info to the commit log +js: switch to bool +js: lock unconditionally +js: lock only the tty->ops->write call + +References: CVE-2014-0196 +Reported-and-tested-by: Jiri Slaby +Signed-off-by: Peter Hurley +Signed-off-by: Jiri Slaby +Cc: Linus Torvalds +Cc: Alan Cox +Cc: +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_tty.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 41fe8a047d373..fe9d129c87351 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -2353,8 +2353,12 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, + if (tty->ops->flush_chars) + tty->ops->flush_chars(tty); + } else { ++ struct n_tty_data *ldata = tty->disc_data; ++ + while (nr > 0) { ++ mutex_lock(&ldata->output_lock); + c = tty->ops->write(tty, b, nr); ++ mutex_unlock(&ldata->output_lock); + if (c < 0) { + retval = c; + goto break_out; diff --git a/Patches/Linux_CVEs/CVE-2014-0196/1.patch b/Patches/Linux_CVEs/CVE-2014-0196/1.patch new file mode 100644 index 00000000..21d68bf3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-0196/1.patch @@ -0,0 +1,84 @@ +From 1e5099713cefc67aa562f6d8fe43444f41baf52d Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Sat, 3 May 2014 14:04:59 +0200 +Subject: n_tty: Fix n_tty_write crash when echoing in raw mode + +commit 4291086b1f081b869c6d79e5b7441633dc3ace00 upstream. + +The tty atomic_write_lock does not provide an exclusion guarantee for +the tty driver if the termios settings are LECHO & !OPOST. And since +it is unexpected and not allowed to call TTY buffer helpers like +tty_insert_flip_string concurrently, this may lead to crashes when +concurrect writers call pty_write. In that case the following two +writers: +* the ECHOing from a workqueue and +* pty_write from the process +race and can overflow the corresponding TTY buffer like follows. + +If we look into tty_insert_flip_string_fixed_flag, there is: + int space = __tty_buffer_request_room(port, goal, flags); + struct tty_buffer *tb = port->buf.tail; + ... + memcpy(char_buf_ptr(tb, tb->used), chars, space); + ... + tb->used += space; + +so the race of the two can result in something like this: + A B +__tty_buffer_request_room + __tty_buffer_request_room +memcpy(buf(tb->used), ...) +tb->used += space; + memcpy(buf(tb->used), ...) ->BOOM + +B's memcpy is past the tty_buffer due to the previous A's tb->used +increment. + +Since the N_TTY line discipline input processing can output +concurrently with a tty write, obtain the N_TTY ldisc output_lock to +serialize echo output with normal tty writes. This ensures the tty +buffer helper tty_insert_flip_string is not called concurrently and +everything is fine. + +Note that this is nicely reproducible by an ordinary user using +forkpty and some setup around that (raw termios + ECHO). And it is +present in kernels at least after commit +d945cb9cce20ac7143c2de8d88b187f62db99bdc (pty: Rework the pty layer to +use the normal buffering logic) in 2.6.31-rc3. + +js: add more info to the commit log +js: switch to bool +js: lock unconditionally +js: lock only the tty->ops->write call + +References: CVE-2014-0196 +Reported-and-tested-by: Jiri Slaby +Signed-off-by: Peter Hurley +Signed-off-by: Jiri Slaby +Cc: Linus Torvalds +Cc: Alan Cox +Cc: +Signed-off-by: Greg Kroah-Hartman +[bwh: Backported to 3.2: output_lock is a member of struct tty_struct] +Signed-off-by: Ben Hutchings +--- + drivers/tty/n_tty.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 0f8a785..bac83d8 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -1997,7 +1997,9 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, + tty->ops->flush_chars(tty); + } else { + while (nr > 0) { ++ mutex_lock(&tty->output_lock); + c = tty->ops->write(tty, b, nr); ++ mutex_unlock(&tty->output_lock); + if (c < 0) { + retval = c; + goto break_out; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-0196/2.patch b/Patches/Linux_CVEs/CVE-2014-0196/2.patch new file mode 100644 index 00000000..b7c78569 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-0196/2.patch @@ -0,0 +1,83 @@ +From 9aabfc9e7775abbbcf534cdecccc4f12ee423b27 Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Tue, 13 May 2014 14:36:46 -0700 +Subject: n_tty: Fix n_tty_write crash when echoing in raw mode + +The tty atomic_write_lock does not provide an exclusion guarantee for +the tty driver if the termios settings are LECHO & !OPOST. And since +it is unexpected and not allowed to call TTY buffer helpers like +tty_insert_flip_string concurrently, this may lead to crashes when +concurrect writers call pty_write. In that case the following two +writers: +* the ECHOing from a workqueue and +* pty_write from the process +race and can overflow the corresponding TTY buffer like follows. + +If we look into tty_insert_flip_string_fixed_flag, there is: + int space = __tty_buffer_request_room(port, goal, flags); + struct tty_buffer *tb = port->buf.tail; + ... + memcpy(char_buf_ptr(tb, tb->used), chars, space); + ... + tb->used += space; + +so the race of the two can result in something like this: + A B + __tty_buffer_request_room + __tty_buffer_request_room + memcpy(buf(tb->used), ...) + tb->used += space; + memcpy(buf(tb->used), ...) ->BOOM + +B's memcpy is past the tty_buffer due to the previous A's tb->used +increment. + +Since the N_TTY line discipline input processing can output +concurrently with a tty write, obtain the N_TTY ldisc output_lock to +serialize echo output with normal tty writes. This ensures the tty +buffer helper tty_insert_flip_string is not called concurrently and +everything is fine. + +Note that this is nicely reproducible by an ordinary user using +forkpty and some setup around that (raw termios + ECHO). And it is +present in kernels at least after commit +d945cb9cce20ac7143c2de8d88b187f62db99bdc (pty: Rework the pty layer to +use the normal buffering logic) in 2.6.31-rc3. + +js: add more info to the commit log +js: switch to bool +js: lock unconditionally +js: lock only the tty->ops->write call + +Signed-off-by: Peter Hurley +Signed-off-by: Jiri Slaby +Signed-off-by: Greg Kroah-Hartman +Change-Id: I9e235db6ec2bb950f26bd8a23f6145dab5dc0a15 +Git-commit: 4291086b1f081b869c6d79e5b7441633dc3ace00 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git +Signed-off-by: Avijit Kanti Das +[rsiddoji@codeaurora.org: resolve trivial merge conflicts] +Signed-off-by: Ravi Kumar S +--- + drivers/tty/n_tty.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 8eb5573..54c46c8 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -1998,8 +1998,11 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, + if (tty->ops->flush_chars) + tty->ops->flush_chars(tty); + } else { ++ + while (nr > 0) { ++ mutex_lock(&tty->output_lock); + c = tty->ops->write(tty, b, nr); ++ mutex_unlock(&tty->output_lock); + if (c < 0) { + retval = c; + goto break_out; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-0206/0.patch b/Patches/Linux_CVEs/CVE-2014-0206/0.patch new file mode 100644 index 00000000..7c80276a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-0206/0.patch @@ -0,0 +1,45 @@ +From d36db46c2cba973557eb6138d22210c4e0cf17d6 Mon Sep 17 00:00:00 2001 +From: Benjamin LaHaise +Date: Tue, 24 Jun 2014 13:32:51 -0400 +Subject: aio: fix kernel memory disclosure in io_getevents() introduced in + v3.10 + +commit edfbbf388f293d70bf4b7c0bc38774d05e6f711a upstream. + +A kernel memory disclosure was introduced in aio_read_events_ring() in v3.10 +by commit a31ad380bed817aa25f8830ad23e1a0480fef797. The changes made to +aio_read_events_ring() failed to correctly limit the index into +ctx->ring_pages[], allowing an attacked to cause the subsequent kmap() of +an arbitrary page with a copy_to_user() to copy the contents into userspace. +This vulnerability has been assigned CVE-2014-0206. Thanks to Mateusz and +Petr for disclosing this issue. + +This patch applies to v3.12+. A separate backport is needed for 3.10/3.11. + +[jmoyer@redhat.com: backported to 3.10] +Signed-off-by: Benjamin LaHaise +Signed-off-by: Jeff Moyer +Cc: Mateusz Guzik +Cc: Petr Matousek +Cc: Kent Overstreet +Signed-off-by: Greg Kroah-Hartman +--- + fs/aio.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/aio.c b/fs/aio.c +index 8d2c997..ded94c4 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -717,6 +717,8 @@ static long aio_read_events_ring(struct kioctx *ctx, + if (head == ctx->tail) + goto out; + ++ head %= ctx->nr_events; ++ + while (ret < nr) { + long avail; + struct io_event *ev; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-1739/0.patch b/Patches/Linux_CVEs/CVE-2014-1739/0.patch new file mode 100644 index 00000000..58b14f95 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-1739/0.patch @@ -0,0 +1,33 @@ +From e6a623460e5fc960ac3ee9f946d3106233fd28d8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Salva=20Peir=C3=B3?= +Date: Wed, 30 Apr 2014 19:48:02 +0200 +Subject: [media] media-device: fix infoleak in ioctl media_enum_entities() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes CVE-2014-1739. + +Signed-off-by: Salva Peiró +Acked-by: Laurent Pinchart +Cc: stable@vger.kernel.org +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/media-device.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c +index d5a7a13..703560f 100644 +--- a/drivers/media/media-device.c ++++ b/drivers/media/media-device.c +@@ -93,6 +93,7 @@ static long media_device_enum_entities(struct media_device *mdev, + struct media_entity *ent; + struct media_entity_desc u_ent; + ++ memset(&u_ent, 0, sizeof(u_ent)); + if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id))) + return -EFAULT; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-2523/0.patch b/Patches/Linux_CVEs/CVE-2014-2523/0.patch new file mode 100644 index 00000000..f319b8d5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-2523/0.patch @@ -0,0 +1,59 @@ +From b22f5126a24b3b2f15448c3f2a254fc10cbc2b92 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Mon, 6 Jan 2014 00:57:54 +0100 +Subject: [PATCH] netfilter: nf_conntrack_dccp: fix skb_header_pointer API + usages + +Some occurences in the netfilter tree use skb_header_pointer() in +the following way ... + + struct dccp_hdr _dh, *dh; + ... + skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); + +... where dh itself is a pointer that is being passed as the copy +buffer. Instead, we need to use &_dh as the forth argument so that +we're copying the data into an actual buffer that sits on the stack. + +Currently, we probably could overwrite memory on the stack (e.g. +with a possibly mal-formed DCCP packet), but unintentionally, as +we only want the buffer to be placed into _dh variable. + +Fixes: 2bc780499aa3 ("[NETFILTER]: nf_conntrack: add DCCP protocol support") +Signed-off-by: Daniel Borkmann +Signed-off-by: Pablo Neira Ayuso +--- + net/netfilter/nf_conntrack_proto_dccp.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c +index 38412684a8824..cb372f96f10dc 100644 +--- a/net/netfilter/nf_conntrack_proto_dccp.c ++++ b/net/netfilter/nf_conntrack_proto_dccp.c +@@ -428,7 +428,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, + const char *msg; + u_int8_t state; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + BUG_ON(dh == NULL); + + state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; +@@ -486,7 +486,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, + u_int8_t type, old_state, new_state; + enum ct_dccp_roles role; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + BUG_ON(dh == NULL); + type = dh->dccph_type; + +@@ -577,7 +577,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, + unsigned int cscov; + const char *msg; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + if (dh == NULL) { + msg = "nf_ct_dccp: short packet "; + goto out_invalid; diff --git a/Patches/Linux_CVEs/CVE-2014-2523/1.patch b/Patches/Linux_CVEs/CVE-2014-2523/1.patch new file mode 100644 index 00000000..9e63ea71 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-2523/1.patch @@ -0,0 +1,64 @@ +From 5b866eaa34e4ddc312c927030fde5f6a6184ddc5 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Mon, 6 Jan 2014 00:57:54 +0100 +Subject: netfilter: nf_conntrack_dccp: fix skb_header_pointer API usages + +commit b22f5126a24b3b2f15448c3f2a254fc10cbc2b92 upstream. + +Some occurences in the netfilter tree use skb_header_pointer() in +the following way ... + + struct dccp_hdr _dh, *dh; + ... + skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); + +... where dh itself is a pointer that is being passed as the copy +buffer. Instead, we need to use &_dh as the forth argument so that +we're copying the data into an actual buffer that sits on the stack. + +Currently, we probably could overwrite memory on the stack (e.g. +with a possibly mal-formed DCCP packet), but unintentionally, as +we only want the buffer to be placed into _dh variable. + +Fixes: 2bc780499aa3 ("[NETFILTER]: nf_conntrack: add DCCP protocol support") +Signed-off-by: Daniel Borkmann +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Ben Hutchings +--- + net/netfilter/nf_conntrack_proto_dccp.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c +index 2e664a6..8aa94ee 100644 +--- a/net/netfilter/nf_conntrack_proto_dccp.c ++++ b/net/netfilter/nf_conntrack_proto_dccp.c +@@ -431,7 +431,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, + const char *msg; + u_int8_t state; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + BUG_ON(dh == NULL); + + state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; +@@ -483,7 +483,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, + u_int8_t type, old_state, new_state; + enum ct_dccp_roles role; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + BUG_ON(dh == NULL); + type = dh->dccph_type; + +@@ -575,7 +575,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, + unsigned int cscov; + const char *msg; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + if (dh == NULL) { + msg = "nf_ct_dccp: short packet "; + goto out_invalid; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-2706/0.patch b/Patches/Linux_CVEs/CVE-2014-2706/0.patch new file mode 100644 index 00000000..9ae44f32 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-2706/0.patch @@ -0,0 +1,160 @@ +From 1d147bfa64293b2723c4fec50922168658e613ba Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Thu, 20 Feb 2014 09:22:11 +0200 +Subject: mac80211: fix AP powersave TX vs. wakeup race + +There is a race between the TX path and the STA wakeup: while +a station is sleeping, mac80211 buffers frames until it wakes +up, then the frames are transmitted. However, the RX and TX +path are concurrent, so the packet indicating wakeup can be +processed while a packet is being transmitted. + +This can lead to a situation where the buffered frames list +is emptied on the one side, while a frame is being added on +the other side, as the station is still seen as sleeping in +the TX path. + +As a result, the newly added frame will not be send anytime +soon. It might be sent much later (and out of order) when the +station goes to sleep and wakes up the next time. + +Additionally, it can lead to the crash below. + +Fix all this by synchronising both paths with a new lock. +Both path are not fastpath since they handle PS situations. + +In a later patch we'll remove the extra skb queue locks to +reduce locking overhead. + +BUG: unable to handle kernel +NULL pointer dereference at 000000b0 +IP: [] ieee80211_report_used_skb+0x11/0x3e0 [mac80211] +*pde = 00000000 +Oops: 0000 [#1] SMP DEBUG_PAGEALLOC +EIP: 0060:[] EFLAGS: 00210282 CPU: 1 +EIP is at ieee80211_report_used_skb+0x11/0x3e0 [mac80211] +EAX: e5900da0 EBX: 00000000 ECX: 00000001 EDX: 00000000 +ESI: e41d00c0 EDI: e5900da0 EBP: ebe458e4 ESP: ebe458b0 + DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 +CR0: 8005003b CR2: 000000b0 CR3: 25a78000 CR4: 000407d0 +DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 +DR6: ffff0ff0 DR7: 00000400 +Process iperf (pid: 3934, ti=ebe44000 task=e757c0b0 task.ti=ebe44000) +iwlwifi 0000:02:00.0: I iwl_pcie_enqueue_hcmd Sending command LQ_CMD (#4e), seq: 0x0903, 92 bytes at 3[3]:9 +Stack: + e403b32c ebe458c4 00200002 00200286 e403b338 ebe458cc c10960bb e5900da0 + ff76a6ec ebe458d8 00000000 e41d00c0 e5900da0 ebe458f0 ff6f1b75 e403b210 + ebe4598c ff723dc1 00000000 ff76a6ec e597c978 e403b758 00000002 00000002 +Call Trace: + [] ieee80211_free_txskb+0x15/0x20 [mac80211] + [] invoke_tx_handlers+0x1661/0x1780 [mac80211] + [] ieee80211_tx+0x75/0x100 [mac80211] + [] ieee80211_xmit+0x8f/0xc0 [mac80211] + [] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211] + [] dev_hard_start_xmit+0x450/0x950 + [] sch_direct_xmit+0xa9/0x250 + [] __qdisc_run+0x4b/0x150 + [] dev_queue_xmit+0x2c2/0xca0 + +Cc: stable@vger.kernel.org +Reported-by: Yaara Rozenblum +Signed-off-by: Emmanuel Grumbach +Reviewed-by: Stanislaw Gruszka +[reword commit log, use a separate lock] +Signed-off-by: Johannes Berg +--- + net/mac80211/sta_info.c | 4 ++++ + net/mac80211/sta_info.h | 7 +++---- + net/mac80211/tx.c | 15 +++++++++++++++ + 3 files changed, 22 insertions(+), 4 deletions(-) + +diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c +index decd30c..62a5f08 100644 +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -330,6 +330,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, + rcu_read_unlock(); + + spin_lock_init(&sta->lock); ++ spin_lock_init(&sta->ps_lock); + INIT_WORK(&sta->drv_unblock_wk, sta_unblock); + INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); + mutex_init(&sta->ampdu_mlme.mtx); +@@ -1109,6 +1110,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) + + skb_queue_head_init(&pending); + ++ /* sync with ieee80211_tx_h_unicast_ps_buf */ ++ spin_lock(&sta->ps_lock); + /* Send all buffered frames to the station */ + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + int count = skb_queue_len(&pending), tmp; +@@ -1128,6 +1131,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) + } + + ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta); ++ spin_unlock(&sta->ps_lock); + + /* This station just woke up and isn't aware of our SMPS state */ + if (!ieee80211_smps_is_restrictive(sta->known_smps_mode, +diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h +index d77ff70..d3a6d82 100644 +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat { + * @drv_unblock_wk: used for driver PS unblocking + * @listen_interval: listen interval of this station, when we're acting as AP + * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly ++ * @ps_lock: used for powersave (when mac80211 is the AP) related locking + * @ps_tx_buf: buffers (per AC) of frames to transmit to this station + * when it leaves power saving state or polls + * @tx_filtered: buffers (per AC) of frames we already tried to +@@ -356,10 +357,8 @@ struct sta_info { + /* use the accessors defined below */ + unsigned long _flags; + +- /* +- * STA powersave frame queues, no more than the internal +- * locking required. +- */ ++ /* STA powersave lock and frame queues */ ++ spinlock_t ps_lock; + struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; + struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; + unsigned long driver_buffered_tids; +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 97a02d3..4080c61 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -478,6 +478,20 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + sta->sta.addr, sta->sta.aid, ac); + if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) + purge_old_ps_buffers(tx->local); ++ ++ /* sync with ieee80211_sta_ps_deliver_wakeup */ ++ spin_lock(&sta->ps_lock); ++ /* ++ * STA woke up the meantime and all the frames on ps_tx_buf have ++ * been queued to pending queue. No reordering can happen, go ++ * ahead and Tx the packet. ++ */ ++ if (!test_sta_flag(sta, WLAN_STA_PS_STA) && ++ !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { ++ spin_unlock(&sta->ps_lock); ++ return TX_CONTINUE; ++ } ++ + if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) { + struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]); + ps_dbg(tx->sdata, +@@ -492,6 +506,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; + info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; + skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb); ++ spin_unlock(&sta->ps_lock); + + if (!timer_pending(&local->sta_cleanup)) + mod_timer(&local->sta_cleanup, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-2851/0.patch b/Patches/Linux_CVEs/CVE-2014-2851/0.patch new file mode 100644 index 00000000..a954b65f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-2851/0.patch @@ -0,0 +1,64 @@ +From b04c46190219a4f845e46a459e3102137b7f6cac Mon Sep 17 00:00:00 2001 +From: "Wang, Xiaoming" +Date: Mon, 14 Apr 2014 12:30:45 -0400 +Subject: net: ipv4: current group_info should be put after using. + +Plug a group_info refcount leak in ping_init. +group_info is only needed during initialization and +the code failed to release the reference on exit. +While here move grabbing the reference to a place +where it is actually needed. + +Signed-off-by: Chuansheng Liu +Signed-off-by: Zhang Dongxing +Signed-off-by: xiaoming wang +Signed-off-by: David S. Miller +--- + net/ipv4/ping.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index f4b19e5..8210964 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -252,26 +252,33 @@ int ping_init_sock(struct sock *sk) + { + struct net *net = sock_net(sk); + kgid_t group = current_egid(); +- struct group_info *group_info = get_current_groups(); +- int i, j, count = group_info->ngroups; ++ struct group_info *group_info; ++ int i, j, count; + kgid_t low, high; ++ int ret = 0; + + inet_get_ping_group_range_net(net, &low, &high); + if (gid_lte(low, group) && gid_lte(group, high)) + return 0; + ++ group_info = get_current_groups(); ++ count = group_info->ngroups; + for (i = 0; i < group_info->nblocks; i++) { + int cp_count = min_t(int, NGROUPS_PER_BLOCK, count); + for (j = 0; j < cp_count; j++) { + kgid_t gid = group_info->blocks[i][j]; + if (gid_lte(low, gid) && gid_lte(gid, high)) +- return 0; ++ goto out_release_group; + } + + count -= cp_count; + } + +- return -EACCES; ++ ret = -EACCES; ++ ++out_release_group: ++ put_group_info(group_info); ++ return ret; + } + EXPORT_SYMBOL_GPL(ping_init_sock); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-3145/0.patch b/Patches/Linux_CVEs/CVE-2014-3145/0.patch new file mode 100644 index 00000000..3e4a0227 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-3145/0.patch @@ -0,0 +1,90 @@ +From 05ab8f2647e4221cbdb3856dd7d32bd5407316b3 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 13 Apr 2014 18:23:33 +0200 +Subject: filter: prevent nla extensions to peek beyond the end of the message + +The BPF_S_ANC_NLATTR and BPF_S_ANC_NLATTR_NEST extensions fail to check +for a minimal message length before testing the supplied offset to be +within the bounds of the message. This allows the subtraction of the nla +header to underflow and therefore -- as the data type is unsigned -- +allowing far to big offset and length values for the search of the +netlink attribute. + +The remainder calculation for the BPF_S_ANC_NLATTR_NEST extension is +also wrong. It has the minuend and subtrahend mixed up, therefore +calculates a huge length value, allowing to overrun the end of the +message while looking for the netlink attribute. + +The following three BPF snippets will trigger the bugs when attached to +a UNIX datagram socket and parsing a message with length 1, 2 or 3. + + ,-[ PoC for missing size check in BPF_S_ANC_NLATTR ]-- + | ld #0x87654321 + | ldx #42 + | ld #nla + | ret a + `--- + + ,-[ PoC for the same bug in BPF_S_ANC_NLATTR_NEST ]-- + | ld #0x87654321 + | ldx #42 + | ld #nlan + | ret a + `--- + + ,-[ PoC for wrong remainder calculation in BPF_S_ANC_NLATTR_NEST ]-- + | ; (needs a fake netlink header at offset 0) + | ld #0 + | ldx #42 + | ld #nlan + | ret a + `--- + +Fix the first issue by ensuring the message length fulfills the minimal +size constrains of a nla header. Fix the second bug by getting the math +for the remainder calculation right. + +Fixes: 4738c1db15 ("[SKFILTER]: Add SKF_ADF_NLATTR instruction") +Fixes: d214c7537b ("filter: add SKF_AD_NLATTR_NEST to look for nested..") +Cc: Patrick McHardy +Cc: Pablo Neira Ayuso +Signed-off-by: Mathias Krause +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +--- + net/core/filter.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index e08b382..0e0856f 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -600,6 +600,9 @@ static u64 __skb_get_nlattr(u64 ctx, u64 A, u64 X, u64 r4, u64 r5) + if (skb_is_nonlinear(skb)) + return 0; + ++ if (skb->len < sizeof(struct nlattr)) ++ return 0; ++ + if (A > skb->len - sizeof(struct nlattr)) + return 0; + +@@ -618,11 +621,14 @@ static u64 __skb_get_nlattr_nest(u64 ctx, u64 A, u64 X, u64 r4, u64 r5) + if (skb_is_nonlinear(skb)) + return 0; + ++ if (skb->len < sizeof(struct nlattr)) ++ return 0; ++ + if (A > skb->len - sizeof(struct nlattr)) + return 0; + + nla = (struct nlattr *) &skb->data[A]; +- if (nla->nla_len > A - skb->len) ++ if (nla->nla_len > skb->len - A) + return 0; + + nla = nla_find_nested(nla, X); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-3145/1.patch b/Patches/Linux_CVEs/CVE-2014-3145/1.patch new file mode 100644 index 00000000..789a053c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-3145/1.patch @@ -0,0 +1,91 @@ +From 314760e66c35c8ffa51b4c4ca6948d207e783079 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 13 Apr 2014 18:23:33 +0200 +Subject: filter: prevent nla extensions to peek beyond the end of the message + +[ Upstream commit 05ab8f2647e4221cbdb3856dd7d32bd5407316b3 ] + +The BPF_S_ANC_NLATTR and BPF_S_ANC_NLATTR_NEST extensions fail to check +for a minimal message length before testing the supplied offset to be +within the bounds of the message. This allows the subtraction of the nla +header to underflow and therefore -- as the data type is unsigned -- +allowing far to big offset and length values for the search of the +netlink attribute. + +The remainder calculation for the BPF_S_ANC_NLATTR_NEST extension is +also wrong. It has the minuend and subtrahend mixed up, therefore +calculates a huge length value, allowing to overrun the end of the +message while looking for the netlink attribute. + +The following three BPF snippets will trigger the bugs when attached to +a UNIX datagram socket and parsing a message with length 1, 2 or 3. + + ,-[ PoC for missing size check in BPF_S_ANC_NLATTR ]-- + | ld #0x87654321 + | ldx #42 + | ld #nla + | ret a + `--- + + ,-[ PoC for the same bug in BPF_S_ANC_NLATTR_NEST ]-- + | ld #0x87654321 + | ldx #42 + | ld #nlan + | ret a + `--- + + ,-[ PoC for wrong remainder calculation in BPF_S_ANC_NLATTR_NEST ]-- + | ; (needs a fake netlink header at offset 0) + | ld #0 + | ldx #42 + | ld #nlan + | ret a + `--- + +Fix the first issue by ensuring the message length fulfills the minimal +size constrains of a nla header. Fix the second bug by getting the math +for the remainder calculation right. + +Fixes: 4738c1db15 ("[SKFILTER]: Add SKF_ADF_NLATTR instruction") +Fixes: d214c7537b ("filter: add SKF_AD_NLATTR_NEST to look for nested..") +Cc: Patrick McHardy +Cc: Pablo Neira Ayuso +Signed-off-by: Mathias Krause +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/filter.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index 52f01229..c6c18d8 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -355,6 +355,8 @@ load_b: + + if (skb_is_nonlinear(skb)) + return 0; ++ if (skb->len < sizeof(struct nlattr)) ++ return 0; + if (A > skb->len - sizeof(struct nlattr)) + return 0; + +@@ -371,11 +373,13 @@ load_b: + + if (skb_is_nonlinear(skb)) + return 0; ++ if (skb->len < sizeof(struct nlattr)) ++ return 0; + if (A > skb->len - sizeof(struct nlattr)) + return 0; + + nla = (struct nlattr *)&skb->data[A]; +- if (nla->nla_len > A - skb->len) ++ if (nla->nla_len > skb->len - A) + return 0; + + nla = nla_find_nested(nla, X); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-3145/2.patch b/Patches/Linux_CVEs/CVE-2014-3145/2.patch new file mode 100644 index 00000000..c3660802 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-3145/2.patch @@ -0,0 +1,92 @@ +From d41eb74e53d94aba656ffda647d106808e636cd6 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Sun, 13 Apr 2014 18:23:33 +0200 +Subject: filter: prevent nla extensions to peek beyond the end of the message + +[ Upstream commit 05ab8f2647e4221cbdb3856dd7d32bd5407316b3 ] + +The BPF_S_ANC_NLATTR and BPF_S_ANC_NLATTR_NEST extensions fail to check +for a minimal message length before testing the supplied offset to be +within the bounds of the message. This allows the subtraction of the nla +header to underflow and therefore -- as the data type is unsigned -- +allowing far to big offset and length values for the search of the +netlink attribute. + +The remainder calculation for the BPF_S_ANC_NLATTR_NEST extension is +also wrong. It has the minuend and subtrahend mixed up, therefore +calculates a huge length value, allowing to overrun the end of the +message while looking for the netlink attribute. + +The following three BPF snippets will trigger the bugs when attached to +a UNIX datagram socket and parsing a message with length 1, 2 or 3. + + ,-[ PoC for missing size check in BPF_S_ANC_NLATTR ]-- + | ld #0x87654321 + | ldx #42 + | ld #nla + | ret a + `--- + + ,-[ PoC for the same bug in BPF_S_ANC_NLATTR_NEST ]-- + | ld #0x87654321 + | ldx #42 + | ld #nlan + | ret a + `--- + + ,-[ PoC for wrong remainder calculation in BPF_S_ANC_NLATTR_NEST ]-- + | ; (needs a fake netlink header at offset 0) + | ld #0 + | ldx #42 + | ld #nlan + | ret a + `--- + +Fix the first issue by ensuring the message length fulfills the minimal +size constrains of a nla header. Fix the second bug by getting the math +for the remainder calculation right. + +Fixes: 4738c1db15 ("[SKFILTER]: Add SKF_ADF_NLATTR instruction") +Fixes: d214c7537b ("filter: add SKF_AD_NLATTR_NEST to look for nested..") +Cc: Patrick McHardy +Cc: Pablo Neira Ayuso +Signed-off-by: Mathias Krause +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +[bwh: Fix misplacement of the first check due to a bug in the patch program] +Signed-off-by: Ben Hutchings +--- + net/core/filter.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index 5dea452..9c88080 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -320,6 +320,8 @@ load_b: + + if (skb_is_nonlinear(skb)) + return 0; ++ if (skb->len < sizeof(struct nlattr)) ++ return 0; + if (A > skb->len - sizeof(struct nlattr)) + return 0; + +@@ -336,11 +338,13 @@ load_b: + + if (skb_is_nonlinear(skb)) + return 0; ++ if (skb->len < sizeof(struct nlattr)) ++ return 0; + if (A > skb->len - sizeof(struct nlattr)) + return 0; + + nla = (struct nlattr *)&skb->data[A]; +- if (nla->nla_len > A - skb->len) ++ if (nla->nla_len > skb->len - A) + return 0; + + nla = nla_find_nested(nla, X); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-4014/0.patch b/Patches/Linux_CVEs/CVE-2014-4014/0.patch new file mode 100644 index 00000000..288e918c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4014/0.patch @@ -0,0 +1,206 @@ +From 23adbe12ef7d3d4195e80800ab36b37bee28cd03 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Tue, 10 Jun 2014 12:45:42 -0700 +Subject: fs,userns: Change inode_capable to capable_wrt_inode_uidgid + +The kernel has no concept of capabilities with respect to inodes; inodes +exist independently of namespaces. For example, inode_capable(inode, +CAP_LINUX_IMMUTABLE) would be nonsense. + +This patch changes inode_capable to check for uid and gid mappings and +renames it to capable_wrt_inode_uidgid, which should make it more +obvious what it does. + +Fixes CVE-2014-4014. + +Cc: Theodore Ts'o +Cc: Serge Hallyn +Cc: "Eric W. Biederman" +Cc: Dave Chinner +Cc: stable@vger.kernel.org +Signed-off-by: Andy Lutomirski +Signed-off-by: Linus Torvalds +--- + fs/attr.c | 8 ++++---- + fs/inode.c | 10 +++++++--- + fs/namei.c | 11 ++++++----- + fs/xfs/xfs_ioctl.c | 2 +- + include/linux/capability.h | 2 +- + kernel/capability.c | 20 ++++++++------------ + 6 files changed, 27 insertions(+), 26 deletions(-) + +diff --git a/fs/attr.c b/fs/attr.c +index 5d4e59d..6530ced 100644 +--- a/fs/attr.c ++++ b/fs/attr.c +@@ -50,14 +50,14 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) + if ((ia_valid & ATTR_UID) && + (!uid_eq(current_fsuid(), inode->i_uid) || + !uid_eq(attr->ia_uid, inode->i_uid)) && +- !inode_capable(inode, CAP_CHOWN)) ++ !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) + return -EPERM; + + /* Make sure caller can chgrp. */ + if ((ia_valid & ATTR_GID) && + (!uid_eq(current_fsuid(), inode->i_uid) || + (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) && +- !inode_capable(inode, CAP_CHOWN)) ++ !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) + return -EPERM; + + /* Make sure a caller can chmod. */ +@@ -67,7 +67,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) + /* Also check the setgid bit! */ + if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : + inode->i_gid) && +- !inode_capable(inode, CAP_FSETID)) ++ !capable_wrt_inode_uidgid(inode, CAP_FSETID)) + attr->ia_mode &= ~S_ISGID; + } + +@@ -160,7 +160,7 @@ void setattr_copy(struct inode *inode, const struct iattr *attr) + umode_t mode = attr->ia_mode; + + if (!in_group_p(inode->i_gid) && +- !inode_capable(inode, CAP_FSETID)) ++ !capable_wrt_inode_uidgid(inode, CAP_FSETID)) + mode &= ~S_ISGID; + inode->i_mode = mode; + } +diff --git a/fs/inode.c b/fs/inode.c +index 2feb9b6..6eecb7f 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1839,14 +1839,18 @@ EXPORT_SYMBOL(inode_init_owner); + * inode_owner_or_capable - check current task permissions to inode + * @inode: inode being checked + * +- * Return true if current either has CAP_FOWNER to the inode, or +- * owns the file. ++ * Return true if current either has CAP_FOWNER in a namespace with the ++ * inode owner uid mapped, or owns the file. + */ + bool inode_owner_or_capable(const struct inode *inode) + { ++ struct user_namespace *ns; ++ + if (uid_eq(current_fsuid(), inode->i_uid)) + return true; +- if (inode_capable(inode, CAP_FOWNER)) ++ ++ ns = current_user_ns(); ++ if (ns_capable(ns, CAP_FOWNER) && kuid_has_mapping(ns, inode->i_uid)) + return true; + return false; + } +diff --git a/fs/namei.c b/fs/namei.c +index 8016827..985c6f3 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -332,10 +332,11 @@ int generic_permission(struct inode *inode, int mask) + + if (S_ISDIR(inode->i_mode)) { + /* DACs are overridable for directories */ +- if (inode_capable(inode, CAP_DAC_OVERRIDE)) ++ if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE)) + return 0; + if (!(mask & MAY_WRITE)) +- if (inode_capable(inode, CAP_DAC_READ_SEARCH)) ++ if (capable_wrt_inode_uidgid(inode, ++ CAP_DAC_READ_SEARCH)) + return 0; + return -EACCES; + } +@@ -345,7 +346,7 @@ int generic_permission(struct inode *inode, int mask) + * at least one exec bit set. + */ + if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO)) +- if (inode_capable(inode, CAP_DAC_OVERRIDE)) ++ if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE)) + return 0; + + /* +@@ -353,7 +354,7 @@ int generic_permission(struct inode *inode, int mask) + */ + mask &= MAY_READ | MAY_WRITE | MAY_EXEC; + if (mask == MAY_READ) +- if (inode_capable(inode, CAP_DAC_READ_SEARCH)) ++ if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH)) + return 0; + + return -EACCES; +@@ -2379,7 +2380,7 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) + return 0; + if (uid_eq(dir->i_uid, fsuid)) + return 0; +- return !inode_capable(inode, CAP_FOWNER); ++ return !capable_wrt_inode_uidgid(inode, CAP_FOWNER); + } + + /* +diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c +index 0b18776..6152cbe 100644 +--- a/fs/xfs/xfs_ioctl.c ++++ b/fs/xfs/xfs_ioctl.c +@@ -1215,7 +1215,7 @@ xfs_ioctl_setattr( + * cleared upon successful return from chown() + */ + if ((ip->i_d.di_mode & (S_ISUID|S_ISGID)) && +- !inode_capable(VFS_I(ip), CAP_FSETID)) ++ !capable_wrt_inode_uidgid(VFS_I(ip), CAP_FSETID)) + ip->i_d.di_mode &= ~(S_ISUID|S_ISGID); + + /* +diff --git a/include/linux/capability.h b/include/linux/capability.h +index a6ee1f9..84b13ad 100644 +--- a/include/linux/capability.h ++++ b/include/linux/capability.h +@@ -210,7 +210,7 @@ extern bool has_ns_capability_noaudit(struct task_struct *t, + struct user_namespace *ns, int cap); + extern bool capable(int cap); + extern bool ns_capable(struct user_namespace *ns, int cap); +-extern bool inode_capable(const struct inode *inode, int cap); ++extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap); + extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); + + /* audit system wants to get cap info from files as well */ +diff --git a/kernel/capability.c b/kernel/capability.c +index 84b2bbf..a5cf13c 100644 +--- a/kernel/capability.c ++++ b/kernel/capability.c +@@ -424,23 +424,19 @@ bool capable(int cap) + EXPORT_SYMBOL(capable); + + /** +- * inode_capable - Check superior capability over inode ++ * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped + * @inode: The inode in question + * @cap: The capability in question + * +- * Return true if the current task has the given superior capability +- * targeted at it's own user namespace and that the given inode is owned +- * by the current user namespace or a child namespace. +- * +- * Currently we check to see if an inode is owned by the current +- * user namespace by seeing if the inode's owner maps into the +- * current user namespace. +- * ++ * Return true if the current task has the given capability targeted at ++ * its own user namespace and that the given inode's uid and gid are ++ * mapped into the current user namespace. + */ +-bool inode_capable(const struct inode *inode, int cap) ++bool capable_wrt_inode_uidgid(const struct inode *inode, int cap) + { + struct user_namespace *ns = current_user_ns(); + +- return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid); ++ return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) && ++ kgid_has_mapping(ns, inode->i_gid); + } +-EXPORT_SYMBOL(inode_capable); ++EXPORT_SYMBOL(capable_wrt_inode_uidgid); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-4323/0.patch b/Patches/Linux_CVEs/CVE-2014-4323/0.patch new file mode 100644 index 00000000..c68dbaf0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4323/0.patch @@ -0,0 +1,33 @@ +From 014fa8def84c62893fa016e873c12de1da498603 Mon Sep 17 00:00:00 2001 +From: raghavendra ambadas +Date: Mon, 6 Oct 2014 14:59:57 +0530 +Subject: msm: mdp: Validate input arguments from user space + +Fully verify the input arguments from user client are safe +to use. + +Change-Id: Ie14332443b187951009c63ebfb78456dcd9ba60f +Signed-off-by: Raghavendra Ambadas +--- + drivers/video/msm/mdp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c +index 4ede0b52..c00bd78 100644 +--- a/drivers/video/msm/mdp.c ++++ b/drivers/video/msm/mdp.c +@@ -485,6 +485,11 @@ static int mdp_lut_hw_update(struct fb_cmap *cmap) + c[1] = cmap->blue; + c[2] = cmap->red; + ++ if (cmap->start > MDP_HIST_LUT_SIZE || cmap->len > MDP_HIST_LUT_SIZE || ++ (cmap->start + cmap->len > MDP_HIST_LUT_SIZE)) { ++ pr_err("mdp_lut_hw_update invalid arguments\n"); ++ return -EINVAL; ++ } + for (i = 0; i < cmap->len; i++) { + if (copy_from_user(&r, cmap->red++, sizeof(r)) || + copy_from_user(&g, cmap->green++, sizeof(g)) || +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-4655/0.patch b/Patches/Linux_CVEs/CVE-2014-4655/0.patch new file mode 100644 index 00000000..14ca8e9d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4655/0.patch @@ -0,0 +1,85 @@ +From 82262a46627bebb0febcc26664746c25cef08563 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 18 Jun 2014 13:32:32 +0200 +Subject: [PATCH] ALSA: control: Fix replacing user controls + +There are two issues with the current implementation for replacing user +controls. The first is that the code does not check if the control is actually a +user control and neither does it check if the control is owned by the process +that tries to remove it. That allows userspace applications to remove arbitrary +controls, which can cause a user after free if a for example a driver does not +expect a control to be removed from under its feed. + +The second issue is that on one hand when a control is replaced the +user_ctl_count limit is not checked and on the other hand the user_ctl_count is +increased (even though the number of user controls does not change). This allows +userspace, once the user_ctl_count limit as been reached, to repeatedly replace +a control until user_ctl_count overflows. Once that happens new controls can be +added effectively bypassing the user_ctl_count limit. + +Both issues can be fixed by instead of open-coding the removal of the control +that is to be replaced to use snd_ctl_remove_user_ctl(). This function does +proper permission checks as well as decrements user_ctl_count after the control +has been removed. + +Note that by using snd_ctl_remove_user_ctl() the check which returns -EBUSY at +beginning of the function if the control already exists is removed. This is not +a problem though since the check is quite useless, because the lock that is +protecting the control list is released between the check and before adding the +new control to the list, which means that it is possible that a different +control with the same settings is added to the list after the check. Luckily +there is another check that is done while holding the lock in snd_ctl_add(), so +we'll rely on that to make sure that the same control is not added twice. + +Signed-off-by: Lars-Peter Clausen +Acked-by: Jaroslav Kysela +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/control.c | 25 +++++++++---------------- + 1 file changed, 9 insertions(+), 16 deletions(-) + +diff --git a/sound/core/control.c b/sound/core/control.c +index 00ab034f5fcbe..1f413c2865113 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -1154,8 +1154,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, + struct user_element *ue; + int idx, err; + +- if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS) +- return -ENOMEM; + if (info->count < 1) + return -EINVAL; + access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : +@@ -1164,21 +1162,16 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, + SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)); + info->id.numid = 0; + memset(&kctl, 0, sizeof(kctl)); +- down_write(&card->controls_rwsem); +- _kctl = snd_ctl_find_id(card, &info->id); +- err = 0; +- if (_kctl) { +- if (replace) +- err = snd_ctl_remove(card, _kctl); +- else +- err = -EBUSY; +- } else { +- if (replace) +- err = -ENOENT; ++ ++ if (replace) { ++ err = snd_ctl_remove_user_ctl(file, &info->id); ++ if (err) ++ return err; + } +- up_write(&card->controls_rwsem); +- if (err < 0) +- return err; ++ ++ if (card->user_ctl_count >= MAX_USER_CONTROLS) ++ return -ENOMEM; ++ + memcpy(&kctl.id, &info->id, sizeof(info->id)); + kctl.count = info->owner ? info->owner : 1; + access |= SNDRV_CTL_ELEM_ACCESS_USER; diff --git a/Patches/Linux_CVEs/CVE-2014-4655/1.patch b/Patches/Linux_CVEs/CVE-2014-4655/1.patch new file mode 100644 index 00000000..4628f39f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4655/1.patch @@ -0,0 +1,90 @@ +From 0e2e43eca302b31f64ebfe4734fd2cc7358c4555 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 18 Jun 2014 13:32:32 +0200 +Subject: ALSA: control: Fix replacing user controls + +commit 82262a46627bebb0febcc26664746c25cef08563 upstream. + +There are two issues with the current implementation for replacing user +controls. The first is that the code does not check if the control is actually a +user control and neither does it check if the control is owned by the process +that tries to remove it. That allows userspace applications to remove arbitrary +controls, which can cause a user after free if a for example a driver does not +expect a control to be removed from under its feed. + +The second issue is that on one hand when a control is replaced the +user_ctl_count limit is not checked and on the other hand the user_ctl_count is +increased (even though the number of user controls does not change). This allows +userspace, once the user_ctl_count limit as been reached, to repeatedly replace +a control until user_ctl_count overflows. Once that happens new controls can be +added effectively bypassing the user_ctl_count limit. + +Both issues can be fixed by instead of open-coding the removal of the control +that is to be replaced to use snd_ctl_remove_user_ctl(). This function does +proper permission checks as well as decrements user_ctl_count after the control +has been removed. + +Note that by using snd_ctl_remove_user_ctl() the check which returns -EBUSY at +beginning of the function if the control already exists is removed. This is not +a problem though since the check is quite useless, because the lock that is +protecting the control list is released between the check and before adding the +new control to the list, which means that it is possible that a different +control with the same settings is added to the list after the check. Luckily +there is another check that is done while holding the lock in snd_ctl_add(), so +we'll rely on that to make sure that the same control is not added twice. + +Signed-off-by: Lars-Peter Clausen +Acked-by: Jaroslav Kysela +Signed-off-by: Takashi Iwai +Signed-off-by: Ben Hutchings +--- + sound/core/control.c | 25 +++++++++---------------- + 1 file changed, 9 insertions(+), 16 deletions(-) + +diff --git a/sound/core/control.c b/sound/core/control.c +index 920ea56..caa949e 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -1151,8 +1151,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, + struct user_element *ue; + int idx, err; + +- if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS) +- return -ENOMEM; + if (info->count < 1) + return -EINVAL; + access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : +@@ -1161,21 +1159,16 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, + SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)); + info->id.numid = 0; + memset(&kctl, 0, sizeof(kctl)); +- down_write(&card->controls_rwsem); +- _kctl = snd_ctl_find_id(card, &info->id); +- err = 0; +- if (_kctl) { +- if (replace) +- err = snd_ctl_remove(card, _kctl); +- else +- err = -EBUSY; +- } else { +- if (replace) +- err = -ENOENT; ++ ++ if (replace) { ++ err = snd_ctl_remove_user_ctl(file, &info->id); ++ if (err) ++ return err; + } +- up_write(&card->controls_rwsem); +- if (err < 0) +- return err; ++ ++ if (card->user_ctl_count >= MAX_USER_CONTROLS) ++ return -ENOMEM; ++ + memcpy(&kctl.id, &info->id, sizeof(info->id)); + kctl.count = info->owner ? info->owner : 1; + access |= SNDRV_CTL_ELEM_ACCESS_USER; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-4655/2.patch b/Patches/Linux_CVEs/CVE-2014-4655/2.patch new file mode 100644 index 00000000..2b9602fb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4655/2.patch @@ -0,0 +1,27 @@ +From 08ede038a738f22c1b3425051175e1d627d8dd43 Mon Sep 17 00:00:00 2001 +From: Lu Guanqun +Date: Wed, 24 Aug 2011 14:45:10 +0800 +Subject: [PATCH] ALSA: core: release the constraint check for replace ops + +Suppose the ALSA card already has a number of MAX_USER_CONTROLS controls, and +the user wants to replace one, it should not fail at this condition check. + +Signed-off-by: Lu Guanqun +Signed-off-by: Takashi Iwai +--- + sound/core/control.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/core/control.c b/sound/core/control.c +index 7f2b3a7eabb2b..dc2a44048c850 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -1073,7 +1073,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, + struct user_element *ue; + int idx, err; + +- if (card->user_ctl_count >= MAX_USER_CONTROLS) ++ if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS) + return -ENOMEM; + if (info->count < 1) + return -EINVAL; diff --git a/Patches/Linux_CVEs/CVE-2014-4656/0.patch b/Patches/Linux_CVEs/CVE-2014-4656/0.patch new file mode 100644 index 00000000..416150ba --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4656/0.patch @@ -0,0 +1,37 @@ +From 883a1d49f0d77d30012f114b2e19fc141beb3e8e Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 18 Jun 2014 13:32:35 +0200 +Subject: ALSA: control: Make sure that id->index does not overflow + +The ALSA control code expects that the range of assigned indices to a control is +continuous and does not overflow. Currently there are no checks to enforce this. +If a control with a overflowing index range is created that control becomes +effectively inaccessible and unremovable since snd_ctl_find_id() will not be +able to find it. This patch adds a check that makes sure that controls with a +overflowing index range can not be created. + +Signed-off-by: Lars-Peter Clausen +Acked-by: Jaroslav Kysela +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/control.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/core/control.c b/sound/core/control.c +index 8d6e4ba..f0b0e14 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -342,6 +342,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) + if (snd_BUG_ON(!card || !kcontrol->info)) + goto error; + id = kcontrol->id; ++ if (id.index > UINT_MAX - kcontrol->count) ++ goto error; ++ + down_write(&card->controls_rwsem); + if (snd_ctl_find_id(card, &id)) { + up_write(&card->controls_rwsem); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-4656/1.patch b/Patches/Linux_CVEs/CVE-2014-4656/1.patch new file mode 100644 index 00000000..9cc4560c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4656/1.patch @@ -0,0 +1,39 @@ +From f7500568b7633324e7c4282bb8baa3ff3f17fd7a Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Wed, 18 Jun 2014 13:32:35 +0200 +Subject: ALSA: control: Make sure that id->index does not overflow + +commit 883a1d49f0d77d30012f114b2e19fc141beb3e8e upstream. + +The ALSA control code expects that the range of assigned indices to a control is +continuous and does not overflow. Currently there are no checks to enforce this. +If a control with a overflowing index range is created that control becomes +effectively inaccessible and unremovable since snd_ctl_find_id() will not be +able to find it. This patch adds a check that makes sure that controls with a +overflowing index range can not be created. + +Signed-off-by: Lars-Peter Clausen +Acked-by: Jaroslav Kysela +Signed-off-by: Takashi Iwai +Signed-off-by: Ben Hutchings +--- + sound/core/control.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/core/control.c b/sound/core/control.c +index d3f17de..9210594 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -341,6 +341,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) + if (snd_BUG_ON(!card || !kcontrol->info)) + goto error; + id = kcontrol->id; ++ if (id.index > UINT_MAX - kcontrol->count) ++ goto error; ++ + down_write(&card->controls_rwsem); + if (snd_ctl_find_id(card, &id)) { + up_write(&card->controls_rwsem); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-4943/0.patch b/Patches/Linux_CVEs/CVE-2014-4943/0.patch new file mode 100644 index 00000000..d1b4c1ef --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4943/0.patch @@ -0,0 +1,51 @@ +From 3cf521f7dc87c031617fd47e4b7aa2593c2f3daf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Jul 2014 17:02:31 -0700 +Subject: [PATCH] net/l2tp: don't fall back on UDP [get|set]sockopt + +The l2tp [get|set]sockopt() code has fallen back to the UDP functions +for socket option levels != SOL_PPPOL2TP since day one, but that has +never actually worked, since the l2tp socket isn't an inet socket. + +As David Miller points out: + + "If we wanted this to work, it'd have to look up the tunnel and then + use tunnel->sk, but I wonder how useful that would be" + +Since this can never have worked so nobody could possibly have depended +on that functionality, just remove the broken code and return -EINVAL. + +Reported-by: Sasha Levin +Acked-by: James Chapman +Acked-by: David Miller +Cc: Phil Turnbull +Cc: Vegard Nossum +Cc: Willy Tarreau +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +--- + net/l2tp/l2tp_ppp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 950909f04ee6a..13752d96275e8 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -1365,7 +1365,7 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, + int err; + + if (level != SOL_PPPOL2TP) +- return udp_prot.setsockopt(sk, level, optname, optval, optlen); ++ return -EINVAL; + + if (optlen < sizeof(int)) + return -EINVAL; +@@ -1491,7 +1491,7 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname, + struct pppol2tp_session *ps; + + if (level != SOL_PPPOL2TP) +- return udp_prot.getsockopt(sk, level, optname, optval, optlen); ++ return -EINVAL; + + if (get_user(len, optlen)) + return -EFAULT; diff --git a/Patches/Linux_CVEs/CVE-2014-4943/1.patch b/Patches/Linux_CVEs/CVE-2014-4943/1.patch new file mode 100644 index 00000000..8ec81add --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-4943/1.patch @@ -0,0 +1,56 @@ +From 1179c8f1caca90caf4ce0eec54b499de4f1551c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Jul 2014 17:02:31 -0700 +Subject: net/l2tp: don't fall back on UDP [get|set]sockopt + +commit 3cf521f7dc87c031617fd47e4b7aa2593c2f3daf upstream. + +The l2tp [get|set]sockopt() code has fallen back to the UDP functions +for socket option levels != SOL_PPPOL2TP since day one, but that has +never actually worked, since the l2tp socket isn't an inet socket. + +As David Miller points out: + + "If we wanted this to work, it'd have to look up the tunnel and then + use tunnel->sk, but I wonder how useful that would be" + +Since this can never have worked so nobody could possibly have depended +on that functionality, just remove the broken code and return -EINVAL. + +Reported-by: Sasha Levin +Acked-by: James Chapman +Acked-by: David Miller +Cc: Phil Turnbull +Cc: Vegard Nossum +Cc: Willy Tarreau +Signed-off-by: Linus Torvalds +Signed-off-by: Ben Hutchings +--- + net/l2tp/l2tp_ppp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index e0f0934..437fb59 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -1351,7 +1351,7 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, + int err; + + if (level != SOL_PPPOL2TP) +- return udp_prot.setsockopt(sk, level, optname, optval, optlen); ++ return -EINVAL; + + if (optlen < sizeof(int)) + return -EINVAL; +@@ -1477,7 +1477,7 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, + struct pppol2tp_session *ps; + + if (level != SOL_PPPOL2TP) +- return udp_prot.getsockopt(sk, level, optname, optval, optlen); ++ return -EINVAL; + + if (get_user(len, (int __user *) optlen)) + return -EFAULT; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-5206/0.patch b/Patches/Linux_CVEs/CVE-2014-5206/0.patch new file mode 100644 index 00000000..3ca832c9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-5206/0.patch @@ -0,0 +1,52 @@ +From a6138db815df5ee542d848318e5dae681590fccd Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Mon, 28 Jul 2014 16:26:53 -0700 +Subject: [PATCH] mnt: Only change user settable mount flags in remount + +Kenton Varda discovered that by remounting a +read-only bind mount read-only in a user namespace the +MNT_LOCK_READONLY bit would be cleared, allowing an unprivileged user +to the remount a read-only mount read-write. + +Correct this by replacing the mask of mount flags to preserve +with a mask of mount flags that may be changed, and preserve +all others. This ensures that any future bugs with this mask and +remount will fail in an easy to detect way where new mount flags +simply won't change. + +Cc: stable@vger.kernel.org +Acked-by: Serge E. Hallyn +Signed-off-by: "Eric W. Biederman" +--- + fs/namespace.c | 2 +- + include/linux/mount.h | 4 +++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 7187d01329c35..cb40449ea0dfe 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1937,7 +1937,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags, + err = do_remount_sb(sb, flags, data, 0); + if (!err) { + lock_mount_hash(); +- mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; ++ mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK; + mnt->mnt.mnt_flags = mnt_flags; + touch_mnt_namespace(mnt->mnt_ns); + unlock_mount_hash(); +diff --git a/include/linux/mount.h b/include/linux/mount.h +index 839bac2709048..b637a89e1faeb 100644 +--- a/include/linux/mount.h ++++ b/include/linux/mount.h +@@ -42,7 +42,9 @@ struct mnt_namespace; + * flag, consider how it interacts with shared mounts. + */ + #define MNT_SHARED_MASK (MNT_UNBINDABLE) +-#define MNT_PROPAGATION_MASK (MNT_SHARED | MNT_UNBINDABLE) ++#define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \ ++ | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \ ++ | MNT_READONLY) + + #define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \ + MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED) diff --git a/Patches/Linux_CVEs/CVE-2014-7822/0.patch b/Patches/Linux_CVEs/CVE-2014-7822/0.patch new file mode 100644 index 00000000..a501664e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-7822/0.patch @@ -0,0 +1,72 @@ +From 894c6350eaad7e613ae267504014a456e00a3e2a Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Thu, 29 Jan 2015 02:50:33 +0000 +Subject: splice: Apply generic position and size checks to each write + +We need to check the position and size of file writes against various +limits, using generic_write_check(). This was not being done for +the splice write path. It was fixed upstream by commit 8d0207652cbe +("->splice_write() via ->write_iter()") but we can't apply that. + +CVE-2014-7822 + +Signed-off-by: Ben Hutchings +--- + fs/ocfs2/file.c | 8 ++++++-- + fs/splice.c | 8 ++++++-- + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index d20d64c..0de24a2 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -2468,9 +2468,7 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, + struct address_space *mapping = out->f_mapping; + struct inode *inode = mapping->host; + struct splice_desc sd = { +- .total_len = len, + .flags = flags, +- .pos = *ppos, + .u.file = out, + }; + +@@ -2480,6 +2478,12 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, + out->f_path.dentry->d_name.len, + out->f_path.dentry->d_name.name, len); + ++ ret = generic_write_checks(out, ppos, &len, 0); ++ if (ret) ++ return ret; ++ sd.total_len = len; ++ sd.pos = *ppos; ++ + if (pipe->inode) + mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT); + +diff --git a/fs/splice.c b/fs/splice.c +index 714471d..34c2b2b 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -1013,13 +1013,17 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, + struct address_space *mapping = out->f_mapping; + struct inode *inode = mapping->host; + struct splice_desc sd = { +- .total_len = len, + .flags = flags, +- .pos = *ppos, + .u.file = out, + }; + ssize_t ret; + ++ ret = generic_write_checks(out, ppos, &len, S_ISBLK(inode->i_mode)); ++ if (ret) ++ return ret; ++ sd.total_len = len; ++ sd.pos = *ppos; ++ + pipe_lock(pipe); + + splice_from_pipe_begin(&sd); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-7825/0.patch b/Patches/Linux_CVEs/CVE-2014-7825/0.patch new file mode 100644 index 00000000..285a52c3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-7825/0.patch @@ -0,0 +1,50 @@ +From 6f25b4e75a87fea8087b543f3d1298d301d24ad7 Mon Sep 17 00:00:00 2001 +From: Will Deacon +Date: Thu, 16 Aug 2012 18:14:14 +0100 +Subject: tracing/syscalls: Fix perf syscall tracing when syscall_nr == -1 + +commit 60916a9382e88fbf5e54fd36a3e658efd7ab7bed upstream. + +syscall_get_nr can return -1 in the case that the task is not executing +a system call. + +This patch fixes perf_syscall_{enter,exit} to check that the syscall +number is valid before using it as an index into a bitmap. + +Link: http://lkml.kernel.org/r/1345137254-7377-1-git-send-email-will.deacon@arm.com + +Cc: Jason Baron +Cc: Wade Farnsworth +Cc: Frederic Weisbecker +Signed-off-by: Will Deacon +Signed-off-by: Steven Rostedt +Signed-off-by: Ben Hutchings +--- + kernel/trace/trace_syscalls.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c +index 7c75bbb..22a7c9b 100644 +--- a/kernel/trace/trace_syscalls.c ++++ b/kernel/trace/trace_syscalls.c +@@ -519,6 +519,8 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) + int size; + + syscall_nr = syscall_get_nr(current, regs); ++ if (syscall_nr < 0) ++ return; + if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) + return; + +@@ -593,6 +595,8 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) + int size; + + syscall_nr = syscall_get_nr(current, regs); ++ if (syscall_nr < 0) ++ return; + if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) + return; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-7825/1.patch b/Patches/Linux_CVEs/CVE-2014-7825/1.patch new file mode 100644 index 00000000..03003828 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-7825/1.patch @@ -0,0 +1,91 @@ +From 8043761416d5ae6d8fe5e95331d26465d52e8c6e Mon Sep 17 00:00:00 2001 +From: Rabin Vincent +Date: Wed, 29 Oct 2014 23:06:58 +0100 +Subject: tracing/syscalls: Ignore numbers outside NR_syscalls' range + +commit 086ba77a6db00ed858ff07451bedee197df868c9 upstream. + +ARM has some private syscalls (for example, set_tls(2)) which lie +outside the range of NR_syscalls. If any of these are called while +syscall tracing is being performed, out-of-bounds array access will +occur in the ftrace and perf sys_{enter,exit} handlers. + + # trace-cmd record -e raw_syscalls:* true && trace-cmd report + ... + true-653 [000] 384.675777: sys_enter: NR 192 (0, 1000, 3, 4000022, ffffffff, 0) + true-653 [000] 384.675812: sys_exit: NR 192 = 1995915264 + true-653 [000] 384.675971: sys_enter: NR 983045 (76f74480, 76f74000, 76f74b28, 76f74480, 76f76f74, 1) + true-653 [000] 384.675988: sys_exit: NR 983045 = 0 + ... + + # trace-cmd record -e syscalls:* true + [ 17.289329] Unable to handle kernel paging request at virtual address aaaaaace + [ 17.289590] pgd = 9e71c000 + [ 17.289696] [aaaaaace] *pgd=00000000 + [ 17.289985] Internal error: Oops: 5 [#1] PREEMPT SMP ARM + [ 17.290169] Modules linked in: + [ 17.290391] CPU: 0 PID: 704 Comm: true Not tainted 3.18.0-rc2+ #21 + [ 17.290585] task: 9f4dab00 ti: 9e710000 task.ti: 9e710000 + [ 17.290747] PC is at ftrace_syscall_enter+0x48/0x1f8 + [ 17.290866] LR is at syscall_trace_enter+0x124/0x184 + +Fix this by ignoring out-of-NR_syscalls-bounds syscall numbers. + +Commit cd0980fc8add "tracing: Check invalid syscall nr while tracing syscalls" +added the check for less than zero, but it should have also checked +for greater than NR_syscalls. + +Link: http://lkml.kernel.org/p/1414620418-29472-1-git-send-email-rabin@rab.in + +Fixes: cd0980fc8add "tracing: Check invalid syscall nr while tracing syscalls" +Signed-off-by: Rabin Vincent +Signed-off-by: Steven Rostedt +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +--- + kernel/trace/trace_syscalls.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c +index 22a7c9b..1129062 100644 +--- a/kernel/trace/trace_syscalls.c ++++ b/kernel/trace/trace_syscalls.c +@@ -309,7 +309,7 @@ void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id) + int syscall_nr; + + syscall_nr = syscall_get_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_enter_syscalls)) + return; +@@ -349,7 +349,7 @@ void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) + int syscall_nr; + + syscall_nr = syscall_get_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_exit_syscalls)) + return; +@@ -519,7 +519,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) + int size; + + syscall_nr = syscall_get_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) + return; +@@ -595,7 +595,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) + int size; + + syscall_nr = syscall_get_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) + return; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-7825/2.patch b/Patches/Linux_CVEs/CVE-2014-7825/2.patch new file mode 100644 index 00000000..96490c3e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-7825/2.patch @@ -0,0 +1,85 @@ +From 086ba77a6db00ed858ff07451bedee197df868c9 Mon Sep 17 00:00:00 2001 +From: Rabin Vincent +Date: Wed, 29 Oct 2014 23:06:58 +0100 +Subject: [PATCH] tracing/syscalls: Ignore numbers outside NR_syscalls' range + +ARM has some private syscalls (for example, set_tls(2)) which lie +outside the range of NR_syscalls. If any of these are called while +syscall tracing is being performed, out-of-bounds array access will +occur in the ftrace and perf sys_{enter,exit} handlers. + + # trace-cmd record -e raw_syscalls:* true && trace-cmd report + ... + true-653 [000] 384.675777: sys_enter: NR 192 (0, 1000, 3, 4000022, ffffffff, 0) + true-653 [000] 384.675812: sys_exit: NR 192 = 1995915264 + true-653 [000] 384.675971: sys_enter: NR 983045 (76f74480, 76f74000, 76f74b28, 76f74480, 76f76f74, 1) + true-653 [000] 384.675988: sys_exit: NR 983045 = 0 + ... + + # trace-cmd record -e syscalls:* true + [ 17.289329] Unable to handle kernel paging request at virtual address aaaaaace + [ 17.289590] pgd = 9e71c000 + [ 17.289696] [aaaaaace] *pgd=00000000 + [ 17.289985] Internal error: Oops: 5 [#1] PREEMPT SMP ARM + [ 17.290169] Modules linked in: + [ 17.290391] CPU: 0 PID: 704 Comm: true Not tainted 3.18.0-rc2+ #21 + [ 17.290585] task: 9f4dab00 ti: 9e710000 task.ti: 9e710000 + [ 17.290747] PC is at ftrace_syscall_enter+0x48/0x1f8 + [ 17.290866] LR is at syscall_trace_enter+0x124/0x184 + +Fix this by ignoring out-of-NR_syscalls-bounds syscall numbers. + +Commit cd0980fc8add "tracing: Check invalid syscall nr while tracing syscalls" +added the check for less than zero, but it should have also checked +for greater than NR_syscalls. + +Link: http://lkml.kernel.org/p/1414620418-29472-1-git-send-email-rabin@rab.in + +Fixes: cd0980fc8add "tracing: Check invalid syscall nr while tracing syscalls" +Cc: stable@vger.kernel.org # 2.6.33+ +Signed-off-by: Rabin Vincent +Signed-off-by: Steven Rostedt +--- + kernel/trace/trace_syscalls.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c +index 4dc8b79c5f75d..29228c4d56969 100644 +--- a/kernel/trace/trace_syscalls.c ++++ b/kernel/trace/trace_syscalls.c +@@ -313,7 +313,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + + /* Here we're inside tp handler's rcu_read_lock_sched (__DO_TRACE) */ +@@ -360,7 +360,7 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) + int syscall_nr; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + + /* Here we're inside tp handler's rcu_read_lock_sched (__DO_TRACE()) */ +@@ -567,7 +567,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) + return; +@@ -641,7 +641,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret) + int size; + + syscall_nr = trace_get_syscall_nr(current, regs); +- if (syscall_nr < 0) ++ if (syscall_nr < 0 || syscall_nr >= NR_syscalls) + return; + if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) + return; diff --git a/Patches/Linux_CVEs/CVE-2014-7970/0.patch b/Patches/Linux_CVEs/CVE-2014-7970/0.patch new file mode 100644 index 00000000..02f15198 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-7970/0.patch @@ -0,0 +1,47 @@ +From 0d0826019e529f21c84687521d03f60cd241ca7d Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 8 Oct 2014 10:42:27 -0700 +Subject: mnt: Prevent pivot_root from creating a loop in the mount tree + +Andy Lutomirski recently demonstrated that when chroot is used to set +the root path below the path for the new ``root'' passed to pivot_root +the pivot_root system call succeeds and leaks mounts. + +In examining the code I see that starting with a new root that is +below the current root in the mount tree will result in a loop in the +mount tree after the mounts are detached and then reattached to one +another. Resulting in all kinds of ugliness including a leak of that +mounts involved in the leak of the mount loop. + +Prevent this problem by ensuring that the new mount is reachable from +the current root of the mount tree. + +[Added stable cc. Fixes CVE-2014-7970. --Andy] + +Cc: stable@vger.kernel.org +Reported-by: Andy Lutomirski +Reviewed-by: Andy Lutomirski +Link: http://lkml.kernel.org/r/87bnpmihks.fsf@x220.int.ebiederm.org +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Andy Lutomirski +--- + fs/namespace.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/namespace.c b/fs/namespace.c +index ef42d9b..74647c2 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -2820,6 +2820,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, + /* make sure we can reach put_old from new_root */ + if (!is_path_reachable(old_mnt, old.dentry, &new)) + goto out4; ++ /* make certain new is below the root */ ++ if (!is_path_reachable(new_mnt, new.dentry, &root)) ++ goto out4; + root_mp->m_count++; /* pin it so it won't go away */ + lock_mount_hash(); + detach_mnt(new_mnt, &parent_path); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-7970/1.patch b/Patches/Linux_CVEs/CVE-2014-7970/1.patch new file mode 100644 index 00000000..d796bb59 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-7970/1.patch @@ -0,0 +1,54 @@ +From c88f7bbd8026761a615c9969d186ffa2a1a3da3c Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Thu, 15 Jan 2015 17:49:27 +0000 +Subject: [PATCH] mnt: Prevent pivot_root from creating a loop in the mount + tree + +Andy Lutomirski recently demonstrated that when chroot is used to set +the root path below the path for the new ``root'' passed to pivot_root +the pivot_root system call succeeds and leaks mounts. + +In examining the code I see that starting with a new root that is +below the current root in the mount tree will result in a loop in the +mount tree after the mounts are detached and then reattached to one +another. Resulting in all kinds of ugliness including a leak of that +mounts involved in the leak of the mount loop. + +Prevent this problem by ensuring that the new mount is reachable from +the current root of the mount tree. + +[Added stable cc. Fixes CVE-2014-7970. --Andy] + +Cc: stable@vger.kernel.org +Reported-by: Andy Lutomirski +Reviewed-by: Andy Lutomirski +Link: http://lkml.kernel.org/r/87bnpmihks.fsf@x220.int.ebiederm.org +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Andy Lutomirski +(backported from commit 0d0826019e529f21c84687521d03f60cd241ca7d) +CVE-2014-7970 +BugLink: http://bugs.launchpad.net/bugs/1383356 +Signed-off-by: Luis Henriques +Acked-by: Stefan Bader +Acked-by: Andy Whitcroft +Signed-off-by: Andy Whitcroft + +Change-Id: I0fe1d090eeb4765cc49401784e44a430f9585498 +--- + fs/namespace.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 912d273d970..4f47629a4e0 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -2618,6 +2618,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, + goto out4; + } else if (!is_subdir(old.dentry, new.dentry)) + goto out4; ++ /* make certain new is below the root */ ++ if (!is_path_reachable(new.mnt, new.dentry, &root)) ++ goto out4; + br_write_lock(vfsmount_lock); + detach_mnt(new.mnt, &parent_path); + detach_mnt(root.mnt, &root_parent); diff --git a/Patches/Linux_CVEs/CVE-2014-7970/2.patch b/Patches/Linux_CVEs/CVE-2014-7970/2.patch new file mode 100644 index 00000000..f98e9796 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-7970/2.patch @@ -0,0 +1,50 @@ +From 9f7d53c09a1f87ebe228b55a83c1b8f952d76260 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 8 Oct 2014 10:42:27 -0700 +Subject: mnt: Prevent pivot_root from creating a loop in the mount tree + +commit 0d0826019e529f21c84687521d03f60cd241ca7d upstream. + +Andy Lutomirski recently demonstrated that when chroot is used to set +the root path below the path for the new ``root'' passed to pivot_root +the pivot_root system call succeeds and leaks mounts. + +In examining the code I see that starting with a new root that is +below the current root in the mount tree will result in a loop in the +mount tree after the mounts are detached and then reattached to one +another. Resulting in all kinds of ugliness including a leak of that +mounts involved in the leak of the mount loop. + +Prevent this problem by ensuring that the new mount is reachable from +the current root of the mount tree. + +[Added stable cc. Fixes CVE-2014-7970. --Andy] + +Reported-by: Andy Lutomirski +Reviewed-by: Andy Lutomirski +Link: http://lkml.kernel.org/r/87bnpmihks.fsf@x220.int.ebiederm.org +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Andy Lutomirski +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li +--- + fs/namespace.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/namespace.c b/fs/namespace.c +index f0f2e06..f7be8d9 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -2508,6 +2508,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, + /* make sure we can reach put_old from new_root */ + if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new)) + goto out4; ++ /* make certain new is below the root */ ++ if (!is_path_reachable(new_mnt, new.dentry, &root)) ++ goto out4; + br_write_lock(vfsmount_lock); + detach_mnt(new_mnt, &parent_path); + detach_mnt(root_mnt, &root_parent); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-8160/0.patch b/Patches/Linux_CVEs/CVE-2014-8160/0.patch new file mode 100644 index 00000000..a3d330d7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-8160/0.patch @@ -0,0 +1,88 @@ +From db29a9508a9246e77087c5531e45b2c88ec6988b Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Fri, 26 Sep 2014 11:35:42 +0200 +Subject: [PATCH] netfilter: conntrack: disable generic tracking for known + protocols + +Given following iptables ruleset: + +-P FORWARD DROP +-A FORWARD -m sctp --dport 9 -j ACCEPT +-A FORWARD -p tcp --dport 80 -j ACCEPT +-A FORWARD -p tcp -m conntrack -m state ESTABLISHED,RELATED -j ACCEPT + +One would assume that this allows SCTP on port 9 and TCP on port 80. +Unfortunately, if the SCTP conntrack module is not loaded, this allows +*all* SCTP communication, to pass though, i.e. -p sctp -j ACCEPT, +which we think is a security issue. + +This is because on the first SCTP packet on port 9, we create a dummy +"generic l4" conntrack entry without any port information (since +conntrack doesn't know how to extract this information). + +All subsequent packets that are unknown will then be in established +state since they will fallback to proto_generic and will match the +'generic' entry. + +Our originally proposed version [1] completely disabled generic protocol +tracking, but Jozsef suggests to not track protocols for which a more +suitable helper is available, hence we now mitigate the issue for in +tree known ct protocol helpers only, so that at least NAT and direction +information will still be preserved for others. + + [1] http://www.spinics.net/lists/netfilter-devel/msg33430.html + +Joint work with Daniel Borkmann. + +Signed-off-by: Florian Westphal +Signed-off-by: Daniel Borkmann +Acked-by: Jozsef Kadlecsik +Signed-off-by: Pablo Neira Ayuso +--- + net/netfilter/nf_conntrack_proto_generic.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c +index d25f293776482..957c1db666525 100644 +--- a/net/netfilter/nf_conntrack_proto_generic.c ++++ b/net/netfilter/nf_conntrack_proto_generic.c +@@ -14,6 +14,30 @@ + + static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; + ++static bool nf_generic_should_process(u8 proto) ++{ ++ switch (proto) { ++#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE ++ case IPPROTO_SCTP: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE ++ case IPPROTO_DCCP: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE ++ case IPPROTO_GRE: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE ++ case IPPROTO_UDPLITE: ++ return false; ++#endif ++ default: ++ return true; ++ } ++} ++ + static inline struct nf_generic_net *generic_pernet(struct net *net) + { + return &net->ct.nf_ct_proto.generic; +@@ -67,7 +91,7 @@ static int generic_packet(struct nf_conn *ct, + static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, + unsigned int dataoff, unsigned int *timeouts) + { +- return true; ++ return nf_generic_should_process(nf_ct_protonum(ct)); + } + + #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) diff --git a/Patches/Linux_CVEs/CVE-2014-8160/1.patch b/Patches/Linux_CVEs/CVE-2014-8160/1.patch new file mode 100644 index 00000000..5c2db680 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-8160/1.patch @@ -0,0 +1,94 @@ +From d7cde286daad20dd171247ea47fc5ff4868591f0 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Fri, 26 Sep 2014 11:35:42 +0200 +Subject: netfilter: conntrack: disable generic tracking for known protocols + +commit db29a9508a9246e77087c5531e45b2c88ec6988b upstream. + +Given following iptables ruleset: + +-P FORWARD DROP +-A FORWARD -m sctp --dport 9 -j ACCEPT +-A FORWARD -p tcp --dport 80 -j ACCEPT +-A FORWARD -p tcp -m conntrack -m state ESTABLISHED,RELATED -j ACCEPT + +One would assume that this allows SCTP on port 9 and TCP on port 80. +Unfortunately, if the SCTP conntrack module is not loaded, this allows +*all* SCTP communication, to pass though, i.e. -p sctp -j ACCEPT, +which we think is a security issue. + +This is because on the first SCTP packet on port 9, we create a dummy +"generic l4" conntrack entry without any port information (since +conntrack doesn't know how to extract this information). + +All subsequent packets that are unknown will then be in established +state since they will fallback to proto_generic and will match the +'generic' entry. + +Our originally proposed version [1] completely disabled generic protocol +tracking, but Jozsef suggests to not track protocols for which a more +suitable helper is available, hence we now mitigate the issue for in +tree known ct protocol helpers only, so that at least NAT and direction +information will still be preserved for others. + + [1] http://www.spinics.net/lists/netfilter-devel/msg33430.html + +Joint work with Daniel Borkmann. + +Signed-off-by: Florian Westphal +Signed-off-by: Daniel Borkmann +Acked-by: Jozsef Kadlecsik +Signed-off-by: Pablo Neira Ayuso +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +--- + net/netfilter/nf_conntrack_proto_generic.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c +index e2091d0..53bf12a 100644 +--- a/net/netfilter/nf_conntrack_proto_generic.c ++++ b/net/netfilter/nf_conntrack_proto_generic.c +@@ -14,6 +14,30 @@ + + static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; + ++static bool nf_generic_should_process(u8 proto) ++{ ++ switch (proto) { ++#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE ++ case IPPROTO_SCTP: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE ++ case IPPROTO_DCCP: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE ++ case IPPROTO_GRE: ++ return false; ++#endif ++#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE ++ case IPPROTO_UDPLITE: ++ return false; ++#endif ++ default: ++ return true; ++ } ++} ++ + static bool generic_pkt_to_tuple(const struct sk_buff *skb, + unsigned int dataoff, + struct nf_conntrack_tuple *tuple) +@@ -56,7 +80,7 @@ static int packet(struct nf_conn *ct, + static bool new(struct nf_conn *ct, const struct sk_buff *skb, + unsigned int dataoff) + { +- return true; ++ return nf_generic_should_process(nf_ct_protonum(ct)); + } + + #ifdef CONFIG_SYSCTL +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-8173/0.patch b/Patches/Linux_CVEs/CVE-2014-8173/0.patch new file mode 100644 index 00000000..07aa158e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-8173/0.patch @@ -0,0 +1,51 @@ +From ee53664bda169f519ce3c6a22d378f0b946c8178 Mon Sep 17 00:00:00 2001 +From: "Kirill A. Shutemov" +Date: Fri, 20 Dec 2013 15:10:03 +0200 +Subject: [PATCH] mm: Fix NULL pointer dereference in madvise(MADV_WILLNEED) + support + +Sasha Levin found a NULL pointer dereference that is due to a missing +page table lock, which in turn is due to the pmd entry in question being +a transparent huge-table entry. + +The code - introduced in commit 1998cc048901 ("mm: make +madvise(MADV_WILLNEED) support swap file prefetch") - correctly checks +for this situation using pmd_none_or_trans_huge_or_clear_bad(), but it +turns out that that function doesn't work correctly. + +pmd_none_or_trans_huge_or_clear_bad() expected that pmd_bad() would +trigger if the transparent hugepage bit was set, but it doesn't do that +if pmd_numa() is also set. Note that the NUMA bit only gets set on real +NUMA machines, so people trying to reproduce this on most normal +development systems would never actually trigger this. + +Fix it by removing the very subtle (and subtly incorrect) expectation, +and instead just checking pmd_trans_huge() explicitly. + +Reported-by: Sasha Levin +Acked-by: Andrea Arcangeli +[ Additionally remove the now stale test for pmd_trans_huge() inside the + pmd_bad() case - Linus ] +Signed-off-by: Linus Torvalds +--- + include/asm-generic/pgtable.h | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h +index b12079afbd5f2..db09234589409 100644 +--- a/include/asm-generic/pgtable.h ++++ b/include/asm-generic/pgtable.h +@@ -599,11 +599,10 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + barrier(); + #endif +- if (pmd_none(pmdval)) ++ if (pmd_none(pmdval) || pmd_trans_huge(pmdval)) + return 1; + if (unlikely(pmd_bad(pmdval))) { +- if (!pmd_trans_huge(pmdval)) +- pmd_clear_bad(pmd); ++ pmd_clear_bad(pmd); + return 1; + } + return 0; diff --git a/Patches/Linux_CVEs/CVE-2014-8709/0.patch b/Patches/Linux_CVEs/CVE-2014-8709/0.patch new file mode 100644 index 00000000..25f6dfb3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-8709/0.patch @@ -0,0 +1,53 @@ +From 338f977f4eb441e69bb9a46eaa0ac715c931a67f Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Sat, 1 Feb 2014 00:16:23 +0100 +Subject: mac80211: fix fragmentation code, particularly for encryption + +The "new" fragmentation code (since my rewrite almost 5 years ago) +erroneously sets skb->len rather than using skb_trim() to adjust +the length of the first fragment after copying out all the others. +This leaves the skb tail pointer pointing to after where the data +originally ended, and thus causes the encryption MIC to be written +at that point, rather than where it belongs: immediately after the +data. + +The impact of this is that if software encryption is done, then + a) encryption doesn't work for the first fragment, the connection + becomes unusable as the first fragment will never be properly + verified at the receiver, the MIC is practically guaranteed to + be wrong + b) we leak up to 8 bytes of plaintext (!) of the packet out into + the air + +This is only mitigated by the fact that many devices are capable +of doing encryption in hardware, in which case this can't happen +as the tail pointer is irrelevant in that case. Additionally, +fragmentation is not used very frequently and would normally have +to be configured manually. + +Fix this by using skb_trim() properly. + +Cc: stable@vger.kernel.org +Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation") +Reported-by: Jouni Malinen +Signed-off-by: Johannes Berg +--- + net/mac80211/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 27c990b..97a02d3 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -878,7 +878,7 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx, + } + + /* adjust first fragment's length */ +- skb->len = hdrlen + per_fragm; ++ skb_trim(skb, hdrlen + per_fragm); + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-8709/1.patch b/Patches/Linux_CVEs/CVE-2014-8709/1.patch new file mode 100644 index 00000000..8340cbe2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-8709/1.patch @@ -0,0 +1,56 @@ +From c7b18cdf1887e8ce91e04342cfd2d8fe1630be92 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Sat, 1 Feb 2014 00:16:23 +0100 +Subject: mac80211: fix fragmentation code, particularly for encryption + +commit 338f977f4eb441e69bb9a46eaa0ac715c931a67f upstream. + +The "new" fragmentation code (since my rewrite almost 5 years ago) +erroneously sets skb->len rather than using skb_trim() to adjust +the length of the first fragment after copying out all the others. +This leaves the skb tail pointer pointing to after where the data +originally ended, and thus causes the encryption MIC to be written +at that point, rather than where it belongs: immediately after the +data. + +The impact of this is that if software encryption is done, then + a) encryption doesn't work for the first fragment, the connection + becomes unusable as the first fragment will never be properly + verified at the receiver, the MIC is practically guaranteed to + be wrong + b) we leak up to 8 bytes of plaintext (!) of the packet out into + the air + +This is only mitigated by the fact that many devices are capable +of doing encryption in hardware, in which case this can't happen +as the tail pointer is irrelevant in that case. Additionally, +fragmentation is not used very frequently and would normally have +to be configured manually. + +Fix this by using skb_trim() properly. + +Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation") +Reported-by: Jouni Malinen +Signed-off-by: Johannes Berg +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +--- + net/mac80211/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c +index 4ff35bf..5186f8b 100644 +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -884,7 +884,7 @@ static int ieee80211_fragment(struct ieee80211_local *local, + pos += fraglen; + } + +- skb->len = hdrlen + per_fragm; ++ skb_trim(skb, hdrlen + per_fragm); + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9420/0.patch b/Patches/Linux_CVEs/CVE-2014-9420/0.patch new file mode 100644 index 00000000..d677dc89 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9420/0.patch @@ -0,0 +1,52 @@ +From f54e18f1b831c92f6512d2eedb224cd63d607d3d Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 15 Dec 2014 14:22:46 +0100 +Subject: [PATCH] isofs: Fix infinite looping over CE entries + +Rock Ridge extensions define so called Continuation Entries (CE) which +define where is further space with Rock Ridge data. Corrupted isofs +image can contain arbitrarily long chain of these, including a one +containing loop and thus causing kernel to end in an infinite loop when +traversing these entries. + +Limit the traversal to 32 entries which should be more than enough space +to store all the Rock Ridge data. + +Reported-by: P J P +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +--- + fs/isofs/rock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c +index f488bbae541ac..bb63254ed8486 100644 +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -30,6 +30,7 @@ struct rock_state { + int cont_size; + int cont_extent; + int cont_offset; ++ int cont_loops; + struct inode *inode; + }; + +@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode) + rs->inode = inode; + } + ++/* Maximum number of Rock Ridge continuation entries */ ++#define RR_MAX_CE_ENTRIES 32 ++ + /* + * Returns 0 if the caller should continue scanning, 1 if the scan must end + * and -ve on error. +@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs) + goto out; + } + ret = -EIO; ++ if (++rs->cont_loops >= RR_MAX_CE_ENTRIES) ++ goto out; + bh = sb_bread(rs->inode->i_sb, rs->cont_extent); + if (bh) { + memcpy(rs->buffer, bh->b_data + rs->cont_offset, diff --git a/Patches/Linux_CVEs/CVE-2014-9420/1.patch b/Patches/Linux_CVEs/CVE-2014-9420/1.patch new file mode 100644 index 00000000..12f7d903 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9420/1.patch @@ -0,0 +1,57 @@ +From 212c4d33ca83e2144064fe9c2911607fbed5386f Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 15 Dec 2014 14:22:46 +0100 +Subject: isofs: Fix infinite looping over CE entries + +commit f54e18f1b831c92f6512d2eedb224cd63d607d3d upstream. + +Rock Ridge extensions define so called Continuation Entries (CE) which +define where is further space with Rock Ridge data. Corrupted isofs +image can contain arbitrarily long chain of these, including a one +containing loop and thus causing kernel to end in an infinite loop when +traversing these entries. + +Limit the traversal to 32 entries which should be more than enough space +to store all the Rock Ridge data. + +Reported-by: P J P +Signed-off-by: Jan Kara +Signed-off-by: Ben Hutchings +--- + fs/isofs/rock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c +index ee62cc0..26859de 100644 +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -30,6 +30,7 @@ struct rock_state { + int cont_size; + int cont_extent; + int cont_offset; ++ int cont_loops; + struct inode *inode; + }; + +@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode) + rs->inode = inode; + } + ++/* Maximum number of Rock Ridge continuation entries */ ++#define RR_MAX_CE_ENTRIES 32 ++ + /* + * Returns 0 if the caller should continue scanning, 1 if the scan must end + * and -ve on error. +@@ -105,6 +109,8 @@ static int rock_continue(struct rock_state *rs) + goto out; + } + ret = -EIO; ++ if (++rs->cont_loops >= RR_MAX_CE_ENTRIES) ++ goto out; + bh = sb_bread(rs->inode->i_sb, rs->cont_extent); + if (bh) { + memcpy(rs->buffer, bh->b_data + rs->cont_offset, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9529/0.patch b/Patches/Linux_CVEs/CVE-2014-9529/0.patch new file mode 100644 index 00000000..67850775 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9529/0.patch @@ -0,0 +1,44 @@ +From a3a8784454692dd72e5d5d34dcdab17b4420e74c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Dec 2014 09:39:01 -0500 +Subject: [PATCH] KEYS: close race between key lookup and freeing + +When a key is being garbage collected, it's key->user would get put before +the ->destroy() callback is called, where the key is removed from it's +respective tracking structures. + +This leaves a key hanging in a semi-invalid state which leaves a window open +for a different task to try an access key->user. An example is +find_keyring_by_name() which would dereference key->user for a key that is +in the process of being garbage collected (where key->user was freed but +->destroy() wasn't called yet - so it's still present in the linked list). + +This would cause either a panic, or corrupt memory. + +Fixes CVE-2014-9529. + +Signed-off-by: Sasha Levin +Signed-off-by: David Howells +--- + security/keys/gc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/keys/gc.c b/security/keys/gc.c +index 9609a7f0faea2..c7952375ac532 100644 +--- a/security/keys/gc.c ++++ b/security/keys/gc.c +@@ -148,12 +148,12 @@ static noinline void key_gc_unused_keys(struct list_head *keys) + if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) + atomic_dec(&key->user->nikeys); + +- key_user_put(key->user); +- + /* now throw away the key memory */ + if (key->type->destroy) + key->type->destroy(key); + ++ key_user_put(key->user); ++ + kfree(key->description); + + #ifdef KEY_DEBUGGING diff --git a/Patches/Linux_CVEs/CVE-2014-9529/1.patch b/Patches/Linux_CVEs/CVE-2014-9529/1.patch new file mode 100644 index 00000000..d6a466df --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9529/1.patch @@ -0,0 +1,51 @@ +From dc4a2f40de419c01b538c87f6bdfc15d574d9f7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Dec 2014 09:39:01 -0500 +Subject: KEYS: close race between key lookup and freeing + +commit a3a8784454692dd72e5d5d34dcdab17b4420e74c upstream. + +When a key is being garbage collected, it's key->user would get put before +the ->destroy() callback is called, where the key is removed from it's +respective tracking structures. + +This leaves a key hanging in a semi-invalid state which leaves a window open +for a different task to try an access key->user. An example is +find_keyring_by_name() which would dereference key->user for a key that is +in the process of being garbage collected (where key->user was freed but +->destroy() wasn't called yet - so it's still present in the linked list). + +This would cause either a panic, or corrupt memory. + +Fixes CVE-2014-9529. + +Signed-off-by: Sasha Levin +Signed-off-by: David Howells +[bwh: Backported to 3.2: adjust indentation] +Signed-off-by: Ben Hutchings +--- + security/keys/gc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/keys/gc.c b/security/keys/gc.c +index bf4d8da..2e2395d 100644 +--- a/security/keys/gc.c ++++ b/security/keys/gc.c +@@ -186,12 +186,12 @@ static noinline void key_gc_unused_key(struct key *key) + if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) + atomic_dec(&key->user->nikeys); + +- key_user_put(key->user); +- + /* now throw away the key memory */ + if (key->type->destroy) + key->type->destroy(key); + ++ key_user_put(key->user); ++ + kfree(key->description); + + #ifdef KEY_DEBUGGING +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9683/0.patch b/Patches/Linux_CVEs/CVE-2014-9683/0.patch new file mode 100644 index 00000000..31e9f402 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9683/0.patch @@ -0,0 +1,32 @@ +From 942080643bce061c3dd9d5718d3b745dcb39a8bc Mon Sep 17 00:00:00 2001 +From: Michael Halcrow +Date: Wed, 26 Nov 2014 09:09:16 -0800 +Subject: [PATCH] eCryptfs: Remove buggy and unnecessary write in file name + decode routine + +Dmitry Chernenkov used KASAN to discover that eCryptfs writes past the +end of the allocated buffer during encrypted filename decoding. This +fix corrects the issue by getting rid of the unnecessary 0 write when +the current bit offset is 2. + +Signed-off-by: Michael Halcrow +Reported-by: Dmitry Chernenkov +Suggested-by: Kees Cook +Cc: stable@vger.kernel.org # v2.6.29+: 51ca58d eCryptfs: Filename Encryption: Encoding and encryption functions +Signed-off-by: Tyler Hicks +--- + fs/ecryptfs/crypto.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c +index 2f6735dbf1a9d..31b148f3e7729 100644 +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -1917,7 +1917,6 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, + break; + case 2: + dst[dst_byte_offset++] |= (src_byte); +- dst[dst_byte_offset] = 0; + current_bit_offset = 0; + break; + } diff --git a/Patches/Linux_CVEs/CVE-2014-9683/1.patch b/Patches/Linux_CVEs/CVE-2014-9683/1.patch new file mode 100644 index 00000000..38919fbe --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9683/1.patch @@ -0,0 +1,37 @@ +From f2d130454e46c3989af1b4f882b6a666d24fa2e0 Mon Sep 17 00:00:00 2001 +From: Michael Halcrow +Date: Wed, 26 Nov 2014 09:09:16 -0800 +Subject: eCryptfs: Remove buggy and unnecessary write in file name decode + routine + +commit 942080643bce061c3dd9d5718d3b745dcb39a8bc upstream. + +Dmitry Chernenkov used KASAN to discover that eCryptfs writes past the +end of the allocated buffer during encrypted filename decoding. This +fix corrects the issue by getting rid of the unnecessary 0 write when +the current bit offset is 2. + +Signed-off-by: Michael Halcrow +Reported-by: Dmitry Chernenkov +Suggested-by: Kees Cook +Signed-off-by: Tyler Hicks +Signed-off-by: Ben Hutchings +--- + fs/ecryptfs/crypto.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c +index 68b19ab..dceedec 100644 +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -2038,7 +2038,6 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, + break; + case 2: + dst[dst_byte_offset++] |= (src_byte); +- dst[dst_byte_offset] = 0; + current_bit_offset = 0; + break; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9715/0.patch b/Patches/Linux_CVEs/CVE-2014-9715/0.patch new file mode 100644 index 00000000..6b1c6df4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9715/0.patch @@ -0,0 +1,50 @@ +From 223b02d923ecd7c84cf9780bb3686f455d279279 Mon Sep 17 00:00:00 2001 +From: Andrey Vagin +Date: Fri, 28 Mar 2014 13:54:32 +0400 +Subject: [PATCH] netfilter: nf_conntrack: reserve two bytes for nf_ct_ext->len + +"len" contains sizeof(nf_ct_ext) and size of extensions. In a worst +case it can contain all extensions. Bellow you can find sizes for all +types of extensions. Their sum is definitely bigger than 256. + +nf_ct_ext_types[0]->len = 24 +nf_ct_ext_types[1]->len = 32 +nf_ct_ext_types[2]->len = 24 +nf_ct_ext_types[3]->len = 32 +nf_ct_ext_types[4]->len = 152 +nf_ct_ext_types[5]->len = 2 +nf_ct_ext_types[6]->len = 16 +nf_ct_ext_types[7]->len = 8 + +I have seen "len" up to 280 and my host has crashes w/o this patch. + +The right way to fix this problem is reducing the size of the ecache +extension (4) and Florian is going to do this, but these changes will +be quite large to be appropriate for a stable tree. + +Fixes: 5b423f6a40a0 (netfilter: nf_conntrack: fix racy timer handling with reliable) +Cc: Pablo Neira Ayuso +Cc: Patrick McHardy +Cc: Jozsef Kadlecsik +Cc: "David S. Miller" +Signed-off-by: Andrey Vagin +Signed-off-by: Pablo Neira Ayuso +--- + include/net/netfilter/nf_conntrack_extend.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h +index 956b175523ffa..55d15049ab2fd 100644 +--- a/include/net/netfilter/nf_conntrack_extend.h ++++ b/include/net/netfilter/nf_conntrack_extend.h +@@ -47,8 +47,8 @@ enum nf_ct_ext_id { + /* Extensions: optional stuff which isn't permanently in struct. */ + struct nf_ct_ext { + struct rcu_head rcu; +- u8 offset[NF_CT_EXT_NUM]; +- u8 len; ++ u16 offset[NF_CT_EXT_NUM]; ++ u16 len; + char data[0]; + }; + diff --git a/Patches/Linux_CVEs/CVE-2014-9715/1.patch b/Patches/Linux_CVEs/CVE-2014-9715/1.patch new file mode 100644 index 00000000..3f7042c9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9715/1.patch @@ -0,0 +1,56 @@ +From 33eedfe8ecbaabcdc38be63901cb2b79e3190fda Mon Sep 17 00:00:00 2001 +From: Andrey Vagin +Date: Fri, 28 Mar 2014 13:54:32 +0400 +Subject: netfilter: nf_conntrack: reserve two bytes for nf_ct_ext->len + +commit 223b02d923ecd7c84cf9780bb3686f455d279279 upstream. + +"len" contains sizeof(nf_ct_ext) and size of extensions. In a worst +case it can contain all extensions. Bellow you can find sizes for all +types of extensions. Their sum is definitely bigger than 256. + +nf_ct_ext_types[0]->len = 24 +nf_ct_ext_types[1]->len = 32 +nf_ct_ext_types[2]->len = 24 +nf_ct_ext_types[3]->len = 32 +nf_ct_ext_types[4]->len = 152 +nf_ct_ext_types[5]->len = 2 +nf_ct_ext_types[6]->len = 16 +nf_ct_ext_types[7]->len = 8 + +I have seen "len" up to 280 and my host has crashes w/o this patch. + +The right way to fix this problem is reducing the size of the ecache +extension (4) and Florian is going to do this, but these changes will +be quite large to be appropriate for a stable tree. + +Fixes: 5b423f6a40a0 (netfilter: nf_conntrack: fix racy timer handling with reliable) +Cc: Pablo Neira Ayuso +Cc: Patrick McHardy +Cc: Jozsef Kadlecsik +Cc: "David S. Miller" +Signed-off-by: Andrey Vagin +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Ben Hutchings +--- + include/net/netfilter/nf_conntrack_extend.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h +index 2dcf317..d918074 100644 +--- a/include/net/netfilter/nf_conntrack_extend.h ++++ b/include/net/netfilter/nf_conntrack_extend.h +@@ -33,8 +33,8 @@ enum nf_ct_ext_id { + /* Extensions: optional stuff which isn't permanently in struct. */ + struct nf_ct_ext { + struct rcu_head rcu; +- u8 offset[NF_CT_EXT_NUM]; +- u8 len; ++ u16 offset[NF_CT_EXT_NUM]; ++ u16 len; + char data[0]; + }; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9731/0.patch b/Patches/Linux_CVEs/CVE-2014-9731/0.patch new file mode 100644 index 00000000..60b78c75 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9731/0.patch @@ -0,0 +1,236 @@ +From 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 18 Dec 2014 22:37:50 +0100 +Subject: udf: Check path length when reading symlink + +Symlink reading code does not check whether the resulting path fits into +the page provided by the generic code. This isn't as easy as just +checking the symlink size because of various encoding conversions we +perform on path. So we have to check whether there is still enough space +in the buffer on the fly. + +CC: stable@vger.kernel.org +Reported-by: Carl Henrik Lunde +Signed-off-by: Jan Kara +--- + fs/udf/dir.c | 3 ++- + fs/udf/namei.c | 3 ++- + fs/udf/symlink.c | 31 ++++++++++++++++++++++++++----- + fs/udf/udfdecl.h | 3 ++- + fs/udf/unicode.c | 28 ++++++++++++++++------------ + 5 files changed, 48 insertions(+), 20 deletions(-) + +diff --git a/fs/udf/dir.c b/fs/udf/dir.c +index a012c51..a7690b4 100644 +--- a/fs/udf/dir.c ++++ b/fs/udf/dir.c +@@ -167,7 +167,8 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) + continue; + } + +- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); ++ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, ++ UDF_NAME_LEN); + if (!flen) + continue; + +diff --git a/fs/udf/namei.c b/fs/udf/namei.c +index c12e260..6ff19b5 100644 +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -233,7 +233,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, + if (!lfi) + continue; + +- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); ++ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, ++ UDF_NAME_LEN); + if (flen && udf_match(flen, fname, child->len, child->name)) + goto out_ok; + } +diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c +index c3aa6fa..0f1b3a2 100644 +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -30,13 +30,16 @@ + #include + #include "udf_i.h" + +-static void udf_pc_to_char(struct super_block *sb, unsigned char *from, +- int fromlen, unsigned char *to) ++static int udf_pc_to_char(struct super_block *sb, unsigned char *from, ++ int fromlen, unsigned char *to, int tolen) + { + struct pathComponent *pc; + int elen = 0; ++ int comp_len; + unsigned char *p = to; + ++ /* Reserve one byte for terminating \0 */ ++ tolen--; + while (elen < fromlen) { + pc = (struct pathComponent *)(from + elen); + switch (pc->componentType) { +@@ -49,22 +52,37 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from, + break; + /* Fall through */ + case 2: ++ if (tolen == 0) ++ return -ENAMETOOLONG; + p = to; + *p++ = '/'; ++ tolen--; + break; + case 3: ++ if (tolen < 3) ++ return -ENAMETOOLONG; + memcpy(p, "../", 3); + p += 3; ++ tolen -= 3; + break; + case 4: ++ if (tolen < 2) ++ return -ENAMETOOLONG; + memcpy(p, "./", 2); + p += 2; ++ tolen -= 2; + /* that would be . - just ignore */ + break; + case 5: +- p += udf_get_filename(sb, pc->componentIdent, p, +- pc->lengthComponentIdent); ++ comp_len = udf_get_filename(sb, pc->componentIdent, ++ pc->lengthComponentIdent, ++ p, tolen); ++ p += comp_len; ++ tolen -= comp_len; ++ if (tolen == 0) ++ return -ENAMETOOLONG; + *p++ = '/'; ++ tolen--; + break; + } + elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; +@@ -73,6 +91,7 @@ static void udf_pc_to_char(struct super_block *sb, unsigned char *from, + p[-1] = '\0'; + else + p[0] = '\0'; ++ return 0; + } + + static int udf_symlink_filler(struct file *file, struct page *page) +@@ -108,8 +127,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) + symlink = bh->b_data; + } + +- udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); ++ err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); + brelse(bh); ++ if (err) ++ goto out_unlock_inode; + + up_read(&iinfo->i_data_sem); + SetPageUptodate(page); +diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h +index 1cc3c99..47bb3f5 100644 +--- a/fs/udf/udfdecl.h ++++ b/fs/udf/udfdecl.h +@@ -211,7 +211,8 @@ udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc, + } + + /* unicode.c */ +-extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); ++extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *, ++ int); + extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, + int); + extern int udf_build_ustr(struct ustr *, dstring *, int); +diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c +index afd470e..b84fee3 100644 +--- a/fs/udf/unicode.c ++++ b/fs/udf/unicode.c +@@ -28,7 +28,8 @@ + + #include "udf_sb.h" + +-static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); ++static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *, ++ int); + + static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) + { +@@ -333,8 +334,8 @@ try_again: + return u_len + 1; + } + +-int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, +- int flen) ++int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, ++ uint8_t *dname, int dlen) + { + struct ustr *filename, *unifilename; + int len = 0; +@@ -347,7 +348,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, + if (!unifilename) + goto out1; + +- if (udf_build_ustr_exact(unifilename, sname, flen)) ++ if (udf_build_ustr_exact(unifilename, sname, slen)) + goto out2; + + if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { +@@ -366,7 +367,8 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, + } else + goto out2; + +- len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, ++ len = udf_translate_to_linux(dname, dlen, ++ filename->u_name, filename->u_len, + unifilename->u_name, unifilename->u_len); + out2: + kfree(unifilename); +@@ -403,10 +405,12 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname, + #define EXT_MARK '.' + #define CRC_MARK '#' + #define EXT_SIZE 5 ++/* Number of chars we need to store generated CRC to make filename unique */ ++#define CRC_LEN 5 + +-static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, +- int udfLen, uint8_t *fidName, +- int fidNameLen) ++static int udf_translate_to_linux(uint8_t *newName, int newLen, ++ uint8_t *udfName, int udfLen, ++ uint8_t *fidName, int fidNameLen) + { + int index, newIndex = 0, needsCRC = 0; + int extIndex = 0, newExtIndex = 0, hasExt = 0; +@@ -439,7 +443,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, + newExtIndex = newIndex; + } + } +- if (newIndex < 256) ++ if (newIndex < newLen) + newName[newIndex++] = curr; + else + needsCRC = 1; +@@ -467,13 +471,13 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, + } + ext[localExtIndex++] = curr; + } +- maxFilenameLen = 250 - localExtIndex; ++ maxFilenameLen = newLen - CRC_LEN - localExtIndex; + if (newIndex > maxFilenameLen) + newIndex = maxFilenameLen; + else + newIndex = newExtIndex; +- } else if (newIndex > 250) +- newIndex = 250; ++ } else if (newIndex > newLen - CRC_LEN) ++ newIndex = newLen - CRC_LEN; + newName[newIndex++] = CRC_MARK; + valueCRC = crc_itu_t(0, fidName, fidNameLen); + newName[newIndex++] = hex_asc_upper_hi(valueCRC >> 8); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9777/0.patch b/Patches/Linux_CVEs/CVE-2014-9777/0.patch new file mode 100644 index 00000000..3d3613c3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9777/0.patch @@ -0,0 +1,48 @@ +From af85054aa6a1bcd38be2354921f2f80aef1440e5 Mon Sep 17 00:00:00 2001 +From: "Pachika, Vikas Reddy" +Date: Fri, 1 Nov 2013 21:06:37 +0530 +Subject: msm: vidc: Validate userspace buffer count + +Makesure the number of buffers count is less than +the maximum limit to avoid structure overflow errors. + +Change-Id: Icf3850de36325637ae43ac95f1c8f0f63e201d31 +CRs-fixed: 563694 +Signed-off-by: Pachika, Vikas Reddy +--- + drivers/video/msm/vidc/common/dec/vdec.c | 6 ++++++ + include/media/msm/vidc_init.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c +index a843889..b45100f 100644 +--- a/drivers/video/msm/vidc/common/dec/vdec.c ++++ b/drivers/video/msm/vidc/common/dec/vdec.c +@@ -1201,6 +1201,12 @@ static u32 vid_dec_set_h264_mv_buffers(struct video_client_ctx *client_ctx, + vcd_h264_mv_buffer->pmem_fd = mv_data->pmem_fd; + vcd_h264_mv_buffer->offset = mv_data->offset; + ++ if (mv_data->count > MAX_MV_BUFFERS) { ++ ERR("MV buffers maximum count reached, count = %d", ++ mv_data->count); ++ return false; ++ } ++ + if (!vcd_get_ion_status()) { + if (get_pmem_file(vcd_h264_mv_buffer->pmem_fd, + (unsigned long *) (&(vcd_h264_mv_buffer-> +diff --git a/include/media/msm/vidc_init.h b/include/media/msm/vidc_init.h +index c35f770..5df0c3e 100644 +--- a/include/media/msm/vidc_init.h ++++ b/include/media/msm/vidc_init.h +@@ -20,6 +20,7 @@ + #define VIDC_MAX_NUM_CLIENTS 4 + #define MAX_VIDEO_NUM_OF_BUFF 100 + #define MAX_META_BUFFERS 32 ++#define MAX_MV_BUFFERS 32 + + enum buffer_dir { + BUFFER_TYPE_INPUT, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9778/0.patch b/Patches/Linux_CVEs/CVE-2014-9778/0.patch new file mode 100644 index 00000000..3d3613c3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9778/0.patch @@ -0,0 +1,48 @@ +From af85054aa6a1bcd38be2354921f2f80aef1440e5 Mon Sep 17 00:00:00 2001 +From: "Pachika, Vikas Reddy" +Date: Fri, 1 Nov 2013 21:06:37 +0530 +Subject: msm: vidc: Validate userspace buffer count + +Makesure the number of buffers count is less than +the maximum limit to avoid structure overflow errors. + +Change-Id: Icf3850de36325637ae43ac95f1c8f0f63e201d31 +CRs-fixed: 563694 +Signed-off-by: Pachika, Vikas Reddy +--- + drivers/video/msm/vidc/common/dec/vdec.c | 6 ++++++ + include/media/msm/vidc_init.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c +index a843889..b45100f 100644 +--- a/drivers/video/msm/vidc/common/dec/vdec.c ++++ b/drivers/video/msm/vidc/common/dec/vdec.c +@@ -1201,6 +1201,12 @@ static u32 vid_dec_set_h264_mv_buffers(struct video_client_ctx *client_ctx, + vcd_h264_mv_buffer->pmem_fd = mv_data->pmem_fd; + vcd_h264_mv_buffer->offset = mv_data->offset; + ++ if (mv_data->count > MAX_MV_BUFFERS) { ++ ERR("MV buffers maximum count reached, count = %d", ++ mv_data->count); ++ return false; ++ } ++ + if (!vcd_get_ion_status()) { + if (get_pmem_file(vcd_h264_mv_buffer->pmem_fd, + (unsigned long *) (&(vcd_h264_mv_buffer-> +diff --git a/include/media/msm/vidc_init.h b/include/media/msm/vidc_init.h +index c35f770..5df0c3e 100644 +--- a/include/media/msm/vidc_init.h ++++ b/include/media/msm/vidc_init.h +@@ -20,6 +20,7 @@ + #define VIDC_MAX_NUM_CLIENTS 4 + #define MAX_VIDEO_NUM_OF_BUFF 100 + #define MAX_META_BUFFERS 32 ++#define MAX_MV_BUFFERS 32 + + enum buffer_dir { + BUFFER_TYPE_INPUT, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9780/0.patch b/Patches/Linux_CVEs/CVE-2014-9780/0.patch new file mode 100644 index 00000000..74af5d5a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9780/0.patch @@ -0,0 +1,30 @@ +From b5bb13e1f738f90df11e0c17f843c73999a84a54 Mon Sep 17 00:00:00 2001 +From: Terence Hampson +Date: Thu, 19 Sep 2013 10:53:18 -0400 +Subject: mdss: mdp3: Validate input from userspace + +Fully verify that the values from client are safe to use. + +Change-Id: I73d6839f5bccd53b8bc2d812dc7673b13735299c +Signed-off-by: Terence Hampson +--- + drivers/video/msm/mdss/mdp3_ctrl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c +index ee51e92..1d6d437 100644 +--- a/drivers/video/msm/mdss/mdp3_ctrl.c ++++ b/drivers/video/msm/mdss/mdp3_ctrl.c +@@ -1218,7 +1218,8 @@ static int mdp3_ctrl_lut_update(struct msm_fb_data_type *mfd, + if (!mdp3_session->dma->config_lut) + return -EINVAL; + +- if (cmap->start + cmap->len > MDP_LUT_SIZE) { ++ if (cmap->start > MDP_LUT_SIZE || cmap->len > MDP_LUT_SIZE || ++ (cmap->start + cmap->len > MDP_LUT_SIZE)) { + pr_err("mdp3_ctrl_lut_update invalid arguments\n"); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9781/0.patch b/Patches/Linux_CVEs/CVE-2014-9781/0.patch new file mode 100644 index 00000000..7070789a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9781/0.patch @@ -0,0 +1,37 @@ +From a2b5237ad265ec634489c8b296d870827b2a1b13 Mon Sep 17 00:00:00 2001 +From: Shalabh Jain +Date: Tue, 12 Nov 2013 15:10:44 -0800 +Subject: fbcmap: prevent memory overflow + +Add bounds check before copying data to prevent +buffer overflow. + +Change-Id: I47b9685b1ab13c4863fb6db62bbb9497a00b36da +Signed-off-by: Shalabh Jain +--- + drivers/video/fbcmap.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c +index 31e93a5..f26570d 100644 +--- a/drivers/video/fbcmap.c ++++ b/drivers/video/fbcmap.c +@@ -203,11 +203,13 @@ int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to) + fromoff = to->start - from->start; + else + tooff = from->start - to->start; ++ if ((to->len <= tooff) || (from->len <= fromoff)) ++ return -EINVAL; ++ + size = to->len - tooff; ++ + if (size > (int) (from->len - fromoff)) + size = from->len - fromoff; +- if (size <= 0) +- return -EINVAL; + size *= sizeof(u16); + + if (from->red && to->red) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9782/0.patch b/Patches/Linux_CVEs/CVE-2014-9782/0.patch new file mode 100644 index 00000000..7fa4a12a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9782/0.patch @@ -0,0 +1,135 @@ +From 2e57a46ab2ba7299d99d9cdc1382bd1e612963fb Mon Sep 17 00:00:00 2001 +From: Hariram Purushothaman +Date: Wed, 24 Jul 2013 10:42:21 -0700 +Subject: msm: camera: Fix various small issues in Actuator driver + +Bound check and validate userspace parameters direction, +number of steps and direction sign. Also fix possible +memory leak in certain error cases. + +CRs-Fixed: 511349 +Change-Id: Icaa324468574494fb40f2de78e522090806744cb +Signed-off-by: Hariram Purushothaman +--- + .../msm/camera_v2/sensor/actuator/msm_actuator.c | 40 +++++++++++++++++++--- + include/media/msm_cam_sensor.h | 4 +++ + 2 files changed, 40 insertions(+), 4 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 87178b7..fe2c16f 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 +@@ -245,6 +245,20 @@ static int32_t msm_actuator_move_focus( + if (dest_step_pos == a_ctrl->curr_step_pos) + return rc; + ++ if ((sign_dir > MSM_ACTUATOR_MOVE_SIGNED_NEAR) || ++ (sign_dir < MSM_ACTUATOR_MOVE_SIGNED_FAR)) { ++ pr_err("Invalid sign_dir = %d\n", sign_dir); ++ return -EFAULT; ++ } ++ if ((dir > MOVE_FAR) || (dir < MOVE_NEAR)) { ++ pr_err("Invalid direction = %d\n", dir); ++ return -EFAULT; ++ } ++ if (dest_step_pos > a_ctrl->total_steps) { ++ pr_err("Step pos greater than total steps = %d\n", ++ dest_step_pos); ++ return -EFAULT; ++ } + curr_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos]; + a_ctrl->i2c_tbl_index = 0; + CDBG("curr_step_pos =%d dest_step_pos =%d curr_lens_pos=%d\n", +@@ -318,6 +332,12 @@ static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl, + kfree(a_ctrl->step_position_table); + a_ctrl->step_position_table = NULL; + ++ if (set_info->af_tuning_params.total_steps ++ > MAX_ACTUATOR_AF_TOTAL_STEPS) { ++ pr_err("Max actuator totalsteps exceeded = %d\n", ++ set_info->af_tuning_params.total_steps); ++ return -EFAULT; ++ } + /* Fill step position table */ + a_ctrl->step_position_table = + kmalloc(sizeof(uint16_t) * +@@ -409,12 +429,19 @@ static int32_t msm_actuator_init(struct msm_actuator_ctrl_t *a_ctrl, + pr_err("Actuator function table not found\n"); + return rc; + } +- +- a_ctrl->region_size = set_info->af_tuning_params.region_size; +- if (a_ctrl->region_size > MAX_ACTUATOR_REGION) { ++ if (set_info->af_tuning_params.total_steps ++ > MAX_ACTUATOR_AF_TOTAL_STEPS) { ++ pr_err("Max actuator totalsteps exceeded = %d\n", ++ set_info->af_tuning_params.total_steps); ++ return -EFAULT; ++ } ++ if (set_info->af_tuning_params.region_size ++ > MAX_ACTUATOR_REGION) { + pr_err("MAX_ACTUATOR_REGION is exceeded.\n"); + return -EFAULT; + } ++ ++ a_ctrl->region_size = set_info->af_tuning_params.region_size; + a_ctrl->pwd_step = set_info->af_tuning_params.pwd_step; + a_ctrl->total_steps = set_info->af_tuning_params.total_steps; + +@@ -461,7 +488,9 @@ static int32_t msm_actuator_init(struct msm_actuator_ctrl_t *a_ctrl, + return -EFAULT; + } + +- if (set_info->actuator_params.init_setting_size) { ++ if (set_info->actuator_params.init_setting_size && ++ set_info->actuator_params.init_setting_size ++ <= MAX_ACTUATOR_REG_TBL_SIZE) { + if (a_ctrl->func_tbl->actuator_init_focus) { + init_settings = kmalloc(sizeof(struct reg_settings_t) * + (set_info->actuator_params.init_setting_size), +@@ -793,6 +822,7 @@ static int32_t msm_actuator_platform_probe(struct platform_device *pdev) + &pdev->id); + CDBG("cell-index %d, rc %d\n", pdev->id, rc); + if (rc < 0) { ++ kfree(msm_actuator_t); + pr_err("failed rc %d\n", rc); + return rc; + } +@@ -801,6 +831,7 @@ static int32_t msm_actuator_platform_probe(struct platform_device *pdev) + &msm_actuator_t->cci_master); + CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t->cci_master, rc); + if (rc < 0) { ++ kfree(msm_actuator_t); + pr_err("failed rc %d\n", rc); + return rc; + } +@@ -817,6 +848,7 @@ static int32_t msm_actuator_platform_probe(struct platform_device *pdev) + msm_actuator_t->i2c_client.cci_client = kzalloc(sizeof( + struct msm_camera_cci_client), GFP_KERNEL); + if (!msm_actuator_t->i2c_client.cci_client) { ++ kfree(msm_actuator_t); + pr_err("failed no memory\n"); + return -ENOMEM; + } +diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h +index 326e8bf..08a2025 100644 +--- a/include/media/msm_cam_sensor.h ++++ b/include/media/msm_cam_sensor.h +@@ -40,10 +40,14 @@ + #define MAX_ACTUATOR_REGION 5 + #define MAX_ACTUATOR_INIT_SET 12 + #define MAX_ACTUATOR_REG_TBL_SIZE 8 ++#define MAX_ACTUATOR_AF_TOTAL_STEPS 1024 + + #define MOVE_NEAR 0 + #define MOVE_FAR 1 + ++#define MSM_ACTUATOR_MOVE_SIGNED_FAR -1 ++#define MSM_ACTUATOR_MOVE_SIGNED_NEAR 1 ++ + #define MAX_EEPROM_NAME 32 + + #define MAX_AF_ITERATIONS 3 +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9783/0.patch b/Patches/Linux_CVEs/CVE-2014-9783/0.patch new file mode 100644 index 00000000..bcb90e1e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9783/0.patch @@ -0,0 +1,218 @@ +From 2b1050b49a9a5f7bb57006648d145e001a3eaa8b Mon Sep 17 00:00:00 2001 +From: Hariram Purushothaman +Date: Wed, 31 Jul 2013 14:30:36 -0700 +Subject: msm: camera: Fix various small issues in cci driver + +Remove some unused ioctl exposed, Also add +some bound checks for ioctl user params. + +Change-Id: Ifdd441fdb25fd20b005c4e4e1ebe4e203f1216ac +CRs-Fixed: 511382 +Signed-off-by: Hariram Purushothaman +--- + .../platform/msm/camera_v2/sensor/cci/msm_cci.c | 101 +++++++++++++-------- + include/media/msm_cam_sensor.h | 2 + + 2 files changed, 63 insertions(+), 40 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 7f4f231..6beb92e 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 +@@ -41,6 +41,9 @@ + + /* Max bytes that can be read per CCI read transaction */ + #define CCI_READ_MAX 12 ++#define CCI_I2C_READ_MAX_RETRIES 3 ++#define CCI_I2C_MAX_READ 8192 ++#define CCI_I2C_MAX_WRITE 8192 + + static struct v4l2_subdev *g_cci_subdev; + +@@ -87,36 +90,6 @@ static void msm_cci_set_clk_param(struct cci_device *cci_dev) + return; + } + +-static int32_t msm_cci_i2c_config_sync_timer(struct v4l2_subdev *sd, +- struct msm_camera_cci_ctrl *c_ctrl) +-{ +- struct cci_device *cci_dev; +- cci_dev = v4l2_get_subdevdata(sd); +- msm_camera_io_w(c_ctrl->cci_info->cid, cci_dev->base + +- CCI_SET_CID_SYNC_TIMER_0_ADDR + (c_ctrl->cci_info->cid * 0x4)); +- return 0; +-} +- +-static int32_t msm_cci_i2c_set_freq(struct v4l2_subdev *sd, +- struct msm_camera_cci_ctrl *c_ctrl) +-{ +- struct cci_device *cci_dev; +- uint32_t val; +- cci_dev = v4l2_get_subdevdata(sd); +- val = c_ctrl->cci_info->freq; +- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR + +- c_ctrl->cci_info->cci_i2c_master*0x100); +- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR + +- c_ctrl->cci_info->cci_i2c_master*0x100); +- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR + +- c_ctrl->cci_info->cci_i2c_master*0x100); +- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR + +- c_ctrl->cci_info->cci_i2c_master*0x100); +- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR + +- c_ctrl->cci_info->cci_i2c_master*0x100); +- return 0; +-} +- + static void msm_cci_flush_queue(struct cci_device *cci_dev, + enum cci_i2c_master_t master) + { +@@ -213,8 +186,29 @@ static int32_t msm_cci_data_queue(struct cci_device *cci_dev, + uint16_t cmd_size = i2c_msg->size; + struct msm_camera_i2c_reg_conf *i2c_cmd = i2c_msg->reg_conf_tbl; + enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; ++ ++ if (i2c_cmd == NULL) { ++ pr_err("%s:%d Failed line\n", __func__, ++ __LINE__); ++ return -EINVAL; ++ } ++ ++ if ((!cmd_size) || (cmd_size > CCI_I2C_MAX_WRITE)) { ++ pr_err("%s:%d Failed line\n", __func__, __LINE__); ++ return -EINVAL; ++ } ++ + CDBG("%s addr type %d data type %d\n", __func__, + i2c_msg->addr_type, i2c_msg->data_type); ++ ++ if (i2c_msg->addr_type >= MSM_CAMERA_I2C_ADDR_TYPE_MAX) { ++ pr_err("%s failed line %d\n", __func__, __LINE__); ++ return -EINVAL; ++ } ++ if (i2c_msg->data_type >= MSM_CAMERA_I2C_DATA_TYPE_MAX) { ++ pr_err("%s failed line %d\n", __func__, __LINE__); ++ return -EINVAL; ++ } + /* assume total size within the max queue */ + while (cmd_size) { + CDBG("%s cmd_size %d addr 0x%x data 0x%x", __func__, +@@ -321,6 +315,18 @@ static int32_t msm_cci_i2c_read(struct v4l2_subdev *sd, + goto ERROR; + } + ++ if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) { ++ pr_err("%s:%d More than max retries\n", __func__, ++ __LINE__); ++ goto ERROR; ++ } ++ ++ if (read_cfg->data == NULL) { ++ pr_err("%s:%d Data ptr is NULL\n", __func__, ++ __LINE__); ++ goto ERROR; ++ } ++ + CDBG("%s master %d, queue %d\n", __func__, master, queue); + CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__, + c_ctrl->cci_info->sid, c_ctrl->cci_info->retries, +@@ -341,6 +347,11 @@ static int32_t msm_cci_i2c_read(struct v4l2_subdev *sd, + goto ERROR; + } + ++ if (read_cfg->addr_type >= MSM_CAMERA_I2C_ADDR_TYPE_MAX) { ++ CDBG("%s failed line %d\n", __func__, __LINE__); ++ goto ERROR; ++ } ++ + if (read_cfg->addr_type == MSM_CAMERA_I2C_BYTE_ADDR) + val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4) | + ((read_cfg->addr & 0xFF) << 8); +@@ -454,9 +465,14 @@ static int32_t msm_cci_i2c_read_bytes(struct v4l2_subdev *sd, + return -EINVAL; + } + ++ if (c_ctrl->cci_info->cci_i2c_master > MASTER_MAX) { ++ pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__); ++ return -EINVAL; ++ } ++ + master = c_ctrl->cci_info->cci_i2c_master; + read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg; +- if (!read_cfg->num_byte) { ++ if ((!read_cfg->num_byte) || (read_cfg->num_byte > CCI_I2C_MAX_READ)) { + pr_err("%s:%d read num bytes 0\n", __func__, __LINE__); + rc = -EINVAL; + goto ERROR; +@@ -494,6 +510,10 @@ static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd, + enum cci_i2c_master_t master; + enum cci_i2c_queue_t queue = QUEUE_0; + cci_dev = v4l2_get_subdevdata(sd); ++ if (c_ctrl->cci_info->cci_i2c_master > MASTER_MAX) { ++ pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__); ++ return -EINVAL; ++ } + master = c_ctrl->cci_info->cci_i2c_master; + CDBG("%s master %d, queue %d\n", __func__, master, queue); + CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__, +@@ -514,6 +534,11 @@ static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd, + __LINE__, rc); + goto ERROR; + } ++ if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) { ++ pr_err("%s:%d More than max retries\n", __func__, ++ __LINE__); ++ goto ERROR; ++ } + + val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 | + c_ctrl->cci_info->retries << 16 | +@@ -533,7 +558,11 @@ static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd, + goto ERROR; + } + +- msm_cci_data_queue(cci_dev, c_ctrl, queue); ++ rc = msm_cci_data_queue(cci_dev, c_ctrl, queue); ++ if (rc < 0) { ++ CDBG("%s failed line %d\n", __func__, __LINE__); ++ goto ERROR; ++ } + val = CCI_I2C_UNLOCK_CMD; + CDBG("%s:%d CCI_I2C_UNLOCK_CMD\n", __func__, __LINE__); + rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue); +@@ -703,14 +732,6 @@ static int32_t msm_cci_config(struct v4l2_subdev *sd, + case MSM_CCI_RELEASE: + rc = msm_cci_release(sd); + break; +- case MSM_CCI_SET_SID: +- break; +- case MSM_CCI_SET_FREQ: +- rc = msm_cci_i2c_set_freq(sd, cci_ctrl); +- break; +- case MSM_CCI_SET_SYNC_CID: +- rc = msm_cci_i2c_config_sync_timer(sd, cci_ctrl); +- break; + case MSM_CCI_I2C_READ: + rc = msm_cci_i2c_read_bytes(sd, cci_ctrl); + break; +diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h +index 2805401..da16bb8 100644 +--- a/include/media/msm_cam_sensor.h ++++ b/include/media/msm_cam_sensor.h +@@ -52,6 +52,7 @@ enum msm_camera_i2c_reg_addr_type { + MSM_CAMERA_I2C_BYTE_ADDR = 1, + MSM_CAMERA_I2C_WORD_ADDR, + MSM_CAMERA_I2C_3B_ADDR, ++ MSM_CAMERA_I2C_ADDR_TYPE_MAX, + }; + + enum msm_camera_i2c_data_type { +@@ -62,6 +63,7 @@ enum msm_camera_i2c_data_type { + MSM_CAMERA_I2C_SET_WORD_MASK, + MSM_CAMERA_I2C_UNSET_WORD_MASK, + MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA, ++ MSM_CAMERA_I2C_DATA_TYPE_MAX, + }; + + enum msm_sensor_power_seq_type_t { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9784/0.patch b/Patches/Linux_CVEs/CVE-2014-9784/0.patch new file mode 100644 index 00000000..7314dbab --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9784/0.patch @@ -0,0 +1,203 @@ +From 36503d639cedcc73880974ed92132247576e72ba Mon Sep 17 00:00:00 2001 +From: Sreelakshmi Gownipalli +Date: Tue, 14 Jan 2014 16:54:46 -0800 +Subject: diag: Fix for diag debugfs buffer overflow + +Diag debugfs buffer has potential buffer overflow scenario which can cause +memory corruption. Added safeguard to prevent this. + +Crs-fixed: 585147 +Change-Id: Ie1f099bb4bb626adff99ae225966aef70c1bc15e +Signed-off-by: Sreelakshmi Gownipalli +--- + drivers/char/diag/diag_debugfs.c | 44 +++++++++++++++++++++++++--------------- + 1 file changed, 28 insertions(+), 16 deletions(-) + +diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c +index d63d34b..96c0fa0 100644 +--- a/drivers/char/diag/diag_debugfs.c ++++ b/drivers/char/diag/diag_debugfs.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2014, The 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 +@@ -33,14 +33,14 @@ static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf, + { + char *buf; + int ret; +- ++ unsigned int buf_size; + buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + if (!buf) { + pr_err("diag: %s, Error allocating memory\n", __func__); + return -ENOMEM; + } +- +- ret = scnprintf(buf, DEBUG_BUF_SIZE, ++ buf_size = ksize(buf); ++ ret = scnprintf(buf, buf_size, + "modem ch: 0x%p\n" + "lpass ch: 0x%p\n" + "riva ch: 0x%p\n" +@@ -183,7 +183,7 @@ static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf, + driver->real_time_mode); + + #ifdef CONFIG_DIAG_OVER_USB +- ret += scnprintf(buf+ret, DEBUG_BUF_SIZE, ++ ret += scnprintf(buf+ret, buf_size-ret, + "usb_connected: %d\n", + driver->usb_connected); + #endif +@@ -200,7 +200,8 @@ static ssize_t diag_dbgfs_read_dcistats(struct file *file, + unsigned int bytes_remaining, bytes_written = 0; + unsigned int bytes_in_buf = 0, i = 0; + struct diag_dci_data_info *temp_data = dci_data_smd; +- int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; ++ unsigned int buf_size; ++ buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; + + if (diag_dbgfs_dci_finished) { + diag_dbgfs_dci_finished = 0; +@@ -213,6 +214,7 @@ static ssize_t diag_dbgfs_read_dcistats(struct file *file, + return -ENOMEM; + } + ++ buf_size = ksize(buf); + bytes_remaining = buf_size; + + if (diag_dbgfs_dci_data_index == 0) { +@@ -281,6 +283,7 @@ static ssize_t diag_dbgfs_read_workpending(struct file *file, + { + char *buf; + int ret; ++ unsigned int buf_size; + + buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + if (!buf) { +@@ -288,7 +291,8 @@ static ssize_t diag_dbgfs_read_workpending(struct file *file, + return -ENOMEM; + } + +- ret = scnprintf(buf, DEBUG_BUF_SIZE, ++ buf_size = ksize(buf); ++ ret = scnprintf(buf, buf_size, + "Pending status for work_stucts:\n" + "diag_drain_work: %d\n" + "Modem data diag_read_smd_work: %d\n" +@@ -336,7 +340,7 @@ static ssize_t diag_dbgfs_read_workpending(struct file *file, + diag_notify_update_smd_work))); + + #ifdef CONFIG_DIAG_OVER_USB +- ret += scnprintf(buf+ret, DEBUG_BUF_SIZE, ++ ret += scnprintf(buf+ret, buf_size-ret, + "diag_proc_hdlc_work: %d\n" + "diag_read_work: %d\n", + work_pending(&(driver->diag_proc_hdlc_work)), +@@ -357,7 +361,8 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + unsigned int bytes_remaining; + unsigned int bytes_in_buffer = 0; + unsigned int bytes_written; +- int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; ++ unsigned int buf_size; ++ buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; + + if (diag_dbgfs_table_index >= diag_max_reg) { + /* Done. Reset to prepare for future requests */ +@@ -370,7 +375,7 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + pr_err("diag: %s, Error allocating memory\n", __func__); + return -ENOMEM; + } +- ++ buf_size = ksize(buf); + bytes_remaining = buf_size; + + if (diag_dbgfs_table_index == 0) { +@@ -379,6 +384,7 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + "WCNSS: %d, APPS: %d\n", + MODEM_DATA, LPASS_DATA, WCNSS_DATA, APPS_DATA); + bytes_in_buffer += bytes_written; ++ bytes_remaining -= bytes_written; + } + + for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) { +@@ -422,14 +428,15 @@ static ssize_t diag_dbgfs_read_mempool(struct file *file, char __user *ubuf, + { + char *buf = NULL; + int ret = 0, i = 0; +- ++ unsigned int buf_size; + buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + if (ZERO_OR_NULL_PTR(buf)) { + pr_err("diag: %s, Error allocating memory\n", __func__); + return -ENOMEM; + } ++ buf_size = ksize(buf); + +- ret = scnprintf(buf, DEBUG_BUF_SIZE, ++ ret = scnprintf(buf, buf_size, + "POOL_TYPE_COPY: [0x%p : 0x%p] count = %d\n" + "POOL_TYPE_HDLC: [0x%p : 0x%p] count = %d\n" + "POOL_TYPE_USER: [0x%p : 0x%p] count = %d\n" +@@ -454,7 +461,7 @@ static ssize_t diag_dbgfs_read_mempool(struct file *file, char __user *ubuf, + for (i = 0; i < MAX_HSIC_CH; i++) { + if (!diag_hsic[i].hsic_inited) + continue; +- ret += scnprintf(buf+ret, DEBUG_BUF_SIZE-ret, ++ ret += scnprintf(buf+ret, buf_size-ret, + "POOL_TYPE_HSIC_%d: [0x%p : 0x%p] count = %d\n", + i+1, + diag_hsic[i].diag_hsic_pool, +@@ -465,7 +472,7 @@ static ssize_t diag_dbgfs_read_mempool(struct file *file, char __user *ubuf, + for (i = 0; i < MAX_HSIC_CH; i++) { + if (!diag_hsic[i].hsic_inited) + continue; +- ret += scnprintf(buf+ret, DEBUG_BUF_SIZE-ret, ++ ret += scnprintf(buf+ret, buf_size-ret, + "POOL_TYPE_HSIC_%d_WRITE: [0x%p : 0x%p] count = %d\n", + i+1, + diag_hsic[i].diag_hsic_write_pool, +@@ -484,6 +491,7 @@ static ssize_t diag_dbgfs_read_mempool(struct file *file, char __user *ubuf, + { + char *buf = NULL; + int ret = 0; ++ unsigned int buf_size; + + buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + if (ZERO_OR_NULL_PTR(buf)) { +@@ -491,7 +499,8 @@ static ssize_t diag_dbgfs_read_mempool(struct file *file, char __user *ubuf, + return -ENOMEM; + } + +- ret = scnprintf(buf, DEBUG_BUF_SIZE, ++ buf_size = ksize(buf); ++ ret = scnprintf(buf, buf_size, + "POOL_TYPE_COPY: [0x%p : 0x%p] count = %d\n" + "POOL_TYPE_HDLC: [0x%p : 0x%p] count = %d\n" + "POOL_TYPE_USER: [0x%p : 0x%p] count = %d\n" +@@ -530,10 +539,12 @@ static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf, + unsigned int bytes_remaining; + unsigned int bytes_in_buffer = 0; + unsigned int bytes_written; +- int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; ++ unsigned int buf_size; + int bytes_hsic_inited = 45; + int bytes_hsic_not_inited = 410; + ++ buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; ++ + if (diag_dbgfs_finished) { + diag_dbgfs_finished = 0; + return 0; +@@ -545,6 +556,7 @@ static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf, + return -ENOMEM; + } + ++ buf_size = ksize(buf); + bytes_remaining = buf_size; + + /* Only one smux for now */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9785/0.patch b/Patches/Linux_CVEs/CVE-2014-9785/0.patch new file mode 100644 index 00000000..d2831804 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9785/0.patch @@ -0,0 +1,66 @@ +From b4338420db61f029ca6713a89c41b3a5852b20ce Mon Sep 17 00:00:00 2001 +From: Hariprasad Dhalinarasimha +Date: Tue, 1 Oct 2013 18:25:21 -0700 +Subject: qseecom: Change __copy_from_user to copy_from_user + +__copy_from_user does not do address check, so use +copy_from_user instead. + +Change-Id: I575c0f3c44b55a521c0d42828988c518c0640a29 +Signed-off-by: Hariprasad Dhalinarasimha +--- + drivers/misc/qseecom.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 04fe140..8e9731f 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -431,7 +431,7 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data, + uint32_t len; + + /* Copy the relevant information needed for loading the image */ +- if (__copy_from_user(&req, (void __user *)argp, sizeof(req))) ++ if (copy_from_user(&req, (void __user *)argp, sizeof(req))) + return -EFAULT; + + /* Get the handle of the shared fd */ +@@ -604,7 +604,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) + struct qseecom_load_app_ireq load_req; + + /* Copy the relevant information needed for loading the image */ +- if (__copy_from_user(&load_img_req, ++ if (copy_from_user(&load_img_req, + (void __user *)argp, + sizeof(struct qseecom_load_img_req))) { + pr_err("copy_from_user failed\n"); +@@ -875,7 +875,7 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, + struct qseecom_send_svc_cmd_req req; + /*struct qseecom_command_scm_resp resp;*/ + +- if (__copy_from_user(&req, ++ if (copy_from_user(&req, + (void __user *)argp, + sizeof(req))) { + pr_err("copy_from_user failed\n"); +@@ -2086,7 +2086,7 @@ static int qseecom_load_external_elf(struct qseecom_dev_handle *data, + struct qseecom_command_scm_resp resp; + + /* Copy the relevant information needed for loading the image */ +- if (__copy_from_user(&load_img_req, ++ if (copy_from_user(&load_img_req, + (void __user *)argp, + sizeof(struct qseecom_load_img_req))) { + pr_err("copy_from_user failed\n"); +@@ -2248,7 +2248,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, + unsigned long flags = 0; + + /* Copy the relevant information needed for loading the image */ +- if (__copy_from_user(&query_req, ++ if (copy_from_user(&query_req, + (void __user *)argp, + sizeof(struct qseecom_qseos_app_load_query))) { + pr_err("copy_from_user failed\n"); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9786/0.patch b/Patches/Linux_CVEs/CVE-2014-9786/0.patch new file mode 100644 index 00000000..4832ad38 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9786/0.patch @@ -0,0 +1,48 @@ +From 2fb303d9c6ca080f253b10ed9384293ca69ad32b Mon Sep 17 00:00:00 2001 +From: Vasko Kalanoski +Date: Tue, 8 Oct 2013 10:50:32 -0700 +Subject: msm: actuator: fix to prevent kernel heap buffer overflow + +fix to prevent kernel heap buffer overflow allows user +controlled data to be written to the heap via the +msm_camera actuator IOCTLs + +Change-Id: I4458831e28e0081fb2f5ae55506be866100e1b4f +Signed-off-by: Vasko Kalanoski +--- + .../platform/msm/camera_v2/sensor/actuator/msm_actuator.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 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..e605326 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 +@@ -79,6 +79,11 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl, + struct msm_camera_i2c_reg_array *i2c_tbl = a_ctrl->i2c_reg_tbl; + CDBG("Enter\n"); + for (i = 0; i < size; i++) { ++ /* check that the index into i2c_tbl cannot grow larger that ++ the allocated size of i2c_tbl */ ++ if ((a_ctrl->total_steps + 1) < (a_ctrl->i2c_tbl_index)) { ++ break; ++ } + if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) { + value = (next_lens_position << + write_arr[i].data_shift) | +@@ -464,8 +469,11 @@ static int32_t msm_actuator_init(struct msm_actuator_ctrl_t *a_ctrl, + + a_ctrl->i2c_data_type = set_info->actuator_params.i2c_data_type; + a_ctrl->i2c_client.addr_type = set_info->actuator_params.i2c_addr_type; +- a_ctrl->reg_tbl_size = set_info->actuator_params.reg_tbl_size; +- if (a_ctrl->reg_tbl_size > MAX_ACTUATOR_REG_TBL_SIZE) { ++ if (set_info->actuator_params.reg_tbl_size <= ++ MAX_ACTUATOR_REG_TBL_SIZE) { ++ a_ctrl->reg_tbl_size = set_info->actuator_params.reg_tbl_size; ++ } else { ++ a_ctrl->reg_tbl_size = 0; + pr_err("MAX_ACTUATOR_REG_TBL_SIZE is exceeded.\n"); + return -EFAULT; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9787/0.patch b/Patches/Linux_CVEs/CVE-2014-9787/0.patch new file mode 100644 index 00000000..3385d66e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9787/0.patch @@ -0,0 +1,43 @@ +From 528400ae4cba715f6c9ff4a2657dafd913f30b8b Mon Sep 17 00:00:00 2001 +From: Hariprasad Dhalinarasimha +Date: Thu, 3 Oct 2013 16:43:39 -0700 +Subject: qseecom: Validate the incoming length from user space + +Check if there is no integer overflow before using req_len and +resp_len (received from user space). If an overflow is detected +then exit the operation. + +Change-Id: I0459a6992bb3b280db42be63a275c55fa6105b1c +Signed-off-by: Hariprasad Dhalinarasimha +--- + drivers/misc/qseecom.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 58703cf..1452908 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -961,6 +961,11 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + return -EINVAL; + } + ++ if (req->cmd_req_len > UINT_MAX - req->resp_len) { ++ pr_err("Integer overflow detected in req_len & rsp_len, exiting now\n"); ++ return -EINVAL; ++ } ++ + reqd_len_sb_in = req->cmd_req_len + req->resp_len; + if (reqd_len_sb_in > data->client.sb_length) { + pr_debug("Not enough memory to fit cmd_buf and " +@@ -980,7 +985,7 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + + msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + data->client.sb_virt, +- (req->cmd_req_len + req->resp_len), ++ reqd_len_sb_in, + ION_IOC_CLEAN_INV_CACHES); + + ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *) &send_data_req, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9788/0.patch b/Patches/Linux_CVEs/CVE-2014-9788/0.patch new file mode 100644 index 00000000..6453d7aa --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9788/0.patch @@ -0,0 +1,194 @@ +From 73bfc22aa70cc0b7e6709381125a0a42aa72a4f2 Mon Sep 17 00:00:00 2001 +From: Shiv Maliyappanahalli +Date: Wed, 2 Oct 2013 17:00:30 -0700 +Subject: ASoC: msm: qdsp6v2: Fix buffer overflow in voice driver + +Userspace registers calibration data with acdb driver +through ioctls. Voice driver registers the calibration +data with CVD by querying acdb data from acdb driver and +copies the calibration data in apr message. + +The size of the calibration data can be controlled by userspace +and can result in buffer overflow if the calibration size is +greater than the destination buffer size. + +Reject acdb data if the size is greater than the size of +destination buffer. + +CRs-Fixed: 548872 +Change-Id: I4cd23a38c90b745226ddbc28656c82ff7c10432b +Signed-off-by: Shiv Maliyappanahalli +--- + sound/soc/msm/qdsp6/q6voice.c | 9 ++++--- + sound/soc/msm/qdsp6v2/q6voice.c | 53 ++++++++++++++++++++++++++++++++++------- + 2 files changed, 50 insertions(+), 12 deletions(-) + +diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c +index 0e53c64..7294350 100644 +--- a/sound/soc/msm/qdsp6/q6voice.c ++++ b/sound/soc/msm/qdsp6/q6voice.c +@@ -1519,7 +1519,8 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v) + + /* get the cvs cal data */ + get_all_vocstrm_cal(&cal_block); +- if (cal_block.cal_size == 0) ++ if (cal_block.cal_size == 0 || ++ cal_block.cal_size > CVS_CAL_SIZE) + goto fail; + + if (v == NULL) { +@@ -1928,7 +1929,8 @@ static int voice_send_cvp_register_cal_cmd(struct voice_data *v) + + /* get the cvp cal data */ + get_all_vocproc_cal(&cal_block); +- if (cal_block.cal_size == 0) ++ if (cal_block.cal_size == 0 || ++ cal_block.cal_size > CVP_CAL_SIZE) + goto fail; + + if (v == NULL) { +@@ -2063,7 +2065,8 @@ static int voice_send_cvp_register_vol_cal_table_cmd(struct voice_data *v) + get_all_vocvol_cal(&vol_block); + get_all_vocproc_cal(&voc_block); + +- if (vol_block.cal_size == 0) ++ if (vol_block.cal_size == 0 || ++ vol_block.cal_size > CVP_CAL_SIZE) + goto fail; + + if (v == NULL) { +diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c +index 079cc4d..622fae1 100644 +--- a/sound/soc/msm/qdsp6v2/q6voice.c ++++ b/sound/soc/msm/qdsp6v2/q6voice.c +@@ -1955,20 +1955,22 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v) + if (!common.apr_q6_cvs) { + pr_err("%s: apr_cvs is NULL\n", __func__); + +- ret = -EPERM; ++ ret = -EINVAL; + goto done; + } + + if (!common.cal_mem_handle) { + pr_err("%s: Cal mem handle is NULL\n", __func__); +- ret = -EPERM; ++ ++ ret = -EINVAL; + goto done; + } + + get_vocstrm_cal(&cal_block); + if (cal_block.cal_size == 0) { + pr_err("%s: CVS cal size is 0\n", __func__); +- ret = -EPERM; ++ ++ ret = -EINVAL; + goto done; + } + +@@ -1989,6 +1991,15 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v) + + /* Get the column info corresponding to CVS cal from ACDB. */ + get_voice_col_data(VOCSTRM_CAL, &cal_block); ++ if (cal_block.cal_size == 0 || ++ cal_block.cal_size > ++ sizeof(cvs_reg_cal_cmd.cvs_cal_data.column_info)) { ++ pr_err("%s: Invalid VOCSTRM_CAL size %d\n", ++ __func__, cal_block.cal_size); ++ ++ ret = -EINVAL; ++ goto done; ++ } + memcpy(&cvs_reg_cal_cmd.cvs_cal_data.column_info[0], + (void *) cal_block.cal_kvaddr, + cal_block.cal_size); +@@ -2227,20 +2238,22 @@ static int voice_send_cvp_register_cal_cmd(struct voice_data *v) + if (!common.apr_q6_cvp) { + pr_err("%s: apr_cvp is NULL\n", __func__); + +- ret = -EPERM; ++ ret = -EINVAL; + goto done; + } + + if (!common.cal_mem_handle) { + pr_err("%s: Cal mem handle is NULL\n", __func__); +- ret = -EPERM; ++ ++ ret = -EINVAL; + goto done; + } + + get_vocproc_cal(&cal_block); + if (cal_block.cal_size == 0) { + pr_err("%s: CVP cal size is 0\n", __func__); +- ret = -EPERM; ++ ++ ret = -EINVAL; + goto done; + } + +@@ -2261,6 +2274,16 @@ static int voice_send_cvp_register_cal_cmd(struct voice_data *v) + + /* Get the column info corresponding to CVP cal from ACDB. */ + get_voice_col_data(VOCPROC_CAL, &cal_block); ++ if (cal_block.cal_size == 0 || ++ cal_block.cal_size > ++ sizeof(cvp_reg_cal_cmd.cvp_cal_data.column_info)) { ++ pr_err("%s: Invalid VOCPROC_CAL size %d\n", ++ __func__, cal_block.cal_size); ++ ++ ret = -EINVAL; ++ goto done; ++ } ++ + memcpy(&cvp_reg_cal_cmd.cvp_cal_data.column_info[0], + (void *) cal_block.cal_kvaddr, + cal_block.cal_size); +@@ -2363,20 +2386,22 @@ static int voice_send_cvp_register_vol_cal_cmd(struct voice_data *v) + if (!common.apr_q6_cvp) { + pr_err("%s: apr_cvp is NULL\n", __func__); + +- ret = -EPERM; ++ ret = -EINVAL; + goto done; + } + + if (!common.cal_mem_handle) { + pr_err("%s: Cal mem handle is NULL\n", __func__); +- ret = -EPERM; ++ ++ ret = -EINVAL; + goto done; + } + + get_vocvol_cal(&cal_block); + if (cal_block.cal_size == 0) { + pr_err("%s: CVP vol cal size is 0\n", __func__); +- ret = -EPERM; ++ ++ ret = -EINVAL; + goto done; + } + +@@ -2399,6 +2424,16 @@ static int voice_send_cvp_register_vol_cal_cmd(struct voice_data *v) + + /* Get the column info corresponding to CVP volume cal from ACDB. */ + get_voice_col_data(VOCVOL_CAL, &cal_block); ++ if (cal_block.cal_size == 0 || ++ cal_block.cal_size > ++ sizeof(cvp_reg_vol_cal_cmd.cvp_vol_cal_data.column_info)) { ++ pr_err("%s: Invalid VOCVOL_CAL size %d\n", ++ __func__, cal_block.cal_size); ++ ++ ret = -EINVAL; ++ goto done; ++ } ++ + memcpy(&cvp_reg_vol_cal_cmd.cvp_vol_cal_data.column_info[0], + (void *) cal_block.cal_kvaddr, + cal_block.cal_size); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9789/0.patch b/Patches/Linux_CVEs/CVE-2014-9789/0.patch new file mode 100644 index 00000000..1a5639ba --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9789/0.patch @@ -0,0 +1,105 @@ +From 5720ed5c3a786e3ba0a2428ac45da5d7ec996b4e Mon Sep 17 00:00:00 2001 +From: Gopikrishnaiah Anandan +Date: Fri, 16 Aug 2013 17:34:21 -0400 +Subject: Soc: msm: qdsp6v2: Fix invalid params handling + +Alloc and free apis should sanity check all input params. +If allocation fails set client and ion handle to NULL. + +Change-Id: Ide3bd782eb90ee8b033e39de232929a1ca7174b7 +Signed-off-by: Gopikrishnaiah Anandan +--- + arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c +index 0c71659..f9e9d6d 100644 +--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c ++++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c +@@ -53,7 +53,11 @@ int msm_audio_ion_alloc(const char *name, struct ion_client **client, + pr_debug("%s:probe is not done, deferred\n", __func__); + return -EPROBE_DEFER; + } +- ++ if (!name || !client || !handle || !paddr || !vaddr ++ || !bufsz || !pa_len) { ++ pr_err("%s: Invalid params\n", __func__); ++ return -EINVAL; ++ } + *client = msm_audio_ion_client_create(UINT_MAX, name); + if (IS_ERR_OR_NULL((void *)(*client))) { + pr_err("%s: ION create client for AUDIO failed\n", __func__); +@@ -102,9 +106,9 @@ int msm_audio_ion_alloc(const char *name, struct ion_client **client, + + err_ion_handle: + ion_free(*client, *handle); +- *handle = NULL; + err_ion_client: + msm_audio_ion_client_destroy(*client); ++ *handle = NULL; + *client = NULL; + err: + return -EINVAL; +@@ -116,10 +120,17 @@ int msm_audio_ion_import(const char *name, struct ion_client **client, + ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr) + { + int rc = 0; ++ if (!name || !client || !handle || !ionflag || !paddr || !vaddr ++ || !bufsz || !pa_len) { ++ pr_err("%s: Invalid params\n", __func__); ++ rc = -EINVAL; ++ goto err; ++ } + + *client = msm_audio_ion_client_create(UINT_MAX, name); + if (IS_ERR_OR_NULL((void *)(*client))) { + pr_err("%s: ION create client for AUDIO failed\n", __func__); ++ rc = -EINVAL; + goto err; + } + +@@ -132,8 +143,9 @@ int msm_audio_ion_import(const char *name, struct ion_client **client, + if (IS_ERR_OR_NULL((void *) (*handle))) { + pr_err("%s: ion import dma buffer failed\n", + __func__); +- goto err_ion_handle; +- } ++ rc = -EINVAL; ++ goto err_destroy_client; ++ } + + if (ionflag != NULL) { + rc = ion_handle_get_flags(*client, *handle, ionflag); +@@ -154,6 +166,7 @@ int msm_audio_ion_import(const char *name, struct ion_client **client, + *vaddr = ion_map_kernel(*client, *handle); + if (IS_ERR_OR_NULL((void *)*vaddr)) { + pr_err("%s: ION memory mapping for AUDIO failed\n", __func__); ++ rc = -ENOMEM; + goto err_ion_handle; + } + pr_debug("%s: mapped address = %p, size=%d\n", __func__, *vaddr, bufsz); +@@ -162,13 +175,20 @@ int msm_audio_ion_import(const char *name, struct ion_client **client, + + err_ion_handle: + ion_free(*client, *handle); ++err_destroy_client: + msm_audio_ion_client_destroy(*client); ++ *client = NULL; ++ *handle = NULL; + err: +- return -EINVAL; ++ return rc; + } + + int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle) + { ++ if (!client || !handle) { ++ pr_err("%s Invalid params\n", __func__); ++ return -EINVAL; ++ } + if (msm_audio_ion_data.smmu_enabled) { + /* Need to populate book kept infomation */ + pr_debug("client=%p, domain=%p, domain_id=%d, group=%p", +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9790/0.patch b/Patches/Linux_CVEs/CVE-2014-9790/0.patch new file mode 100644 index 00000000..2ff79139 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9790/0.patch @@ -0,0 +1,64 @@ +From 6ed921bda8cbb505e8654dfc1095185b0bccc38e Mon Sep 17 00:00:00 2001 +From: Raviv Shvili +Date: Tue, 1 Oct 2013 17:18:29 +0300 +Subject: mmc: core : fix arbitrary read/write to user space + +In the MMC card debug_fs the read and write handlers use the strlcat +and sscanf, without checking the pointer given. +Since the pointer is not checked it is possible to write +everywhere (ring 0 or 3). +In order to fix it, an access_ok function is being used to verify +the buffer's pointer supplied by user is valid. + +CRs-fixed: 545716 +Change-Id: Ia710b6af5a95974fc930ca902e8ff18afa4e17ba +Signed-off-by: Raviv Shvili +--- + drivers/mmc/core/debugfs.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c +index 903decf..9897f9f 100644 +--- a/drivers/mmc/core/debugfs.c ++++ b/drivers/mmc/core/debugfs.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -392,6 +393,9 @@ static ssize_t mmc_wr_pack_stats_read(struct file *filp, char __user *ubuf, + if (!card) + return cnt; + ++ if (!access_ok(VERIFY_WRITE, ubuf, cnt)) ++ return cnt; ++ + if (!card->wr_pack_stats.print_in_read) + return 0; + +@@ -532,6 +536,9 @@ static ssize_t mmc_wr_pack_stats_write(struct file *filp, + if (!card) + return cnt; + ++ if (!access_ok(VERIFY_READ, ubuf, cnt)) ++ return cnt; ++ + sscanf(ubuf, "%d", &value); + if (value) { + mmc_blk_init_packed_statistics(card); +@@ -571,6 +578,9 @@ static ssize_t mmc_bkops_stats_read(struct file *filp, char __user *ubuf, + if (!card) + return cnt; + ++ if (!access_ok(VERIFY_WRITE, ubuf, cnt)) ++ return cnt; ++ + bkops_stats = &card->bkops_info.bkops_stats; + + if (!bkops_stats->print_stats) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9792/0.patch b/Patches/Linux_CVEs/CVE-2014-9792/0.patch new file mode 100644 index 00000000..d063f53d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9792/0.patch @@ -0,0 +1,34 @@ +From a3e3dd9fc0a2699ae053ffd3efb52cdc73ad94cd Mon Sep 17 00:00:00 2001 +From: Zaheerulla Meer +Date: Fri, 11 Oct 2013 18:18:35 +0530 +Subject: msm: ipc: Possible memory corruption due to Sign Conversion + +msm_ipc_router_skb_to_buf() takes an unsigned argument and assigns the +same to a signed local variable. This might cause issues when the value +of the argument is too high. + +Change the datatype of the local variable to unsigned. + +CRs-Fixed: 550606 +Change-Id: I257a095681dd82fba05367fd6faf25820e95c719 +Signed-off-by: Zaheerulla Meer +--- + arch/arm/mach-msm/ipc_router.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c +index 9cdad6a1..cb9ad4c 100644 +--- a/arch/arm/mach-msm/ipc_router.c ++++ b/arch/arm/mach-msm/ipc_router.c +@@ -434,7 +434,7 @@ static void *msm_ipc_router_skb_to_buf(struct sk_buff_head *skb_head, + unsigned int len) + { + struct sk_buff *temp; +- int offset = 0, buf_len = 0, copy_len; ++ unsigned int offset = 0, buf_len = 0, copy_len; + void *buf; + + if (!skb_head) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9803/0.patch b/Patches/Linux_CVEs/CVE-2014-9803/0.patch new file mode 100644 index 00000000..408e8ea9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9803/0.patch @@ -0,0 +1,70 @@ +From 5a0fdfada3a2aa50d7b947a2e958bf00cbe0d830 Mon Sep 17 00:00:00 2001 +From: Catalin Marinas +Date: Fri, 16 May 2014 16:44:32 +0100 +Subject: Revert "arm64: Introduce execute-only page access permissions" + +This reverts commit bc07c2c6e9ed125d362af0214b6313dca180cb08. + +While the aim is increased security for --x memory maps, it does not +protect against kernel level reads. Until SECCOMP is implemented for +arm64, revert this patch to avoid giving a false idea of execute-only +mappings. + +Signed-off-by: Catalin Marinas +--- + arch/arm64/include/asm/pgtable.h | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +(limited to 'arch/arm64/include/asm/pgtable.h') + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index e4c60d6..aa150ed 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -86,13 +86,12 @@ extern void __pgd_error(const char *file, int line, unsigned long val); + #define PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) + #define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) + #define PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) +-#define PAGE_EXECONLY __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN) + + #define __P000 PAGE_NONE + #define __P001 PAGE_READONLY + #define __P010 PAGE_COPY + #define __P011 PAGE_COPY +-#define __P100 PAGE_EXECONLY ++#define __P100 PAGE_READONLY_EXEC + #define __P101 PAGE_READONLY_EXEC + #define __P110 PAGE_COPY_EXEC + #define __P111 PAGE_COPY_EXEC +@@ -101,7 +100,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); + #define __S001 PAGE_READONLY + #define __S010 PAGE_SHARED + #define __S011 PAGE_SHARED +-#define __S100 PAGE_EXECONLY ++#define __S100 PAGE_READONLY_EXEC + #define __S101 PAGE_READONLY_EXEC + #define __S110 PAGE_SHARED_EXEC + #define __S111 PAGE_SHARED_EXEC +@@ -137,8 +136,8 @@ extern struct page *empty_zero_page; + #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE)) + #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) + +-#define pte_valid_ng(pte) \ +- ((pte_val(pte) & (PTE_VALID | PTE_NG)) == (PTE_VALID | PTE_NG)) ++#define pte_valid_user(pte) \ ++ ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) + + static inline pte_t pte_wrprotect(pte_t pte) + { +@@ -192,7 +191,7 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); + static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pte) + { +- if (pte_valid_ng(pte)) { ++ if (pte_valid_user(pte)) { + if (!pte_special(pte) && pte_exec(pte)) + __sync_icache_dcache(pte, addr); + if (pte_dirty(pte) && pte_write(pte)) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9863/0.patch b/Patches/Linux_CVEs/CVE-2014-9863/0.patch new file mode 100644 index 00000000..093e6eca --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9863/0.patch @@ -0,0 +1,123 @@ +From 75eac48a48562f819f50eeff8369b296d89102d7 Mon Sep 17 00:00:00 2001 +From: Katish Paran +Date: Tue, 24 Dec 2013 17:46:29 +0530 +Subject: diag: Safeguard for bound checks and integer underflow + +At certain point in diag driver there can be integer underflow +and thus can lead to memory leak. Bound checks are placed to +ensure correct behavior of condition statements. + +Change-Id: I47e02f764c2c7412db6f90fd42192fee32a761d3 +CRs-fixed: 549470 +Signed-off-by: Katish Paran +--- + drivers/char/diag/diag_debugfs.c | 15 ++++++++------- + drivers/char/diag/diagchar_core.c | 15 +++++++++++++-- + drivers/char/diag/diagchar_hdlc.c | 4 ++-- + 3 files changed, 23 insertions(+), 11 deletions(-) + +diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c +index 4bbe948..d63d34b 100644 +--- a/drivers/char/diag/diag_debugfs.c ++++ b/drivers/char/diag/diag_debugfs.c +@@ -197,7 +197,8 @@ static ssize_t diag_dbgfs_read_dcistats(struct file *file, + char __user *ubuf, size_t count, loff_t *ppos) + { + char *buf = NULL; +- int bytes_remaining, bytes_written = 0, bytes_in_buf = 0, i = 0; ++ unsigned int bytes_remaining, bytes_written = 0; ++ unsigned int bytes_in_buf = 0, i = 0; + struct diag_dci_data_info *temp_data = dci_data_smd; + int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; + +@@ -353,9 +354,9 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + char *buf; + int ret = 0; + int i; +- int bytes_remaining; +- int bytes_in_buffer = 0; +- int bytes_written; ++ unsigned int bytes_remaining; ++ unsigned int bytes_in_buffer = 0; ++ unsigned int bytes_written; + int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; + + if (diag_dbgfs_table_index >= diag_max_reg) { +@@ -526,9 +527,9 @@ static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf, + char *buf; + int ret; + int i; +- int bytes_remaining; +- int bytes_in_buffer = 0; +- int bytes_written; ++ unsigned int bytes_remaining; ++ unsigned int bytes_in_buffer = 0; ++ unsigned int bytes_written; + int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count; + int bytes_hsic_inited = 45; + int bytes_hsic_not_inited = 410; +diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c +index 38ca47b..ab68902 100644 +--- a/drivers/char/diag/diagchar_core.c ++++ b/drivers/char/diag/diagchar_core.c +@@ -51,6 +51,7 @@ MODULE_DESCRIPTION("Diag Char Driver"); + MODULE_LICENSE("GPL v2"); + MODULE_VERSION("1.0"); + ++#define MIN_SIZ_ALLOW 4 + #define INIT 1 + #define EXIT -1 + struct diagchar_dev *driver; +@@ -1461,6 +1462,10 @@ static ssize_t diagchar_write(struct file *file, const char __user *buf, + index = 0; + /* Get the packet type F3/log/event/Pkt response */ + err = copy_from_user((&pkt_type), buf, 4); ++ if (err) { ++ pr_alert("diag: copy failed for pkt_type\n"); ++ return -EAGAIN; ++ } + /* First 4 bytes indicate the type of payload - ignore these */ + if (count < 4) { + pr_err("diag: Client sending short data\n"); +@@ -1504,8 +1509,9 @@ static ssize_t diagchar_write(struct file *file, const char __user *buf, + return err; + } + if (pkt_type == CALLBACK_DATA_TYPE) { +- if (payload_size > driver->itemsize) { +- pr_err("diag: Dropping packet, packet payload size crosses 4KB limit. Current payload size %d\n", ++ if (payload_size > driver->itemsize || ++ payload_size <= MIN_SIZ_ALLOW) { ++ pr_err("diag: Dropping packet, invalid packet size. Current payload size %d\n", + payload_size); + driver->dropped_count++; + return -EBADMSG; +@@ -1639,6 +1645,11 @@ static ssize_t diagchar_write(struct file *file, const char __user *buf, + diag_get_remote(*(int *)driver->user_space_data_buf); + + if (remote_proc) { ++ if (payload_size <= MIN_SIZ_ALLOW) { ++ pr_err("diag: Integer underflow in %s, payload size: %d", ++ __func__, payload_size); ++ return -EBADMSG; ++ } + token_offset = 4; + payload_size -= 4; + buf += 4; +diff --git a/drivers/char/diag/diagchar_hdlc.c b/drivers/char/diag/diagchar_hdlc.c +index d5ba452..39f1f44 100644 +--- a/drivers/char/diag/diagchar_hdlc.c ++++ b/drivers/char/diag/diagchar_hdlc.c +@@ -177,8 +177,8 @@ int diag_hdlc_decode(struct diag_hdlc_decode_type *hdlc) + int msg_start; + + if (hdlc && hdlc->src_ptr && hdlc->dest_ptr && +- (hdlc->src_size - hdlc->src_idx > 0) && +- (hdlc->dest_size - hdlc->dest_idx > 0)) { ++ (hdlc->src_size > hdlc->src_idx) && ++ (hdlc->dest_size > hdlc->dest_idx)) { + + msg_start = (hdlc->src_idx == 0) ? 1 : 0; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9864/0.patch b/Patches/Linux_CVEs/CVE-2014-9864/0.patch new file mode 100644 index 00000000..b166953a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9864/0.patch @@ -0,0 +1,343 @@ +From a1124defc680055e2f2a8c8e3da4a94ca2ec842e Mon Sep 17 00:00:00 2001 +From: Mona Hossain +Date: Tue, 1 Oct 2013 13:41:09 -0700 +Subject: qseecom: Add checks for API called in IOCTL + +Validate the caller is the right type for the IOCTL being +issued and inputs are valid. + +Change-Id: Iad71f0f5ed4d53c5d011bd55cdf74ec053d09af5 +Signed-off-by: Mona Hossain +Signed-off-by: Hariprasad Dhalinarasimha +--- + drivers/misc/qseecom.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 159 insertions(+), 6 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 7cc1c9f..51f0228 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -434,6 +434,12 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data, + if (copy_from_user(&req, (void __user *)argp, sizeof(req))) + return -EFAULT; + ++ if ((req.ifd_data_fd <= 0) || (req.virt_sb_base == 0) || ++ (req.sb_len == 0)) { ++ pr_err("Inavlid input(s)ion_fd(%d), sb_len(%d), vaddr(0x%x)\n", ++ req.ifd_data_fd, req.sb_len, req.virt_sb_base); ++ return -EFAULT; ++ } + /* Get the handle of the shared fd */ + data->client.ihandle = ion_import_dma_buf(qseecom.ion_clnt, + req.ifd_data_fd); +@@ -2680,6 +2686,12 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + + switch (cmd) { + case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: { ++ if (data->type != QSEECOM_GENERIC) { ++ pr_err("reg lstnr req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + pr_debug("ioctl register_listener_req()\n"); + atomic_inc(&data->ioctl_count); + data->type = QSEECOM_LISTENER_SERVICE; +@@ -2691,6 +2703,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ: { ++ if ((data->listener.id == 0) || ++ (data->type != QSEECOM_LISTENER_SERVICE)) { ++ pr_err("unreg lstnr req: invalid handle (%d) lid(%d)\n", ++ data->type, data->listener.id); ++ ret = -EINVAL; ++ break; ++ } + pr_debug("ioctl unregister_listener_req()\n"); + atomic_inc(&data->ioctl_count); + ret = qseecom_unregister_listener(data); +@@ -2701,6 +2720,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_SEND_CMD_REQ: { ++ if ((data->client.app_id == 0) || ++ (data->type != QSEECOM_CLIENT_APP)) { ++ pr_err("send cmd req: invalid handle (%d) app_id(%d)\n", ++ data->type, data->client.app_id); ++ ret = -EINVAL; ++ break; ++ } + /* Only one client allowed here at a time */ + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); +@@ -2713,6 +2739,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: { ++ if ((data->client.app_id == 0) || ++ (data->type != QSEECOM_CLIENT_APP)) { ++ pr_err("send mdfd cmd: invalid handle (%d) appid(%d)\n", ++ data->type, data->client.app_id); ++ ret = -EINVAL; ++ break; ++ } + /* Only one client allowed here at a time */ + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); +@@ -2725,6 +2758,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_RECEIVE_REQ: { ++ if ((data->listener.id == 0) || ++ (data->type != QSEECOM_LISTENER_SERVICE)) { ++ pr_err("receive req: invalid handle (%d), lid(%d)\n", ++ data->type, data->listener.id); ++ ret = -EINVAL; ++ break; ++ } + atomic_inc(&data->ioctl_count); + ret = qseecom_receive_req(data); + atomic_dec(&data->ioctl_count); +@@ -2734,6 +2774,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_SEND_RESP_REQ: { ++ if ((data->listener.id == 0) || ++ (data->type != QSEECOM_LISTENER_SERVICE)) { ++ pr_err("send resp req: invalid handle (%d), lid(%d)\n", ++ data->type, data->listener.id); ++ ret = -EINVAL; ++ break; ++ } + atomic_inc(&data->ioctl_count); + ret = qseecom_send_resp(); + atomic_dec(&data->ioctl_count); +@@ -2743,7 +2790,14 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_SET_MEM_PARAM_REQ: { +- data->type = QSEECOM_CLIENT_APP; ++ if ((data->type != QSEECOM_CLIENT_APP) && ++ (data->type != QSEECOM_GENERIC) && ++ (data->type != QSEECOM_SECURE_SERVICE)) { ++ pr_err("set mem param req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + pr_debug("SET_MEM_PARAM: qseecom addr = 0x%x\n", (u32)data); + ret = qseecom_set_client_mem_param(data, argp); + if (ret) +@@ -2752,6 +2806,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_LOAD_APP_REQ: { ++ if ((data->type != QSEECOM_GENERIC) && ++ (data->type != QSEECOM_CLIENT_APP)) { ++ pr_err("load app req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + data->type = QSEECOM_CLIENT_APP; + pr_debug("LOAD_APP_REQ: qseecom_addr = 0x%x\n", (u32)data); + mutex_lock(&app_access_lock); +@@ -2772,6 +2833,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_UNLOAD_APP_REQ: { ++ if ((data->client.app_id == 0) || ++ (data->type != QSEECOM_CLIENT_APP)) { ++ pr_err("unload app req:invalid handle(%d) app_id(%d)\n", ++ data->type, data->client.app_id); ++ ret = -EINVAL; ++ break; ++ } + pr_debug("UNLOAD_APP: qseecom_addr = 0x%x\n", (u32)data); + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); +@@ -2791,6 +2859,20 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_PERF_ENABLE_REQ:{ ++ if ((data->type != QSEECOM_GENERIC) && ++ (data->type != QSEECOM_CLIENT_APP)) { ++ pr_err("perf enable req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } ++ if ((data->type == QSEECOM_CLIENT_APP) && ++ (data->client.app_id == 0)) { ++ pr_err("perf enable req:invalid handle(%d) appid(%d)\n", ++ data->type, data->client.app_id); ++ ret = -EINVAL; ++ break; ++ } + atomic_inc(&data->ioctl_count); + ret = qsee_vote_for_clock(data, CLK_DFAB); + if (ret) +@@ -2802,13 +2884,33 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_PERF_DISABLE_REQ:{ ++ if ((data->type != QSEECOM_SECURE_SERVICE) && ++ (data->type != QSEECOM_CLIENT_APP)) { ++ pr_err("perf disable req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } ++ if ((data->type == QSEECOM_CLIENT_APP) && ++ (data->client.app_id == 0)) { ++ pr_err("perf disable: invalid handle (%d)app_id(%d)\n", ++ data->type, data->client.app_id); ++ ret = -EINVAL; ++ break; ++ } + atomic_inc(&data->ioctl_count); +- qsee_disable_clock_vote(data, CLK_DFAB); +- qsee_disable_clock_vote(data, CLK_SFPB); ++ qsee_disable_clock_vote(data, CLK_DFAB); ++ qsee_disable_clock_vote(data, CLK_SFPB); + atomic_dec(&data->ioctl_count); + break; + } + case QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ: { ++ if (data->type != QSEECOM_GENERIC) { ++ pr_err("load ext elf req: invalid client handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + data->type = QSEECOM_UNAVAILABLE_CLIENT_APP; + data->released = true; + mutex_lock(&app_access_lock); +@@ -2821,6 +2923,12 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ: { ++ if (data->type != QSEECOM_UNAVAILABLE_CLIENT_APP) { ++ pr_err("unload ext elf req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + data->released = true; + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); +@@ -2842,9 +2950,15 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ: { ++ if (data->type != QSEECOM_GENERIC) { ++ pr_err("send cmd svc req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + data->type = QSEECOM_SECURE_SERVICE; + if (qseecom.qsee_version < QSEE_VERSION_03) { +- pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee version %u\n", ++ pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee ver %u\n", + qseecom.qsee_version); + return -EINVAL; + } +@@ -2856,8 +2970,14 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_CREATE_KEY_REQ: { ++ if (data->type != QSEECOM_GENERIC) { ++ pr_err("create key req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + if (qseecom.qsee_version < QSEE_VERSION_05) { +- pr_err("Create Key feature not supported in qsee version %u\n", ++ pr_err("Create Key feature unsupported: qsee ver %u\n", + qseecom.qsee_version); + return -EINVAL; + } +@@ -2873,8 +2993,14 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_WIPE_KEY_REQ: { ++ if (data->type != QSEECOM_GENERIC) { ++ pr_err("wipe key req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + if (qseecom.qsee_version < QSEE_VERSION_05) { +- pr_err("Wipe Key feature not supported in qsee version %u\n", ++ pr_err("Wipe Key feature unsupported in qsee ver %u\n", + qseecom.qsee_version); + return -EINVAL; + } +@@ -2889,6 +3015,12 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: { ++ if (data->type != QSEECOM_GENERIC) { ++ pr_err("save part hash req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + data->released = true; + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); +@@ -2898,6 +3030,12 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ: { ++ if (data->type != QSEECOM_GENERIC) { ++ pr_err("ES activated req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + data->released = true; + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); +@@ -2907,6 +3045,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_SEND_MODFD_RESP: { ++ if ((data->listener.id == 0) || ++ (data->type != QSEECOM_LISTENER_SERVICE)) { ++ pr_err("receive req: invalid handle (%d), lid(%d)\n", ++ data->type, data->listener.id); ++ ret = -EINVAL; ++ break; ++ } + /* Only one client allowed here at a time */ + atomic_inc(&data->ioctl_count); + ret = qseecom_send_modfd_resp(data, argp); +@@ -2917,6 +3062,13 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + case QSEECOM_IOCTL_UNPROTECT_BUF: { ++ if ((data->listener.id == 0) || ++ (data->type != QSEECOM_LISTENER_SERVICE)) { ++ pr_err("receive req: invalid handle (%d), lid(%d)\n", ++ data->type, data->listener.id); ++ ret = -EINVAL; ++ break; ++ } + /* Only one client allowed here at a time */ + atomic_inc(&data->ioctl_count); + ret = qseecom_unprotect_buffer(argp); +@@ -2927,6 +3079,7 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, + break; + } + default: ++ pr_err("Invalid IOCTL: %d\n", cmd); + return -EINVAL; + } + return ret; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9865/0.patch b/Patches/Linux_CVEs/CVE-2014-9865/0.patch new file mode 100644 index 00000000..a59ebe13 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9865/0.patch @@ -0,0 +1,91 @@ +From e65a876a155de945e306f2726f3a557415e6044e Mon Sep 17 00:00:00 2001 +From: Mona Hossain +Date: Tue, 1 Oct 2013 14:08:20 -0700 +Subject: qseecom: Validate inputs from user space + +Validate send_cmd, send_modfd_cmd and send_mdfd_resp +input parameters: cmd and response pointers and buffer +lengths and offsets issued to modify data. + +Change-Id: I381836d08aaa48357486fbdc6a122eb5b42bfa0b +Signed-off-by: Mona Hossain +--- + drivers/misc/qseecom.c | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 4c1943b..97f3362 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -1134,9 +1134,22 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + 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; ++ } + +- if (req->cmd_req_len <= 0 || +- req->resp_len <= 0 || ++ if ((req->cmd_req_len == 0) || (req->resp_len == 0) || + req->cmd_req_len > data->client.sb_length || + req->resp_len > data->client.sb_length) { + pr_err("cmd buffer length or " +@@ -1371,6 +1384,7 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, + void __user *argp) + { + int ret = 0; ++ int i; + struct qseecom_send_modfd_cmd_req req; + struct qseecom_send_cmd_req send_cmd_req; + +@@ -1384,6 +1398,14 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, + send_cmd_req.resp_buf = req.resp_buf; + send_cmd_req.resp_len = req.resp_len; + ++ /* validate offsets */ ++ for (i = 0; i < MAX_ION_FD; i++) { ++ if (req.ifd_data[i].cmd_buf_offset >= req.cmd_req_len) { ++ pr_err("Invalid offset %d = 0x%x\n", ++ i, req.ifd_data[i].cmd_buf_offset); ++ return -EINVAL; ++ } ++ } + ret = __qseecom_update_cmd_buf(&req, false, data, false); + if (ret) + return ret; +@@ -2001,11 +2023,20 @@ static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data, + void __user *argp) + { + struct qseecom_send_modfd_listener_resp resp; ++ int i; + + if (copy_from_user(&resp, argp, sizeof(resp))) { + pr_err("copy_from_user failed"); + return -EINVAL; + } ++ /* validate offsets */ ++ for (i = 0; i < MAX_ION_FD; i++) { ++ if (resp.ifd_data[i].cmd_buf_offset >= resp.resp_len) { ++ pr_err("Invalid offset %d = 0x%x\n", ++ i, resp.ifd_data[i].cmd_buf_offset); ++ return -EINVAL; ++ } ++ } + __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/Linux_CVEs/CVE-2014-9866/0.patch b/Patches/Linux_CVEs/CVE-2014-9866/0.patch new file mode 100644 index 00000000..cd2c9791 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9866/0.patch @@ -0,0 +1,45 @@ +From 8e6daae70422ad35146a87700e6634a747d1ff5d Mon Sep 17 00:00:00 2001 +From: Hariram Purushothaman +Date: Tue, 16 Jul 2013 11:23:47 -0700 +Subject: msm: camera: Bound check num_cid from userspace in csid driver + +Upper and lower bound checks are enforced for num_cid +which is passed from userspace with lower as 1 and +max of 16. + +Change-Id: Ic5456289cb2f2b4ea17610a7672eb2c5225b7954 +Signed-off-by: Hariram Purushothaman +--- + drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +index 9aca234..229fdb2 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +@@ -440,7 +440,7 @@ static long msm_csid_cmd(struct csid_device *csid_dev, void *arg) + case CSID_CFG: { + struct msm_camera_csid_params csid_params; + struct msm_camera_csid_vc_cfg *vc_cfg = NULL; +- int32_t i = 0; ++ int8_t i = 0; + if (copy_from_user(&csid_params, + (void *)cdata->cfg.csid_params, + sizeof(struct msm_camera_csid_params))) { +@@ -448,6 +448,13 @@ static long msm_csid_cmd(struct csid_device *csid_dev, void *arg) + rc = -EFAULT; + break; + } ++ if (csid_params.lut_params.num_cid < 1 || ++ csid_params.lut_params.num_cid > 16) { ++ pr_err("%s: %d num_cid outside range\n", ++ __func__, __LINE__); ++ rc = -EINVAL; ++ break; ++ } + for (i = 0; i < csid_params.lut_params.num_cid; i++) { + vc_cfg = kzalloc(csid_params.lut_params.num_cid * + sizeof(struct msm_camera_csid_vc_cfg), +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9867/0.patch b/Patches/Linux_CVEs/CVE-2014-9867/0.patch new file mode 100644 index 00000000..88d4f24d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9867/0.patch @@ -0,0 +1,108 @@ +From 322c518689a7f820165ca4c5d6b750b02ac34665 Mon Sep 17 00:00:00 2001 +From: Jim Rasche +Date: Mon, 22 Jul 2013 15:03:50 -0700 +Subject: msm:camera: Fix multiple bounds check + +Added bounds check to user input num_streams at several location, +without checking a position outside array could be dereferenced + +Change-Id: I6e82d8b51e4ec6772316c7daef243240c029db96 +Signed-off-by: Jim Rasche +--- + .../platform/msm/camera_v2/isp/msm_isp_axi_util.c | 46 ++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +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 5b7658d..746425b 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 +@@ -300,7 +300,16 @@ int msm_isp_axi_check_stream_state( + struct msm_vfe_axi_stream *stream_info; + enum msm_vfe_axi_state valid_state = + (stream_cfg_cmd->cmd == START_STREAM) ? INACTIVE : ACTIVE; ++ ++ if (stream_cfg_cmd->num_streams > MAX_NUM_STREAM) { ++ 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) { ++ return -EINVAL; ++ } + stream_info = &axi_data->stream_info[ + HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])]; + spin_lock_irqsave(&stream_info->lock, flags); +@@ -840,7 +849,16 @@ static void msm_isp_update_camif_output_count( + int i; + struct msm_vfe_axi_stream *stream_info; + struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; ++ ++ if (stream_cfg_cmd->num_streams > MAX_NUM_STREAM) { ++ return; ++ } ++ + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { ++ if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) ++ > MAX_NUM_STREAM) { ++ return; ++ } + stream_info = + &axi_data->stream_info[ + HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])]; +@@ -1020,7 +1038,16 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, + uint32_t wm_reload_mask = 0x0; + struct msm_vfe_axi_stream *stream_info; + struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; ++ ++ if (stream_cfg_cmd->num_streams > MAX_NUM_STREAM) { ++ 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) { ++ return -EINVAL; ++ } + stream_info = &axi_data->stream_info[ + HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])]; + src_state = axi_data->src_info[ +@@ -1073,7 +1100,16 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev, + uint8_t wait_for_complete = 0; + struct msm_vfe_axi_stream *stream_info; + struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; ++ ++ if (stream_cfg_cmd->num_streams > MAX_NUM_STREAM) { ++ 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) { ++ return -EINVAL; ++ } + stream_info = &axi_data->stream_info[ + HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])]; + +@@ -1158,8 +1194,18 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) + return -EBUSY; + } + ++ /*num_stream is uint32 and update_info[] bound by MAX_NUM_STREAM*/ ++ if (update_cmd->num_streams > MAX_NUM_STREAM) { ++ return -EINVAL; ++ } ++ + 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) { ++ return -EINVAL; ++ } + stream_info = &axi_data->stream_info[ + HANDLE_TO_IDX(update_info->stream_handle)]; + if (stream_info->state != ACTIVE && +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9868/0.patch b/Patches/Linux_CVEs/CVE-2014-9868/0.patch new file mode 100644 index 00000000..6107cf1c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9868/0.patch @@ -0,0 +1,60 @@ +From 1f274b74c00187ba1c379971503f51944148b22f Mon Sep 17 00:00:00 2001 +From: Lakshmi Narayana Kalavala +Date: Thu, 25 Jul 2013 15:55:03 -0700 +Subject: msm: camera: Fix possible out of bound writes in csi driver + +The value csi_lane_mask which is uint16_t is controllable from userspace. +The while loop can loop for 2^16 - 1, Hence extract the required +bit combination from the userspace argument, used it for further +processing. + +CRs-Fixed: 511976 +Change-Id: I80b0fe7ac273352503d9705510f05debe6cbb10a +Signed-off-by: Lakshmi Narayana Kalavala +--- + drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +index 21b9cdc..32cf0d3 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +@@ -423,7 +423,7 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) + __LINE__, csi_lane_params); + return -EINVAL; + } +- csi_lane_mask = csi_lane_params->csi_lane_mask; ++ csi_lane_mask = (csi_lane_params->csi_lane_mask & 0x1F); + + CDBG("%s csiphy_params, lane assign %x mask = %x\n", + __func__, +@@ -436,7 +436,7 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) + csiphy_dev->lane_mask[csiphy_dev->pdev->id] &= + ~(csi_lane_mask); + i = 0; +- while (csi_lane_mask & 0x1F) { ++ while (csi_lane_mask) { + if (csi_lane_mask & 0x1) { + msm_camera_io_w(0x0, csiphy_dev->base + + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i); +@@ -507,7 +507,7 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) + __LINE__, csi_lane_params); + return -EINVAL; + } +- csi_lane_mask = csi_lane_params->csi_lane_mask; ++ csi_lane_mask = (csi_lane_params->csi_lane_mask & 0x1F); + + CDBG("%s csiphy_params, lane assign %x mask = %x\n", + __func__, +@@ -520,7 +520,7 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) + csiphy_dev->lane_mask[csiphy_dev->pdev->id] &= + ~(csi_lane_mask); + i = 0; +- while (csi_lane_mask & 0x1F) { ++ while (csi_lane_mask) { + if (csi_lane_mask & 0x1) { + msm_camera_io_w(0x0, csiphy_dev->base + + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9869/0.patch b/Patches/Linux_CVEs/CVE-2014-9869/0.patch new file mode 100644 index 00000000..289a1d0f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9869/0.patch @@ -0,0 +1,74 @@ +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/Linux_CVEs/CVE-2014-9869/1.patch b/Patches/Linux_CVEs/CVE-2014-9869/1.patch new file mode 100644 index 00000000..fb032866 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9869/1.patch @@ -0,0 +1,145 @@ +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/Linux_CVEs/CVE-2014-9870/0.patch b/Patches/Linux_CVEs/CVE-2014-9870/0.patch new file mode 100644 index 00000000..ae176f5b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9870/0.patch @@ -0,0 +1,216 @@ +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/Linux_CVEs/CVE-2014-9871/0.patch b/Patches/Linux_CVEs/CVE-2014-9871/0.patch new file mode 100644 index 00000000..a777f848 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9871/0.patch @@ -0,0 +1,146 @@ +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/Linux_CVEs/CVE-2014-9872/0.patch b/Patches/Linux_CVEs/CVE-2014-9872/0.patch new file mode 100644 index 00000000..d8872c85 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9872/0.patch @@ -0,0 +1,99 @@ +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/Linux_CVEs/CVE-2014-9873/0.patch b/Patches/Linux_CVEs/CVE-2014-9873/0.patch new file mode 100644 index 00000000..d619ae2f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9873/0.patch @@ -0,0 +1,35 @@ +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/Linux_CVEs/CVE-2014-9874/0.patch b/Patches/Linux_CVEs/CVE-2014-9874/0.patch new file mode 100644 index 00000000..31191d4d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9874/0.patch @@ -0,0 +1,64 @@ +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/Linux_CVEs/CVE-2014-9874/1.patch b/Patches/Linux_CVEs/CVE-2014-9874/1.patch new file mode 100644 index 00000000..d2dd6731 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9874/1.patch @@ -0,0 +1,44 @@ +From 6b7b66961934660a91fb035e6e4223689a2500da Mon Sep 17 00:00:00 2001 +From: Masaki Sato +Date: Fri, 18 Apr 2014 13:23:17 -0500 +Subject: [PATCH] Revert "(CR): Asoc:msm:Added Buffer overflow check" + +This change was only meant for A-family and causes EVRC encoder +buffer allocation failure on B-family. + +This reverts commit fdd50cb69df64e8eef0933c9ee9bccb1eeae69ca. + +Change-Id: I2ce76602ef396a2939de05626c43ad4e87737418 +Signed-off-by: Masaki Sato +Reviewed-on: http://gerrit.mot.com/629216 +Submit-Approved: Jira Key +Tested-by: Jira Key +SLTApproved: Slta Waiver +Reviewed-by: Jeffrey Carlyle +Reviewed-by: Sriram Divakar +Reviewed-by: Yin-Jun Chen +--- + sound/soc/msm/qdsp6v2/q6asm.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c +index e09af8b48ba..77736150a60 100644 +--- a/sound/soc/msm/qdsp6v2/q6asm.c ++++ b/sound/soc/msm/qdsp6v2/q6asm.c +@@ -46,7 +46,6 @@ + + #define TRUE 0x01 + #define FALSE 0x00 +-#define FRAME_NUM (8) + + /* TODO, combine them together */ + static DEFINE_MUTEX(session_lock); +@@ -924,8 +923,6 @@ 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); diff --git a/Patches/Linux_CVEs/CVE-2014-9875/0.patch b/Patches/Linux_CVEs/CVE-2014-9875/0.patch new file mode 100644 index 00000000..de34d9da --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9875/0.patch @@ -0,0 +1,246 @@ +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/Linux_CVEs/CVE-2014-9876/0.patch b/Patches/Linux_CVEs/CVE-2014-9876/0.patch new file mode 100644 index 00000000..2ab8feac --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9876/0.patch @@ -0,0 +1,51 @@ +From 7efd393ca08ac74b2e3d2639b0ad77da139e9139 Mon Sep 17 00:00:00 2001 +From: Mohit Aggarwal +Date: Thu, 30 May 2013 11:12:39 +0530 +Subject: 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. + +Change-Id: I72858e7625764652571aee3154e3c2eb61655168 +CRs-Fixed: 483400 +CRs-Fixed: 483408 +Signed-off-by: Mohit Aggarwal +--- + drivers/char/diag/diagfwd.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c +index 05b2872..baa0a83 100644 +--- a/drivers/char/diag/diagfwd.c ++++ b/drivers/char/diag/diagfwd.c +@@ -95,7 +95,7 @@ do { \ + } while (0) + + #define CHK_OVERFLOW(bufStart, start, end, length) \ +-((bufStart <= start) && (end - start >= length)) ? 1 : 0 ++((bufStart <= start) && (end - start >= length) && (length > 0)) ? 1 : 0 + + /* Determine if this device uses a device tree */ + #ifdef CONFIG_OF +@@ -1604,8 +1604,15 @@ void diag_process_hdlc(void *data, unsigned len) + + ret = diag_hdlc_decode(&hdlc); + ++ /* ++ * If the message is 3 bytes or less in length then the message is ++ * too short. A message will need 4 bytes minimum, since there are ++ * 2 bytes for the CRC and 1 byte for the ending 0x7e for the hdlc ++ * encoding ++ */ + if (hdlc.dest_idx < 4) { +- pr_err("diag: Integer underflow in hdlc processing\n"); ++ pr_err_ratelimited("diag: In %s, message is too short, len: %d," ++ " dest len: %d\n", __func__, len, hdlc.dest_idx); + return; + } + if (ret) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9876/1.patch b/Patches/Linux_CVEs/CVE-2014-9876/1.patch new file mode 100644 index 00000000..a277fdce --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9876/1.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); diff --git a/Patches/Linux_CVEs/CVE-2014-9877/0.patch b/Patches/Linux_CVEs/CVE-2014-9877/0.patch new file mode 100644 index 00000000..e9b561ac --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9877/0.patch @@ -0,0 +1,94 @@ +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/Linux_CVEs/CVE-2014-9878/0.patch b/Patches/Linux_CVEs/CVE-2014-9878/0.patch new file mode 100644 index 00000000..f370db93 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9878/0.patch @@ -0,0 +1,103 @@ +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/Linux_CVEs/CVE-2014-9879/0.patch b/Patches/Linux_CVEs/CVE-2014-9879/0.patch new file mode 100644 index 00000000..23bf2885 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9879/0.patch @@ -0,0 +1,155 @@ +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/Linux_CVEs/CVE-2014-9880/0.patch b/Patches/Linux_CVEs/CVE-2014-9880/0.patch new file mode 100644 index 00000000..800fe67c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9880/0.patch @@ -0,0 +1,35 @@ +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/Linux_CVEs/CVE-2014-9881/0.patch b/Patches/Linux_CVEs/CVE-2014-9881/0.patch new file mode 100644 index 00000000..62ba9399 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9881/0.patch @@ -0,0 +1,63 @@ +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/Linux_CVEs/CVE-2014-9882/0.patch b/Patches/Linux_CVEs/CVE-2014-9882/0.patch new file mode 100644 index 00000000..23829e98 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9882/0.patch @@ -0,0 +1,54 @@ +From 3a4ebaac557a9e3fbcbab4561650abac8298a4d9 Mon Sep 17 00:00:00 2001 +From: Satish Kodishala +Date: Thu, 10 Oct 2013 15:44:11 +0530 +Subject: radio: iris: Checking if driver's buffer is large enough. + +Checking if driver's buffer is large enough to copy +the data from user space. + +Change-Id: I7b4eed81cf77ce2973669ce18ccd95a5df397d82 +CRs-fixed: 552329 +Signed-off-by: Satish Kodishala +--- + drivers/media/radio/radio-iris.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c +index 5e056be..a9e25bd 100644 +--- a/drivers/media/radio/radio-iris.c ++++ b/drivers/media/radio/radio-iris.c +@@ -3472,13 +3472,26 @@ static int iris_vidioc_s_ctrl(struct file *file, void *priv, + radio->riva_data_req.cmd_params.start_addr = ctrl->value; + break; + case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN: +- radio->riva_data_req.cmd_params.length = ctrl->value; ++ if ((ctrl->value > 0) && ++ (ctrl->value <= MAX_RIVA_PEEK_RSP_SIZE)) { ++ radio->riva_data_req.cmd_params.length = ctrl->value; ++ } else { ++ FMDERR("Length %d is more than the buffer size %d\n", ++ ctrl->value, MAX_RIVA_PEEK_RSP_SIZE); ++ retval = -EINVAL; ++ } + break; + case V4L2_CID_PRIVATE_IRIS_RIVA_POKE: +- memcpy(radio->riva_data_req.data, (void *)ctrl->value, +- radio->riva_data_req.cmd_params.length); +- radio->riva_data_req.cmd_params.subopcode = RIVA_POKE_OPCODE; +- retval = hci_poke_data(&radio->riva_data_req , radio->fm_hdev); ++ if (radio->riva_data_req.cmd_params.length <= MAX_RIVA_PEEK_RSP_SIZE) { ++ memcpy(radio->riva_data_req.data, (void *)ctrl->value, ++ radio->riva_data_req.cmd_params.length); ++ radio->riva_data_req.cmd_params.subopcode = RIVA_POKE_OPCODE; ++ retval = hci_poke_data(&radio->riva_data_req , radio->fm_hdev); ++ } else { ++ FMDERR("Can not copy into driver's buffer. Length %d is more than" ++ "the buffer size %d\n", ctrl->value, MAX_RIVA_PEEK_RSP_SIZE); ++ retval = -EINVAL; ++ } + break; + case V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR: + radio->ssbi_data_accs.start_addr = ctrl->value; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9882/1.patch b/Patches/Linux_CVEs/CVE-2014-9882/1.patch new file mode 100644 index 00000000..a9a0df43 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9882/1.patch @@ -0,0 +1,48 @@ +From 0f6afe815b1b3f920f3502be654c848bdfe5ef38 Mon Sep 17 00:00:00 2001 +From: Ayaz Ahmad +Date: Tue, 8 Oct 2013 15:56:04 +0530 +Subject: radio: iris: Use kernel API to copy data from user space + +Use copy_from_user kernel api to copy any data from user space +to kernel space. + +Change-Id: Ia3b7bb0f98180bd8792c1c18e930cb5609b8dc82 +CRs-Fixed: 540320 +Signed-off-by: Ayaz Ahmad +--- + drivers/media/radio/radio-iris.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c +index a554749..3bac006 100644 +--- a/drivers/media/radio/radio-iris.c ++++ b/drivers/media/radio/radio-iris.c +@@ -3623,13 +3623,21 @@ static int iris_vidioc_s_ctrl(struct file *file, void *priv, + break; + case V4L2_CID_PRIVATE_IRIS_RIVA_POKE: + if (radio->riva_data_req.cmd_params.length <= MAX_RIVA_PEEK_RSP_SIZE) { +- memcpy(radio->riva_data_req.data, (void *)ctrl->value, ++ retval = copy_from_user(radio->riva_data_req.data, ++ (void *)ctrl->value, + radio->riva_data_req.cmd_params.length); +- radio->riva_data_req.cmd_params.subopcode = RIVA_POKE_OPCODE; +- retval = hci_poke_data(&radio->riva_data_req , radio->fm_hdev); ++ if (retval == 0) { ++ radio->riva_data_req.cmd_params.subopcode = ++ RIVA_POKE_OPCODE; ++ retval = hci_poke_data(&radio->riva_data_req, ++ radio->fm_hdev); ++ } else { ++ retval = -EINVAL; ++ } + } else { + FMDERR("Can not copy into driver's buffer. Length %d is more than" +- "the buffer size %d\n", ctrl->value, MAX_RIVA_PEEK_RSP_SIZE); ++ "the buffer size %d\n", radio->riva_data_req.cmd_params.length, ++ MAX_RIVA_PEEK_RSP_SIZE); + retval = -EINVAL; + } + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9883/0.patch b/Patches/Linux_CVEs/CVE-2014-9883/0.patch new file mode 100644 index 00000000..e062d8fc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9883/0.patch @@ -0,0 +1,58 @@ +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/Linux_CVEs/CVE-2014-9884/0.patch b/Patches/Linux_CVEs/CVE-2014-9884/0.patch new file mode 100644 index 00000000..a0d6afc1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9884/0.patch @@ -0,0 +1,151 @@ +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/Linux_CVEs/CVE-2014-9885/0.patch b/Patches/Linux_CVEs/CVE-2014-9885/0.patch new file mode 100644 index 00000000..ffcb5526 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9885/0.patch @@ -0,0 +1,30 @@ +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/Linux_CVEs/CVE-2014-9886/0.patch b/Patches/Linux_CVEs/CVE-2014-9886/0.patch new file mode 100644 index 00000000..15191d3a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9886/0.patch @@ -0,0 +1,178 @@ +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/Linux_CVEs/CVE-2014-9887/0.patch b/Patches/Linux_CVEs/CVE-2014-9887/0.patch new file mode 100644 index 00000000..76fc99b4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9887/0.patch @@ -0,0 +1,35 @@ +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/Linux_CVEs/CVE-2014-9888/0.patch b/Patches/Linux_CVEs/CVE-2014-9888/0.patch new file mode 100644 index 00000000..e0c39a8e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9888/0.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)) diff --git a/Patches/Linux_CVEs/CVE-2014-9888/1.patch b/Patches/Linux_CVEs/CVE-2014-9888/1.patch new file mode 100644 index 00000000..47a0698c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9888/1.patch @@ -0,0 +1,35 @@ +From f044936caab337a4384fbfe64a4cbae33c7e22a1 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Wed, 23 Oct 2013 16:14:59 +0100 +Subject: 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. + +Change-Id: Ib40f59f3c569f82409943cf8f9a86a9869d922cc +Signed-off-by: Russell King +Git-commit: 0ea1ec713f04bdfac343c9702b21cd3a7c711826 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git +[lauraa@codeaurora.org: dropped functions not in older builds] +Signed-off-by: Laura Abbott +--- + arch/arm/mm/dma-mapping.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index 230dfe0ef..935bb9a 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -657,7 +657,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; + bool no_kernel_mapping = dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, + attrs); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9889/0.patch b/Patches/Linux_CVEs/CVE-2014-9889/0.patch new file mode 100644 index 00000000..3dc90a8a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9889/0.patch @@ -0,0 +1,85 @@ +From b0c2274b13a0487e72e57342a842a99a15149fb9 Mon Sep 17 00:00:00 2001 +From: Iliya Varadzhakov +Date: Thu, 19 Jun 2014 20:03:00 -0700 +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: Id272eb2296233c66befd015f41f19a9fbc551572 +Signed-off-by: Iliya Varadzhakov +--- + .../platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 24 ++++++++++++++++++++++ + include/media/msmb_pproc.h | 3 ++- + 2 files changed, 26 insertions(+), 1 deletion(-) + +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 a7589e4..5b17a4d 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 +@@ -1436,6 +1436,18 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + } + cpp_frame_msg = new_frame->cpp_cmd_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), +@@ -1532,6 +1544,12 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + goto phyaddr_err; + } + ++ if ((stripe_base + num_stripes*27 + 1) != new_frame->msg_len) { ++ pr_err("Invalid frame message\n"); ++ rc = -EINVAL; ++ goto phyaddr_err; ++ } ++ + for (i = 0; i < num_stripes; i++) { + cpp_frame_msg[stripe_base + 5 + i*27] += + (uint32_t) in_phyaddr; +@@ -1572,6 +1590,12 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + + stripe_base = STRIPE_BASE_FW_1_8_0; + ++ if ((stripe_base + num_stripes*48 + 1) != new_frame->msg_len) { ++ pr_err("Invalid frame message\n"); ++ rc = -EINVAL; ++ goto phyaddr_err; ++ } ++ + for (i = 0; i < num_stripes; i++) { + + cpp_frame_msg[stripe_base + 8 + i * 48] += +diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h +index 118ec30..3137aaa 100644 +--- a/include/media/msmb_pproc.h ++++ b/include/media/msmb_pproc.h +@@ -16,7 +16,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/Linux_CVEs/CVE-2014-9889/1.patch b/Patches/Linux_CVEs/CVE-2014-9889/1.patch new file mode 100644 index 00000000..cf130879 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9889/1.patch @@ -0,0 +1,155 @@ +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/Linux_CVEs/CVE-2014-9890/0.patch b/Patches/Linux_CVEs/CVE-2014-9890/0.patch new file mode 100644 index 00000000..5be0e2d8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9890/0.patch @@ -0,0 +1,39 @@ +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/Linux_CVEs/CVE-2014-9891/0.patch b/Patches/Linux_CVEs/CVE-2014-9891/0.patch new file mode 100644 index 00000000..cd8b5d65 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9891/0.patch @@ -0,0 +1,64 @@ +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/Linux_CVEs/CVE-2014-9892/0.patch b/Patches/Linux_CVEs/CVE-2014-9892/0.patch new file mode 100644 index 00000000..8da8a684 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9892/0.patch @@ -0,0 +1,35 @@ +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/Linux_CVEs/CVE-2014-9893/0.patch b/Patches/Linux_CVEs/CVE-2014-9893/0.patch new file mode 100644 index 00000000..912d44a7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9893/0.patch @@ -0,0 +1,78 @@ +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/Linux_CVEs/CVE-2014-9894/0.patch b/Patches/Linux_CVEs/CVE-2014-9894/0.patch new file mode 100644 index 00000000..208f38e3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9894/0.patch @@ -0,0 +1,39 @@ +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/Linux_CVEs/CVE-2014-9895/0.patch b/Patches/Linux_CVEs/CVE-2014-9895/0.patch new file mode 100644 index 00000000..63d33160 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9895/0.patch @@ -0,0 +1,33 @@ +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/Linux_CVEs/CVE-2014-9895/1.patch b/Patches/Linux_CVEs/CVE-2014-9895/1.patch new file mode 100644 index 00000000..334246f6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9895/1.patch @@ -0,0 +1,36 @@ +From c88e739b1fad662240e99ecbd0bdaac871717987 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Sat, 13 Apr 2013 06:32:15 -0300 +Subject: [PATCH] [media] media: info leak in __media_device_enum_links() + +These structs have holes and reserved struct members which aren't +cleared. I've added a memset() so we don't leak stack information. + +Signed-off-by: Dan Carpenter +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/media-device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c +index 1957c0df08fdb..d5a7a135f75d3 100644 +--- a/drivers/media/media-device.c ++++ b/drivers/media/media-device.c +@@ -142,6 +142,8 @@ static long __media_device_enum_links(struct media_device *mdev, + + for (p = 0; p < entity->num_pads; p++) { + struct media_pad_desc pad; ++ ++ memset(&pad, 0, sizeof(pad)); + media_device_kpad_to_upad(&entity->pads[p], &pad); + if (copy_to_user(&links->pads[p], &pad, sizeof(pad))) + return -EFAULT; +@@ -159,6 +161,7 @@ static long __media_device_enum_links(struct media_device *mdev, + if (entity->links[l].source->entity != entity) + continue; + ++ memset(&link, 0, sizeof(link)); + media_device_kpad_to_upad(entity->links[l].source, + &link.source); + media_device_kpad_to_upad(entity->links[l].sink, diff --git a/Patches/Linux_CVEs/CVE-2014-9896/0.patch b/Patches/Linux_CVEs/CVE-2014-9896/0.patch new file mode 100644 index 00000000..7203bf11 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9896/0.patch @@ -0,0 +1,86 @@ +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/Linux_CVEs/CVE-2014-9897/0.patch b/Patches/Linux_CVEs/CVE-2014-9897/0.patch new file mode 100644 index 00000000..c7d0a1b0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9897/0.patch @@ -0,0 +1,32 @@ +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/Linux_CVEs/CVE-2014-9898/0.patch b/Patches/Linux_CVEs/CVE-2014-9898/0.patch new file mode 100644 index 00000000..15191d3a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9898/0.patch @@ -0,0 +1,178 @@ +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/Linux_CVEs/CVE-2014-9899/0.patch b/Patches/Linux_CVEs/CVE-2014-9899/0.patch new file mode 100644 index 00000000..1ef2d7bd --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9899/0.patch @@ -0,0 +1,43 @@ +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/Linux_CVEs/CVE-2014-9900/0.patch b/Patches/Linux_CVEs/CVE-2014-9900/0.patch new file mode 100644 index 00000000..8bc91005 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9900/0.patch @@ -0,0 +1,36 @@ +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/Linux_CVEs/CVE-2014-9901/0.patch b/Patches/Linux_CVEs/CVE-2014-9901/0.patch new file mode 100644 index 00000000..00ba32d7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9901/0.patch @@ -0,0 +1,294 @@ +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/Linux_CVEs/CVE-2014-9902/0.patch b/Patches/Linux_CVEs/CVE-2014-9902/0.patch new file mode 100644 index 00000000..c7b0144d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9902/0.patch @@ -0,0 +1,61 @@ +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/Linux_CVEs/CVE-2014-9903/0.patch b/Patches/Linux_CVEs/CVE-2014-9903/0.patch new file mode 100644 index 00000000..a5a47412 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9903/0.patch @@ -0,0 +1,44 @@ +From 4efbc454ba68def5ef285b26ebfcfdb605b52755 Mon Sep 17 00:00:00 2001 +From: Vegard Nossum +Date: Sun, 16 Feb 2014 22:24:17 +0100 +Subject: sched: Fix information leak in sys_sched_getattr() + +We're copying the on-stack structure to userspace, but forgot to give +the right number of bytes to copy. This allows the calling process to +obtain up to PAGE_SIZE bytes from the stack (and possibly adjacent +kernel memory). + +This fix copies only as much as we actually have on the stack +(attr->size defaults to the size of the struct) and leaves the rest of +the userspace-provided buffer untouched. + +Found using kmemcheck + trinity. + +Fixes: d50dde5a10f30 ("sched: Add new scheduler syscalls to support an extended scheduling parameters ABI") +Cc: Dario Faggioli +Cc: Juri Lelli +Cc: Ingo Molnar +Signed-off-by: Vegard Nossum +Signed-off-by: Peter Zijlstra +Link: http://lkml.kernel.org/r/1392585857-10725-1-git-send-email-vegard.nossum@oracle.com +Signed-off-by: Thomas Gleixner +--- + kernel/sched/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 33d030a..a6e7470 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -3786,7 +3786,7 @@ static int sched_read_attr(struct sched_attr __user *uattr, + attr->size = usize; + } + +- ret = copy_to_user(uattr, attr, usize); ++ ret = copy_to_user(uattr, attr, attr->size); + if (ret) + return -EFAULT; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9904/0.patch b/Patches/Linux_CVEs/CVE-2014-9904/0.patch new file mode 100644 index 00000000..4ad5569a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9904/0.patch @@ -0,0 +1,36 @@ +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/Linux_CVEs/CVE-2014-9914/0.patch b/Patches/Linux_CVEs/CVE-2014-9914/0.patch new file mode 100644 index 00000000..a630feea --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9914/0.patch @@ -0,0 +1,178 @@ +From 9709674e68646cee5a24e3000b3558d25412203a Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 10 Jun 2014 06:43:01 -0700 +Subject: ipv4: fix a race in ip4_datagram_release_cb() + +Alexey gave a AddressSanitizer[1] report that finally gave a good hint +at where was the origin of various problems already reported by Dormando +in the past [2] + +Problem comes from the fact that UDP can have a lockless TX path, and +concurrent threads can manipulate sk_dst_cache, while another thread, +is holding socket lock and calls __sk_dst_set() in +ip4_datagram_release_cb() (this was added in linux-3.8) + +It seems that all we need to do is to use sk_dst_check() and +sk_dst_set() so that all the writers hold same spinlock +(sk->sk_dst_lock) to prevent corruptions. + +TCP stack do not need this protection, as all sk_dst_cache writers hold +the socket lock. + +[1] +https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel + +AddressSanitizer: heap-use-after-free in ipv4_dst_check +Read of size 2 by thread T15453: + [] ipv4_dst_check+0x1a/0x90 ./net/ipv4/route.c:1116 + [] __sk_dst_check+0x89/0xe0 ./net/core/sock.c:531 + [] ip4_datagram_release_cb+0x46/0x390 ??:0 + [] release_sock+0x17a/0x230 ./net/core/sock.c:2413 + [] ip4_datagram_connect+0x462/0x5d0 ??:0 + [] inet_dgram_connect+0x76/0xd0 ./net/ipv4/af_inet.c:534 + [] SYSC_connect+0x15c/0x1c0 ./net/socket.c:1701 + [] SyS_connect+0xe/0x10 ./net/socket.c:1682 + [] system_call_fastpath+0x16/0x1b +./arch/x86/kernel/entry_64.S:629 + +Freed by thread T15455: + [] dst_destroy+0xa8/0x160 ./net/core/dst.c:251 + [] dst_release+0x45/0x80 ./net/core/dst.c:280 + [] ip4_datagram_connect+0xa1/0x5d0 ??:0 + [] inet_dgram_connect+0x76/0xd0 ./net/ipv4/af_inet.c:534 + [] SYSC_connect+0x15c/0x1c0 ./net/socket.c:1701 + [] SyS_connect+0xe/0x10 ./net/socket.c:1682 + [] system_call_fastpath+0x16/0x1b +./arch/x86/kernel/entry_64.S:629 + +Allocated by thread T15453: + [] dst_alloc+0x81/0x2b0 ./net/core/dst.c:171 + [] rt_dst_alloc+0x47/0x50 ./net/ipv4/route.c:1406 + [< inlined >] __ip_route_output_key+0x3e8/0xf70 +__mkroute_output ./net/ipv4/route.c:1939 + [] __ip_route_output_key+0x3e8/0xf70 ./net/ipv4/route.c:2161 + [] ip_route_output_flow+0x14/0x30 ./net/ipv4/route.c:2249 + [] ip4_datagram_connect+0x317/0x5d0 ??:0 + [] inet_dgram_connect+0x76/0xd0 ./net/ipv4/af_inet.c:534 + [] SYSC_connect+0x15c/0x1c0 ./net/socket.c:1701 + [] SyS_connect+0xe/0x10 ./net/socket.c:1682 + [] system_call_fastpath+0x16/0x1b +./arch/x86/kernel/entry_64.S:629 + +[2] +<4>[196727.311203] general protection fault: 0000 [#1] SMP +<4>[196727.311224] Modules linked in: xt_TEE xt_dscp xt_DSCP macvlan bridge coretemp crc32_pclmul ghash_clmulni_intel gpio_ich microcode ipmi_watchdog ipmi_devintf sb_edac edac_core lpc_ich mfd_core tpm_tis tpm tpm_bios ipmi_si ipmi_msghandler isci igb libsas i2c_algo_bit ixgbe ptp pps_core mdio +<4>[196727.311333] CPU: 17 PID: 0 Comm: swapper/17 Not tainted 3.10.26 #1 +<4>[196727.311344] Hardware name: Supermicro X9DRi-LN4+/X9DR3-LN4+/X9DRi-LN4+/X9DR3-LN4+, BIOS 3.0 07/05/2013 +<4>[196727.311364] task: ffff885e6f069700 ti: ffff885e6f072000 task.ti: ffff885e6f072000 +<4>[196727.311377] RIP: 0010:[] [] ipv4_dst_destroy+0x4f/0x80 +<4>[196727.311399] RSP: 0018:ffff885effd23a70 EFLAGS: 00010282 +<4>[196727.311409] RAX: dead000000200200 RBX: ffff8854c398ecc0 RCX: 0000000000000040 +<4>[196727.311423] RDX: dead000000100100 RSI: dead000000100100 RDI: dead000000200200 +<4>[196727.311437] RBP: ffff885effd23a80 R08: ffffffff815fd9e0 R09: ffff885d5a590800 +<4>[196727.311451] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 +<4>[196727.311464] R13: ffffffff81c8c280 R14: 0000000000000000 R15: ffff880e85ee16ce +<4>[196727.311510] FS: 0000000000000000(0000) GS:ffff885effd20000(0000) knlGS:0000000000000000 +<4>[196727.311554] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +<4>[196727.311581] CR2: 00007a46751eb000 CR3: 0000005e65688000 CR4: 00000000000407e0 +<4>[196727.311625] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +<4>[196727.311669] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 +<4>[196727.311713] Stack: +<4>[196727.311733] ffff8854c398ecc0 ffff8854c398ecc0 ffff885effd23ab0 ffffffff815b7f42 +<4>[196727.311784] ffff88be6595bc00 ffff8854c398ecc0 0000000000000000 ffff8854c398ecc0 +<4>[196727.311834] ffff885effd23ad0 ffffffff815b86c6 ffff885d5a590800 ffff8816827821c0 +<4>[196727.311885] Call Trace: +<4>[196727.311907] +<4>[196727.311912] [] dst_destroy+0x32/0xe0 +<4>[196727.311959] [] dst_release+0x56/0x80 +<4>[196727.311986] [] tcp_v4_do_rcv+0x2a5/0x4a0 +<4>[196727.312013] [] tcp_v4_rcv+0x7da/0x820 +<4>[196727.312041] [] ? ip_rcv_finish+0x360/0x360 +<4>[196727.312070] [] ? nf_hook_slow+0x7d/0x150 +<4>[196727.312097] [] ? ip_rcv_finish+0x360/0x360 +<4>[196727.312125] [] ip_local_deliver_finish+0xb2/0x230 +<4>[196727.312154] [] ip_local_deliver+0x4a/0x90 +<4>[196727.312183] [] ip_rcv_finish+0x119/0x360 +<4>[196727.312212] [] ip_rcv+0x22b/0x340 +<4>[196727.312242] [] ? macvlan_broadcast+0x160/0x160 [macvlan] +<4>[196727.312275] [] __netif_receive_skb_core+0x512/0x640 +<4>[196727.312308] [] ? kmem_cache_alloc+0x13b/0x150 +<4>[196727.312338] [] __netif_receive_skb+0x21/0x70 +<4>[196727.312368] [] netif_receive_skb+0x31/0xa0 +<4>[196727.312397] [] napi_gro_receive+0xe8/0x140 +<4>[196727.312433] [] ixgbe_poll+0x551/0x11f0 [ixgbe] +<4>[196727.312463] [] ? ip_rcv+0x22b/0x340 +<4>[196727.312491] [] net_rx_action+0x111/0x210 +<4>[196727.312521] [] ? __netif_receive_skb+0x21/0x70 +<4>[196727.312552] [] __do_softirq+0xd0/0x270 +<4>[196727.312583] [] call_softirq+0x1c/0x30 +<4>[196727.312613] [] do_softirq+0x55/0x90 +<4>[196727.312640] [] irq_exit+0x55/0x60 +<4>[196727.312668] [] do_IRQ+0x63/0xe0 +<4>[196727.312696] [] common_interrupt+0x6a/0x6a +<4>[196727.312722] +<1>[196727.313071] RIP [] ipv4_dst_destroy+0x4f/0x80 +<4>[196727.313100] RSP +<4>[196727.313377] ---[ end trace 64b3f14fae0f2e29 ]--- +<0>[196727.380908] Kernel panic - not syncing: Fatal exception in interrupt + +Reported-by: Alexey Preobrazhensky +Reported-by: dormando +Signed-off-by: Eric Dumazet +Fixes: 8141ed9fcedb2 ("ipv4: Add a socket release callback for datagram sockets") +Cc: Steffen Klassert +Signed-off-by: David S. Miller +--- + net/ipv4/datagram.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c +index 8b5134c..a3095fd 100644 +--- a/net/ipv4/datagram.c ++++ b/net/ipv4/datagram.c +@@ -86,18 +86,26 @@ out: + } + EXPORT_SYMBOL(ip4_datagram_connect); + ++/* Because UDP xmit path can manipulate sk_dst_cache without holding ++ * socket lock, we need to use sk_dst_set() here, ++ * even if we own the socket lock. ++ */ + void ip4_datagram_release_cb(struct sock *sk) + { + const struct inet_sock *inet = inet_sk(sk); + const struct ip_options_rcu *inet_opt; + __be32 daddr = inet->inet_daddr; ++ struct dst_entry *dst; + struct flowi4 fl4; + struct rtable *rt; + +- if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0)) +- return; +- + rcu_read_lock(); ++ ++ dst = __sk_dst_get(sk); ++ if (!dst || !dst->obsolete || dst->ops->check(dst, 0)) { ++ rcu_read_unlock(); ++ return; ++ } + inet_opt = rcu_dereference(inet->inet_opt); + if (inet_opt && inet_opt->opt.srr) + daddr = inet_opt->opt.faddr; +@@ -105,8 +113,10 @@ void ip4_datagram_release_cb(struct sock *sk) + inet->inet_saddr, inet->inet_dport, + inet->inet_sport, sk->sk_protocol, + RT_CONN_FLAGS(sk), sk->sk_bound_dev_if); +- if (!IS_ERR(rt)) +- __sk_dst_set(sk, &rt->dst); ++ ++ dst = !IS_ERR(rt) ? &rt->dst : NULL; ++ sk_dst_set(sk, dst); ++ + rcu_read_unlock(); + } + EXPORT_SYMBOL_GPL(ip4_datagram_release_cb); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9922/0.patch b/Patches/Linux_CVEs/CVE-2014-9922/0.patch new file mode 100644 index 00000000..3d396a88 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9922/0.patch @@ -0,0 +1,92 @@ +From 69c433ed2ecd2d3264efd7afec4439524b319121 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Fri, 24 Oct 2014 00:14:39 +0200 +Subject: fs: limit filesystem stacking depth + +Add a simple read-only counter to super_block that indicates how deep this +is in the stack of filesystems. Previously ecryptfs was the only stackable +filesystem and it explicitly disallowed multiple layers of itself. + +Overlayfs, however, can be stacked recursively and also may be stacked +on top of ecryptfs or vice versa. + +To limit the kernel stack usage we must limit the depth of the +filesystem stack. Initially the limit is set to 2. + +Signed-off-by: Miklos Szeredi +--- + fs/ecryptfs/main.c | 7 +++++++ + fs/overlayfs/super.c | 9 +++++++++ + include/linux/fs.h | 11 +++++++++++ + 3 files changed, 27 insertions(+) + +diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c +index 1b119d3..c4cd1fd 100644 +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -566,6 +566,13 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; + s->s_blocksize = path.dentry->d_sb->s_blocksize; + s->s_magic = ECRYPTFS_SUPER_MAGIC; ++ s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1; ++ ++ rc = -EINVAL; ++ if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { ++ pr_err("eCryptfs: maximum fs stacking depth exceeded\n"); ++ goto out_free; ++ } + + inode = ecryptfs_get_inode(path.dentry->d_inode, s); + rc = PTR_ERR(inode); +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 7dcc24e..08b704c 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -677,6 +677,15 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) + } + ufs->lower_namelen = statfs.f_namelen; + ++ sb->s_stack_depth = max(upperpath.mnt->mnt_sb->s_stack_depth, ++ lowerpath.mnt->mnt_sb->s_stack_depth) + 1; ++ ++ err = -EINVAL; ++ if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { ++ pr_err("overlayfs: maximum fs stacking depth exceeded\n"); ++ goto out_put_workpath; ++ } ++ + ufs->upper_mnt = clone_private_mount(&upperpath); + err = PTR_ERR(ufs->upper_mnt); + if (IS_ERR(ufs->upper_mnt)) { +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 69118b3..4e41a4a 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -261,6 +261,12 @@ struct iattr { + */ + #include + ++/* ++ * Maximum number of layers of fs stack. Needs to be limited to ++ * prevent kernel stack overflow ++ */ ++#define FILESYSTEM_MAX_STACK_DEPTH 2 ++ + /** + * enum positive_aop_returns - aop return codes with specific semantics + * +@@ -1273,6 +1279,11 @@ struct super_block { + struct list_lru s_dentry_lru ____cacheline_aligned_in_smp; + struct list_lru s_inode_lru ____cacheline_aligned_in_smp; + struct rcu_head rcu; ++ ++ /* ++ * Indicates how deep in a filesystem stack this SB is ++ */ ++ int s_stack_depth; + }; + + extern struct timespec current_fs_time(struct super_block *sb); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2014-9940/0.patch b/Patches/Linux_CVEs/CVE-2014-9940/0.patch new file mode 100644 index 00000000..1ea5321b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2014-9940/0.patch @@ -0,0 +1,31 @@ +From 60a2362f769cf549dc466134efe71c8bf9fbaaba Mon Sep 17 00:00:00 2001 +From: Seung-Woo Kim +Date: Thu, 4 Dec 2014 19:17:17 +0900 +Subject: regulator: core: Fix regualtor_ena_gpio_free not to access pin after + freeing + +After freeing pin from regulator_ena_gpio_free, loop can access +the pin. So this patch fixes not to access pin after freeing. + +Signed-off-by: Seung-Woo Kim +Signed-off-by: Mark Brown +--- + drivers/regulator/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index df2af3a..47a455c 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1713,6 +1713,8 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev) + gpiod_put(pin->gpiod); + list_del(&pin->list); + kfree(pin); ++ rdev->ena_pin = NULL; ++ return; + } else { + pin->request_count--; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-0569/0.patch b/Patches/Linux_CVEs/CVE-2015-0569/0.patch new file mode 100644 index 00000000..4eb29650 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-0569/0.patch @@ -0,0 +1,34 @@ +From a079d716b5481223f0166c644e9ec7c75a31b02c Mon Sep 17 00:00:00 2001 +From: Mahesh A Saptasagar +Date: Tue, 27 Oct 2015 19:25:49 +0530 +Subject: qcacld 2.0: Address buffer overflow due to invalid length + +prima to qcacld-2.0 propagation + +Check for valid length before copying the packet filter data from +userspace buffer to kernel space buffer to avoid buffer overflow +issue. + +Change-Id: I9548727543b903b5eaafa25c6184615d511ca99d +CRs-Fixed: 930533 +--- + CORE/HDD/src/wlan_hdd_wext.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c +index 91809f8..668cd1d 100644 +--- a/CORE/HDD/src/wlan_hdd_wext.c ++++ b/CORE/HDD/src/wlan_hdd_wext.c +@@ -9741,6 +9741,9 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, + + hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d", + pRequest->paramsData[i].dataOffset, pRequest->paramsData[i].dataLength); ++ if ((sizeof(packetFilterSetReq.paramsData[i].compareData)) < ++ (pRequest->paramsData[i].dataLength)) ++ return -EINVAL; + + memcpy(&packetFilterSetReq.paramsData[i].compareData, + pRequest->paramsData[i].compareData, pRequest->paramsData[i].dataLength); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-0569/1.patch b/Patches/Linux_CVEs/CVE-2015-0569/1.patch new file mode 100644 index 00000000..940d5f7c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-0569/1.patch @@ -0,0 +1,32 @@ +From 0ffca4f7bca3a8157d8dbaddbcea292c267fb5aa Mon Sep 17 00:00:00 2001 +From: Mahesh A Saptasagar +Date: Tue, 27 Oct 2015 15:40:18 +0530 +Subject: wlan: Address buffer overflow due to invalid length + +Check for valid length before copying the packet filter data from +userspace buffer to kernel space buffer to avoid buffer overflow +issue. + +Change-Id: I9548727543b903b5eaafa25c6184615d511ca99d +CRs-Fixed: 930533 +--- + CORE/HDD/src/wlan_hdd_wext.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c +index c38563d..79dde24 100644 +--- a/CORE/HDD/src/wlan_hdd_wext.c ++++ b/CORE/HDD/src/wlan_hdd_wext.c +@@ -8401,6 +8401,9 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, + + hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d", + pRequest->paramsData[i].dataOffset, pRequest->paramsData[i].dataLength); ++ if ((sizeof(packetFilterSetReq.paramsData[i].compareData)) < ++ (pRequest->paramsData[i].dataLength)) ++ return -EINVAL; + + memcpy(&packetFilterSetReq.paramsData[i].compareData, + pRequest->paramsData[i].compareData, pRequest->paramsData[i].dataLength); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-0569/2.patch b/Patches/Linux_CVEs/CVE-2015-0569/2.patch new file mode 100644 index 00000000..d347a8d5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-0569/2.patch @@ -0,0 +1,33 @@ +From f31e58289c8ebded58ffe1d4709e2f878765b0a6 Mon Sep 17 00:00:00 2001 +From: Amarnath Hullur Subramanyam +Date: Wed, 28 Oct 2015 17:38:59 -0700 +Subject: [PATCH] qcacld 2.0: Address buffer overflow due to invalid length + +prima to qcacld-2.0 propagation + +Check for valid length before copying the packet filter data from +userspace buffer to kernel space buffer to avoid buffer overflow +issue. + +CRs-Fixed: 930533 +Git-commit: a079d716b5481223f0166c644e9ec7c75a31b02c +Bug: 25344453 +Signed-off-by: Amarnath Hullur Subramanyam +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c +index 93136df4e2480..0b1ee2477e158 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c +@@ -8376,6 +8376,9 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, + + hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d", + pRequest->paramsData[i].dataOffset, pRequest->paramsData[i].dataLength); ++ if ((sizeof(packetFilterSetReq.paramsData[i].compareData)) < ++ (pRequest->paramsData[i].dataLength)) ++ return -EINVAL; + + memcpy(&packetFilterSetReq.paramsData[i].compareData, + pRequest->paramsData[i].compareData, pRequest->paramsData[i].dataLength); diff --git a/Patches/Linux_CVEs/CVE-2015-0570/0.patch b/Patches/Linux_CVEs/CVE-2015-0570/0.patch new file mode 100644 index 00000000..ab87e188 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-0570/0.patch @@ -0,0 +1,178 @@ +From 8bd73c3452ab22ba9bdbaac5ab12de2ed25fcb9d Mon Sep 17 00:00:00 2001 +From: Mahesh A Saptasagar +Date: Tue, 27 Oct 2015 21:56:28 +0530 +Subject: qcacld 2.0: Validate ioctls for valid input length + +prima to qcacld-2.0 propagation + +Return failure to applications if ioctl is invoked with arguments +of improper length. + +Change-Id: I01589f37996510ee130485ef43e1f36811692e28 +CRs-Fixed: 930542 +--- + CORE/HDD/src/wlan_hdd_hostapd.c | 61 +++++++++++++++++++++++++++++++---------- + 1 file changed, 47 insertions(+), 14 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index 881400e..e4e1a63 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -5186,9 +5186,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + case DOT11F_EID_WPA: + if (wps_genie[1] < 2 + 4) + { +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) + { +@@ -5246,6 +5245,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > sizeof(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E)) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT; + pos += length; +@@ -5260,9 +5264,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + + default: + hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)", (*pos<<8 | *(pos+1))); +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + } + } +@@ -5274,9 +5277,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + + default: + hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, wps_genie[0]); +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return 0; ++ ret = -EINVAL; ++ goto exit; + } + } + else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE) +@@ -5288,9 +5290,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + case DOT11F_EID_WPA: + if (wps_genie[1] < 2 + 4) + { +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) + { +@@ -5354,6 +5355,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT; + pos += length; +@@ -5363,6 +5369,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT; +@@ -5373,6 +5384,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT; +@@ -5382,6 +5398,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT; +@@ -5391,6 +5412,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT; +@@ -5414,6 +5440,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length); + pos += length; +@@ -5450,6 +5481,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + #else + halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe); + #endif ++ if (halStatus != eHAL_STATUS_SUCCESS) ++ ret = -EINVAL; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE) + { +@@ -5461,11 +5494,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + WLANSAP_Update_WpsIe ( pVosContext ); + #endif + } +- ++exit: + vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); + EXIT(); +- return halStatus; ++ return ret; + } + + static int iw_softap_setwpsie(struct net_device *dev, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-0570/1.patch b/Patches/Linux_CVEs/CVE-2015-0570/1.patch new file mode 100644 index 00000000..dd60cf10 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-0570/1.patch @@ -0,0 +1,175 @@ +From 606babd474290e84e5a86f94480f62f4a5ff92ac Mon Sep 17 00:00:00 2001 +From: Mahesh A Saptasagar +Date: Tue, 27 Oct 2015 15:13:46 +0530 +Subject: wlan: Validate ioctls for valid input length + +Return failure to applications if ioctl is invoked with arguments +of improper length. + +Change-Id: I01589f37996510ee130485ef43e1f36811692e28 +CRs-Fixed: 930542 +--- + CORE/HDD/src/wlan_hdd_hostapd.c | 60 ++++++++++++++++++++++++++++++++--------- + 1 file changed, 47 insertions(+), 13 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index bdee270..dffcc05 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -3958,9 +3958,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + case DOT11F_EID_WPA: + if (wps_genie[1] < 2 + 4) + { +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) + { +@@ -4018,6 +4017,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > sizeof(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E)) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT; + pos += length; +@@ -4032,9 +4036,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + + default: + hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)", (*pos<<8 | *(pos+1))); +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + } + } +@@ -4046,9 +4049,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + + default: + hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, wps_genie[0]); +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return 0; ++ ret = -EINVAL; ++ goto exit; + } + } + else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE) +@@ -4060,9 +4062,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + case DOT11F_EID_WPA: + if (wps_genie[1] < 2 + 4) + { +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) + { +@@ -4126,6 +4127,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT; + pos += length; +@@ -4135,6 +4141,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT; +@@ -4145,6 +4156,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT; +@@ -4154,6 +4170,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT; +@@ -4163,6 +4184,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT; +@@ -4186,6 +4212,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length); + pos += length; +@@ -4217,6 +4248,8 @@ static int __iw_softap_setwpsie(struct net_device *dev, + } // switch + } + halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe); ++ if (halStatus != eHAL_STATUS_SUCCESS) ++ ret = -EINVAL; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE) + { +@@ -4225,10 +4258,11 @@ static int __iw_softap_setwpsie(struct net_device *dev, + WLANSAP_Update_WpsIe ( pVosContext ); + } + ++exit: + vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); + EXIT(); +- return halStatus; ++ return ret; + } + + static int iw_softap_setwpsie(struct net_device *dev, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-0570/2.patch b/Patches/Linux_CVEs/CVE-2015-0570/2.patch new file mode 100644 index 00000000..20d81dd3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-0570/2.patch @@ -0,0 +1,185 @@ +From 255dd931573beb3afca15909f483f26db22a5c98 Mon Sep 17 00:00:00 2001 +From: Amarnath Hullur Subramanyam +Date: Wed, 28 Oct 2015 20:58:02 -0700 +Subject: [PATCH] qcacld 2.0: Validate ioctls for valid input length + +prima to qcacld-2.0 propagation + +Return failure to applications if ioctl is invoked with arguments +of improper length. + +CRs-Fixed: 930542 +Git-commit: 8bd73c3452ab22ba9bdbaac5ab12de2ed25fcb9d +Bug: 25344453 +Signed-off-by: Amarnath Hullur Subramanyam +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c | 62 +++++++++++++++++----- + 1 file changed, 48 insertions(+), 14 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c +index 1f56db21d64dd..51ee5474a53d1 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -3880,6 +3880,7 @@ static int iw_softap_setwpsie(struct net_device *dev, + u_int8_t WPSIeType; + u_int16_t length; + struct iw_point s_priv_data; ++ int ret = 0; + + ENTER(); + +@@ -3925,9 +3926,8 @@ static int iw_softap_setwpsie(struct net_device *dev, + case DOT11F_EID_WPA: + if (wps_genie[1] < 2 + 4) + { +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) + { +@@ -3985,6 +3985,11 @@ static int iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > sizeof(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E)) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length); + pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT; + pos += length; +@@ -3999,9 +4004,8 @@ static int iw_softap_setwpsie(struct net_device *dev, + + default: + hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)", (*pos<<8 | *(pos+1))); +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + } + } +@@ -4013,9 +4017,8 @@ static int iw_softap_setwpsie(struct net_device *dev, + + default: + hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, wps_genie[0]); +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return 0; ++ ret = -EINVAL; ++ goto exit; + } + } + else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE) +@@ -4027,9 +4030,8 @@ static int iw_softap_setwpsie(struct net_device *dev, + case DOT11F_EID_WPA: + if (wps_genie[1] < 2 + 4) + { +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- return -EINVAL; ++ ret = -EINVAL; ++ goto exit; + } + else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) + { +@@ -4093,6 +4095,11 @@ static int iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT; + pos += length; +@@ -4102,6 +4109,11 @@ static int iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT; +@@ -4112,6 +4124,11 @@ static int iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT; +@@ -4121,6 +4138,11 @@ static int iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT; +@@ -4130,6 +4152,11 @@ static int iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length); + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT; +@@ -4153,6 +4180,11 @@ static int iw_softap_setwpsie(struct net_device *dev, + pos += 2; + length = *pos<<8 | *(pos+1); + pos += 2; ++ if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text))) ++ { ++ ret = -EINVAL; ++ goto exit; ++ } + pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length; + vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length); + pos += length; +@@ -4189,6 +4221,8 @@ static int iw_softap_setwpsie(struct net_device *dev, + #else + halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe); + #endif ++ if (halStatus != eHAL_STATUS_SUCCESS) ++ ret = -EINVAL; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); + if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE) + { +@@ -4200,11 +4234,11 @@ static int iw_softap_setwpsie(struct net_device *dev, + WLANSAP_Update_WpsIe ( pVosContext ); + #endif + } +- ++exit: + vos_mem_free(pSap_WPSIe); + kfree(fwps_genie); + EXIT(); +- return halStatus; ++ return ret; + } + + static int iw_softap_stopbss(struct net_device *dev, diff --git a/Patches/Linux_CVEs/CVE-2015-1420/0.patch b/Patches/Linux_CVEs/CVE-2015-1420/0.patch new file mode 100644 index 00000000..9d201873 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-1420/0.patch @@ -0,0 +1,45 @@ +From 8dfc8b9e8432f50606820b40a7d63618d9d61a07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Jan 2015 15:30:43 -0500 +Subject: vfs: read file_handle only once in handle_to_path + +commit 161f873b89136eb1e69477c847d5a5033239d9ba upstream. + +We used to read file_handle twice. Once to get the amount of extra +bytes, and once to fetch the entire structure. + +This may be problematic since we do size verifications only after the +first read, so if the number of extra bytes changes in userspace between +the first and second calls, we'll have an incoherent view of +file_handle. + +Instead, read the constant size once, and copy that over to the final +structure without having to re-read it again. + +Signed-off-by: Sasha Levin +Cc: Al Viro +Signed-off-by: Linus Torvalds +Signed-off-by: Ben Hutchings +--- + fs/fhandle.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/fs/fhandle.c b/fs/fhandle.c +index 6b08864..c9e18f3 100644 +--- a/fs/fhandle.c ++++ b/fs/fhandle.c +@@ -196,8 +196,9 @@ static int handle_to_path(int mountdirfd, struct file_handle __user *ufh, + goto out_err; + } + /* copy the full handle */ +- if (copy_from_user(handle, ufh, +- sizeof(struct file_handle) + ++ *handle = f_handle; ++ if (copy_from_user(&handle->f_handle, ++ &ufh->f_handle, + f_handle.handle_bytes)) { + retval = -EFAULT; + goto out_handle; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-1465/0.patch b/Patches/Linux_CVEs/CVE-2015-1465/0.patch new file mode 100644 index 00000000..895fdaf4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-1465/0.patch @@ -0,0 +1,97 @@ +From df4d92549f23e1c037e83323aff58a21b3de7fe0 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Fri, 23 Jan 2015 12:01:26 +0100 +Subject: [PATCH] ipv4: try to cache dst_entries which would cause a redirect + +Not caching dst_entries which cause redirects could be exploited by hosts +on the same subnet, causing a severe DoS attack. This effect aggravated +since commit f88649721268999 ("ipv4: fix dst race in sk_dst_get()"). + +Lookups causing redirects will be allocated with DST_NOCACHE set which +will force dst_release to free them via RCU. Unfortunately waiting for +RCU grace period just takes too long, we can end up with >1M dst_entries +waiting to be released and the system will run OOM. rcuos threads cannot +catch up under high softirq load. + +Attaching the flag to emit a redirect later on to the specific skb allows +us to cache those dst_entries thus reducing the pressure on allocation +and deallocation. + +This issue was discovered by Marcelo Leitner. + +Cc: Julian Anastasov +Signed-off-by: Marcelo Leitner +Signed-off-by: Florian Westphal +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: Julian Anastasov +Signed-off-by: David S. Miller +--- + include/net/ip.h | 11 ++++++----- + net/ipv4/ip_forward.c | 3 ++- + net/ipv4/route.c | 9 +++++---- + 3 files changed, 13 insertions(+), 10 deletions(-) + +diff --git a/include/net/ip.h b/include/net/ip.h +index 0bb620702929e..f7cbd703d15d2 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -39,11 +39,12 @@ struct inet_skb_parm { + struct ip_options opt; /* Compiled IP options */ + unsigned char flags; + +-#define IPSKB_FORWARDED 1 +-#define IPSKB_XFRM_TUNNEL_SIZE 2 +-#define IPSKB_XFRM_TRANSFORMED 4 +-#define IPSKB_FRAG_COMPLETE 8 +-#define IPSKB_REROUTED 16 ++#define IPSKB_FORWARDED BIT(0) ++#define IPSKB_XFRM_TUNNEL_SIZE BIT(1) ++#define IPSKB_XFRM_TRANSFORMED BIT(2) ++#define IPSKB_FRAG_COMPLETE BIT(3) ++#define IPSKB_REROUTED BIT(4) ++#define IPSKB_DOREDIRECT BIT(5) + + u16 frag_max_size; + }; +diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c +index 3a83ce5efa80e..787b3c294ce67 100644 +--- a/net/ipv4/ip_forward.c ++++ b/net/ipv4/ip_forward.c +@@ -129,7 +129,8 @@ int ip_forward(struct sk_buff *skb) + * We now generate an ICMP HOST REDIRECT giving the route + * we calculated. + */ +- if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) ++ if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && ++ !skb_sec_path(skb)) + ip_rt_send_redirect(skb); + + skb->priority = rt_tos2priority(iph->tos); +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 6a2155b02602b..d58dd0ec3e530 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -1554,11 +1554,10 @@ static int __mkroute_input(struct sk_buff *skb, + + do_cache = res->fi && !itag; + if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && ++ skb->protocol == htons(ETH_P_IP) && + (IN_DEV_SHARED_MEDIA(out_dev) || +- inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { +- flags |= RTCF_DOREDIRECT; +- do_cache = false; +- } ++ inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) ++ IPCB(skb)->flags |= IPSKB_DOREDIRECT; + + if (skb->protocol != htons(ETH_P_IP)) { + /* Not IP (i.e. ARP). Do not create route, if it is +@@ -2303,6 +2302,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, + r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; + if (rt->rt_flags & RTCF_NOTIFY) + r->rtm_flags |= RTM_F_NOTIFY; ++ if (IPCB(skb)->flags & IPSKB_DOREDIRECT) ++ r->rtm_flags |= RTCF_DOREDIRECT; + + if (nla_put_be32(skb, RTA_DST, dst)) + goto nla_put_failure; diff --git a/Patches/Linux_CVEs/CVE-2015-1593/0.patch b/Patches/Linux_CVEs/CVE-2015-1593/0.patch new file mode 100644 index 00000000..7226ebdb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-1593/0.patch @@ -0,0 +1,111 @@ +From 805f25c4d886cfff790fa8f309e432dd7923d2c2 Mon Sep 17 00:00:00 2001 +From: Hector Marco-Gisbert +Date: Sat, 14 Feb 2015 09:33:50 -0800 +Subject: [PATCH] x86, mm/ASLR: Fix stack randomization on 64-bit systems + +commit 4e7c22d447bb6d7e37bfe39ff658486ae78e8d77 upstream. + +The issue is that the stack for processes is not properly randomized on +64 bit architectures due to an integer overflow. + +The affected function is randomize_stack_top() in file +"fs/binfmt_elf.c": + + static unsigned long randomize_stack_top(unsigned long stack_top) + { + unsigned int random_variable = 0; + + if ((current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE)) { + random_variable = get_random_int() & STACK_RND_MASK; + random_variable <<= PAGE_SHIFT; + } + return PAGE_ALIGN(stack_top) + random_variable; + return PAGE_ALIGN(stack_top) - random_variable; + } + +Note that, it declares the "random_variable" variable as "unsigned int". +Since the result of the shifting operation between STACK_RND_MASK (which +is 0x3fffff on x86_64, 22 bits) and PAGE_SHIFT (which is 12 on x86_64): + + random_variable <<= PAGE_SHIFT; + +then the two leftmost bits are dropped when storing the result in the +"random_variable". This variable shall be at least 34 bits long to hold +the (22+12) result. + +These two dropped bits have an impact on the entropy of process stack. +Concretely, the total stack entropy is reduced by four: from 2^28 to +2^30 (One fourth of expected entropy). + +This patch restores back the entropy by correcting the types involved +in the operations in the functions randomize_stack_top() and +stack_maxrandom_size(). + +The successful fix can be tested with: + + $ for i in `seq 1 10`; do cat /proc/self/maps | grep stack; done + 7ffeda566000-7ffeda587000 rw-p 00000000 00:00 0 [stack] + 7fff5a332000-7fff5a353000 rw-p 00000000 00:00 0 [stack] + 7ffcdb7a1000-7ffcdb7c2000 rw-p 00000000 00:00 0 [stack] + 7ffd5e2c4000-7ffd5e2e5000 rw-p 00000000 00:00 0 [stack] + ... + +Once corrected, the leading bytes should be between 7ffc and 7fff, +rather than always being 7fff. + +Signed-off-by: Hector Marco-Gisbert +Signed-off-by: Ismael Ripoll +[ Rebased, fixed 80 char bugs, cleaned up commit message, added test example and CVE ] +Signed-off-by: Kees Cook +Cc: Linus Torvalds +Cc: Andrew Morton +Cc: Al Viro +Fixes: CVE-2015-1593 +Link: http://lkml.kernel.org/r/20150214173350.GA18393@www.outflux.net +Signed-off-by: Borislav Petkov +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/mm/mmap.c | 6 +++--- + fs/binfmt_elf.c | 5 +++-- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index 919b91205cd4..df4552bd239e 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -35,12 +35,12 @@ struct va_alignment __read_mostly va_align = { + .flags = -1, + }; + +-static unsigned int stack_maxrandom_size(void) ++static unsigned long stack_maxrandom_size(void) + { +- unsigned int max = 0; ++ unsigned long max = 0; + if ((current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE)) { +- max = ((-1U) & STACK_RND_MASK) << PAGE_SHIFT; ++ max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT; + } + + return max; +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index d8fc0605b9d2..e1efcaa1b245 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -554,11 +554,12 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, + + static unsigned long randomize_stack_top(unsigned long stack_top) + { +- unsigned int random_variable = 0; ++ unsigned long random_variable = 0; + + if ((current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE)) { +- random_variable = get_random_int() & STACK_RND_MASK; ++ random_variable = (unsigned long) get_random_int(); ++ random_variable &= STACK_RND_MASK; + random_variable <<= PAGE_SHIFT; + } + #ifdef CONFIG_STACK_GROWSUP diff --git a/Patches/Linux_CVEs/CVE-2015-1805/0.patch b/Patches/Linux_CVEs/CVE-2015-1805/0.patch new file mode 100644 index 00000000..c4f86752 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-1805/0.patch @@ -0,0 +1,185 @@ +From a39bf4a8e29c7336c0c72652b7d0dd1cd1b13c51 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Mon, 15 Jun 2015 03:51:55 +0100 +Subject: pipe: iovec: Fix memory corruption when retrying atomic copy as + non-atomic + +pipe_iov_copy_{from,to}_user() may be tried twice with the same iovec, +the first time atomically and the second time not. The second attempt +needs to continue from the iovec position, pipe buffer offset and +remaining length where the first attempt failed, but currently the +pipe buffer offset and remaining length are reset. This will corrupt +the piped data (possibly also leading to an information leak between +processes) and may also corrupt kernel memory. + +This was fixed upstream by commits f0d1bec9d58d ("new helper: +copy_page_from_iter()") and 637b58c2887e ("switch pipe_read() to +copy_page_to_iter()"), but those aren't suitable for stable. This fix +for older kernel versions was made by Seth Jennings for RHEL and I +have extracted it from their update. + +CVE-2015-1805 + +References: https://bugzilla.redhat.com/show_bug.cgi?id=1202855 +Signed-off-by: Ben Hutchings +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li +--- + fs/pipe.c | 55 ++++++++++++++++++++++++++++++++----------------------- + 1 file changed, 32 insertions(+), 23 deletions(-) + +diff --git a/fs/pipe.c b/fs/pipe.c +index 1667e6f..abfb935 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -104,25 +104,27 @@ void pipe_wait(struct pipe_inode_info *pipe) + } + + static int +-pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, +- int atomic) ++pipe_iov_copy_from_user(void *addr, int *offset, struct iovec *iov, ++ size_t *remaining, int atomic) + { + unsigned long copy; + +- while (len > 0) { ++ while (*remaining > 0) { + while (!iov->iov_len) + iov++; +- copy = min_t(unsigned long, len, iov->iov_len); ++ copy = min_t(unsigned long, *remaining, iov->iov_len); + + if (atomic) { +- if (__copy_from_user_inatomic(to, iov->iov_base, copy)) ++ if (__copy_from_user_inatomic(addr + *offset, ++ iov->iov_base, copy)) + return -EFAULT; + } else { +- if (copy_from_user(to, iov->iov_base, copy)) ++ if (copy_from_user(addr + *offset, ++ iov->iov_base, copy)) + return -EFAULT; + } +- to += copy; +- len -= copy; ++ *offset += copy; ++ *remaining -= copy; + iov->iov_base += copy; + iov->iov_len -= copy; + } +@@ -130,25 +132,27 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, + } + + static int +-pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len, +- int atomic) ++pipe_iov_copy_to_user(struct iovec *iov, void *addr, int *offset, ++ size_t *remaining, int atomic) + { + unsigned long copy; + +- while (len > 0) { ++ while (*remaining > 0) { + while (!iov->iov_len) + iov++; +- copy = min_t(unsigned long, len, iov->iov_len); ++ copy = min_t(unsigned long, *remaining, iov->iov_len); + + if (atomic) { +- if (__copy_to_user_inatomic(iov->iov_base, from, copy)) ++ if (__copy_to_user_inatomic(iov->iov_base, ++ addr + *offset, copy)) + return -EFAULT; + } else { +- if (copy_to_user(iov->iov_base, from, copy)) ++ if (copy_to_user(iov->iov_base, ++ addr + *offset, copy)) + return -EFAULT; + } +- from += copy; +- len -= copy; ++ *offset += copy; ++ *remaining -= copy; + iov->iov_base += copy; + iov->iov_len -= copy; + } +@@ -384,7 +388,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + struct pipe_buffer *buf = pipe->bufs + curbuf; + const struct pipe_buf_operations *ops = buf->ops; + void *addr; +- size_t chars = buf->len; ++ size_t chars = buf->len, remaining; + int error, atomic; + + if (chars > total_len) +@@ -398,9 +402,11 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + } + + atomic = !iov_fault_in_pages_write(iov, chars); ++ remaining = chars; + redo: + addr = ops->map(pipe, buf, atomic); +- error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic); ++ error = pipe_iov_copy_to_user(iov, addr, &buf->offset, ++ &remaining, atomic); + ops->unmap(pipe, buf, addr); + if (unlikely(error)) { + /* +@@ -415,7 +421,6 @@ redo: + break; + } + ret += chars; +- buf->offset += chars; + buf->len -= chars; + + /* Was it a packet buffer? Clean up and exit */ +@@ -522,6 +527,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, + if (ops->can_merge && offset + chars <= PAGE_SIZE) { + int error, atomic = 1; + void *addr; ++ size_t remaining = chars; + + error = ops->confirm(pipe, buf); + if (error) +@@ -530,8 +536,8 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, + iov_fault_in_pages_read(iov, chars); + redo1: + addr = ops->map(pipe, buf, atomic); +- error = pipe_iov_copy_from_user(offset + addr, iov, +- chars, atomic); ++ error = pipe_iov_copy_from_user(addr, &offset, iov, ++ &remaining, atomic); + ops->unmap(pipe, buf, addr); + ret = error; + do_wakeup = 1; +@@ -566,6 +572,8 @@ redo1: + struct page *page = pipe->tmp_page; + char *src; + int error, atomic = 1; ++ int offset = 0; ++ size_t remaining; + + if (!page) { + page = alloc_page(GFP_HIGHUSER); +@@ -586,14 +594,15 @@ redo1: + chars = total_len; + + iov_fault_in_pages_read(iov, chars); ++ remaining = chars; + redo2: + if (atomic) + src = kmap_atomic(page); + else + src = kmap(page); + +- error = pipe_iov_copy_from_user(src, iov, chars, +- atomic); ++ error = pipe_iov_copy_from_user(src, &offset, iov, ++ &remaining, atomic); + if (atomic) + kunmap_atomic(src); + else +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-2041/0.patch b/Patches/Linux_CVEs/CVE-2015-2041/0.patch new file mode 100644 index 00000000..cabfc50a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-2041/0.patch @@ -0,0 +1,52 @@ +From 6b8d9117ccb4f81b1244aafa7bc70ef8fa45fc49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Jan 2015 20:47:00 -0500 +Subject: [PATCH] net: llc: use correct size for sysctl timeout entries + +The timeout entries are sizeof(int) rather than sizeof(long), which +means that when they were getting read we'd also leak kernel memory +to userspace along with the timeout values. + +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +--- + net/llc/sysctl_net_llc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c +index 612a5ddaf93b1..799bafc2af39e 100644 +--- a/net/llc/sysctl_net_llc.c ++++ b/net/llc/sysctl_net_llc.c +@@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = { + { + .procname = "ack", + .data = &sysctl_llc2_ack_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_ack_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "busy", + .data = &sysctl_llc2_busy_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_busy_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "p", + .data = &sysctl_llc2_p_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_p_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "rej", + .data = &sysctl_llc2_rej_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_rej_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, diff --git a/Patches/Linux_CVEs/CVE-2015-2041/1.patch b/Patches/Linux_CVEs/CVE-2015-2041/1.patch new file mode 100644 index 00000000..5cf3aecf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-2041/1.patch @@ -0,0 +1,58 @@ +From 88fe14be08a475ad0eea4ca7c51f32437baf41af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Jan 2015 20:47:00 -0500 +Subject: net: llc: use correct size for sysctl timeout entries + +commit 6b8d9117ccb4f81b1244aafa7bc70ef8fa45fc49 upstream. + +The timeout entries are sizeof(int) rather than sizeof(long), which +means that when they were getting read we'd also leak kernel memory +to userspace along with the timeout values. + +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +Signed-off-by: Ben Hutchings +--- + net/llc/sysctl_net_llc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c +index e2ebe35..be078ec 100644 +--- a/net/llc/sysctl_net_llc.c ++++ b/net/llc/sysctl_net_llc.c +@@ -17,28 +17,28 @@ static struct ctl_table llc2_timeout_table[] = { + { + .procname = "ack", + .data = &sysctl_llc2_ack_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_ack_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "busy", + .data = &sysctl_llc2_busy_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_busy_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "p", + .data = &sysctl_llc2_p_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_p_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "rej", + .data = &sysctl_llc2_rej_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_rej_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-2686/0.patch b/Patches/Linux_CVEs/CVE-2015-2686/0.patch new file mode 100644 index 00000000..a8e5e83a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-2686/0.patch @@ -0,0 +1,38 @@ +From 4de930efc23b92ddf88ce91c405ee645fe6e27ea Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 20 Mar 2015 17:41:43 +0000 +Subject: net: validate the range we feed to iov_iter_init() in + sys_sendto/sys_recvfrom + +Cc: stable@vger.kernel.org # v3.19 +Signed-off-by: Al Viro +Signed-off-by: David S. Miller +--- + net/socket.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/socket.c b/net/socket.c +index bbedbfc..245330c 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -1702,6 +1702,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, + + if (len > INT_MAX) + len = INT_MAX; ++ if (unlikely(!access_ok(VERIFY_READ, buff, len))) ++ return -EFAULT; + sock = sockfd_lookup_light(fd, &err, &fput_needed); + if (!sock) + goto out; +@@ -1760,6 +1762,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, + + if (size > INT_MAX) + size = INT_MAX; ++ if (unlikely(!access_ok(VERIFY_WRITE, ubuf, size))) ++ return -EFAULT; + sock = sockfd_lookup_light(fd, &err, &fput_needed); + if (!sock) + goto out; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-2922/0.patch b/Patches/Linux_CVEs/CVE-2015-2922/0.patch new file mode 100644 index 00000000..ace47011 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-2922/0.patch @@ -0,0 +1,45 @@ +From 6fd99094de2b83d1d4c8457f2c83483b2828e75a Mon Sep 17 00:00:00 2001 +From: "D.S. Ljungmark" +Date: Wed, 25 Mar 2015 09:28:15 +0100 +Subject: [PATCH] ipv6: Don't reduce hop limit for an interface + +A local route may have a lower hop_limit set than global routes do. + +RFC 3756, Section 4.2.7, "Parameter Spoofing" + +> 1. The attacker includes a Current Hop Limit of one or another small +> number which the attacker knows will cause legitimate packets to +> be dropped before they reach their destination. + +> As an example, one possible approach to mitigate this threat is to +> ignore very small hop limits. The nodes could implement a +> configurable minimum hop limit, and ignore attempts to set it below +> said limit. + +Signed-off-by: D.S. Ljungmark +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + net/ipv6/ndisc.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index 471ed24aabaec..14ecdaf06bf74 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -1218,7 +1218,14 @@ static void ndisc_router_discovery(struct sk_buff *skb) + if (rt) + rt6_set_expires(rt, jiffies + (HZ * lifetime)); + if (ra_msg->icmph.icmp6_hop_limit) { +- in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; ++ /* Only set hop_limit on the interface if it is higher than ++ * the current hop_limit. ++ */ ++ if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) { ++ in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; ++ } else { ++ ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n"); ++ } + if (rt) + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, + ra_msg->icmph.icmp6_hop_limit); diff --git a/Patches/Linux_CVEs/CVE-2015-3288/0.patch b/Patches/Linux_CVEs/CVE-2015-3288/0.patch new file mode 100644 index 00000000..a140407e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-3288/0.patch @@ -0,0 +1,76 @@ +From 6b7339f4c31ad69c8e9c0b2859276e22cf72176d Mon Sep 17 00:00:00 2001 +From: "Kirill A. Shutemov" +Date: Mon, 6 Jul 2015 23:18:37 +0300 +Subject: mm: avoid setting up anonymous pages into file mapping + +Reading page fault handler code I've noticed that under right +circumstances kernel would map anonymous pages into file mappings: if +the VMA doesn't have vm_ops->fault() and the VMA wasn't fully populated +on ->mmap(), kernel would handle page fault to not populated pte with +do_anonymous_page(). + +Let's change page fault handler to use do_anonymous_page() only on +anonymous VMA (->vm_ops == NULL) and make sure that the VMA is not +shared. + +For file mappings without vm_ops->fault() or shred VMA without vm_ops, +page fault on pte_none() entry would lead to SIGBUS. + +Signed-off-by: Kirill A. Shutemov +Acked-by: Oleg Nesterov +Cc: Andrew Morton +Cc: Willy Tarreau +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +--- + mm/memory.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/mm/memory.c b/mm/memory.c +index a84fbb7..388dcf9 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -2670,6 +2670,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, + + pte_unmap(page_table); + ++ /* File mapping without ->vm_ops ? */ ++ if (vma->vm_flags & VM_SHARED) ++ return VM_FAULT_SIGBUS; ++ + /* Check if we need to add a guard page to the stack */ + if (check_stack_guard_page(vma, address) < 0) + return VM_FAULT_SIGSEGV; +@@ -3099,6 +3103,9 @@ static int do_fault(struct mm_struct *mm, struct vm_area_struct *vma, + - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + + pte_unmap(page_table); ++ /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */ ++ if (!vma->vm_ops->fault) ++ return VM_FAULT_SIGBUS; + if (!(flags & FAULT_FLAG_WRITE)) + return do_read_fault(mm, vma, address, pmd, pgoff, flags, + orig_pte); +@@ -3244,13 +3251,12 @@ static int handle_pte_fault(struct mm_struct *mm, + barrier(); + if (!pte_present(entry)) { + if (pte_none(entry)) { +- if (vma->vm_ops) { +- if (likely(vma->vm_ops->fault)) +- return do_fault(mm, vma, address, pte, +- pmd, flags, entry); +- } +- return do_anonymous_page(mm, vma, address, +- pte, pmd, flags); ++ if (vma->vm_ops) ++ return do_fault(mm, vma, address, pte, pmd, ++ flags, entry); ++ ++ return do_anonymous_page(mm, vma, address, pte, pmd, ++ flags); + } + return do_swap_page(mm, vma, address, + pte, pmd, flags, entry); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-3288/1.patch b/Patches/Linux_CVEs/CVE-2015-3288/1.patch new file mode 100644 index 00000000..673a7158 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-3288/1.patch @@ -0,0 +1,73 @@ +From e2506476534cff7bb3697fbe0654fdefd101bc80 Mon Sep 17 00:00:00 2001 +From: "Kirill A. Shutemov" +Date: Mon, 6 Jul 2015 23:18:37 +0300 +Subject: mm: avoid setting up anonymous pages into file mapping + +commit 6b7339f4c31ad69c8e9c0b2859276e22cf72176d upstream. + +Reading page fault handler code I've noticed that under right +circumstances kernel would map anonymous pages into file mappings: if +the VMA doesn't have vm_ops->fault() and the VMA wasn't fully populated +on ->mmap(), kernel would handle page fault to not populated pte with +do_anonymous_page(). + +Let's change page fault handler to use do_anonymous_page() only on +anonymous VMA (->vm_ops == NULL) and make sure that the VMA is not +shared. + +For file mappings without vm_ops->fault() or shred VMA without vm_ops, +page fault on pte_none() entry would lead to SIGBUS. + +Signed-off-by: Kirill A. Shutemov +Acked-by: Oleg Nesterov +Cc: Andrew Morton +Cc: Willy Tarreau +Signed-off-by: Linus Torvalds +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +--- + mm/memory.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/mm/memory.c b/mm/memory.c +index 452b8ba..7762b1d 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -3153,6 +3153,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, + + pte_unmap(page_table); + ++ /* File mapping without ->vm_ops ? */ ++ if (vma->vm_flags & VM_SHARED) ++ return VM_FAULT_SIGBUS; ++ + /* Check if we need to add a guard page to the stack */ + if (check_stack_guard_page(vma, address) < 0) + return VM_FAULT_SIGSEGV; +@@ -3412,6 +3416,9 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, + - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + + pte_unmap(page_table); ++ /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */ ++ if (!vma->vm_ops->fault) ++ return VM_FAULT_SIGBUS; + return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); + } + +@@ -3470,11 +3477,9 @@ int handle_pte_fault(struct mm_struct *mm, + entry = *pte; + if (!pte_present(entry)) { + if (pte_none(entry)) { +- if (vma->vm_ops) { +- if (likely(vma->vm_ops->fault)) +- return do_linear_fault(mm, vma, address, ++ if (vma->vm_ops) ++ return do_linear_fault(mm, vma, address, + pte, pmd, flags, entry); +- } + return do_anonymous_page(mm, vma, address, + pte, pmd, flags); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-3339/0.patch b/Patches/Linux_CVEs/CVE-2015-3339/0.patch new file mode 100644 index 00000000..5aef49e7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-3339/0.patch @@ -0,0 +1,114 @@ +From 8b01fc86b9f425899f8a3a8fc1c47d73c2c20543 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Sun, 19 Apr 2015 02:48:39 +0200 +Subject: [PATCH] fs: take i_mutex during prepare_binprm for set[ug]id + executables + +This prevents a race between chown() and execve(), where chowning a +setuid-user binary to root would momentarily make the binary setuid +root. + +This patch was mostly written by Linus Torvalds. + +Signed-off-by: Jann Horn +Signed-off-by: Linus Torvalds +--- + fs/exec.c | 76 ++++++++++++++++++++++++++++++++++++++++----------------------- + 1 file changed, 48 insertions(+), 28 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index 02bfd980a40c7..49a1c61433b73 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1275,6 +1275,53 @@ static void check_unsafe_exec(struct linux_binprm *bprm) + spin_unlock(&p->fs->lock); + } + ++static void bprm_fill_uid(struct linux_binprm *bprm) ++{ ++ struct inode *inode; ++ unsigned int mode; ++ kuid_t uid; ++ kgid_t gid; ++ ++ /* clear any previous set[ug]id data from a previous binary */ ++ bprm->cred->euid = current_euid(); ++ bprm->cred->egid = current_egid(); ++ ++ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ++ return; ++ ++ if (task_no_new_privs(current)) ++ return; ++ ++ inode = file_inode(bprm->file); ++ mode = READ_ONCE(inode->i_mode); ++ if (!(mode & (S_ISUID|S_ISGID))) ++ return; ++ ++ /* Be careful if suid/sgid is set */ ++ mutex_lock(&inode->i_mutex); ++ ++ /* reload atomically mode/uid/gid now that lock held */ ++ mode = inode->i_mode; ++ uid = inode->i_uid; ++ gid = inode->i_gid; ++ mutex_unlock(&inode->i_mutex); ++ ++ /* We ignore suid/sgid if there are no mappings for them in the ns */ ++ if (!kuid_has_mapping(bprm->cred->user_ns, uid) || ++ !kgid_has_mapping(bprm->cred->user_ns, gid)) ++ return; ++ ++ if (mode & S_ISUID) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->euid = uid; ++ } ++ ++ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->egid = gid; ++ } ++} ++ + /* + * Fill the binprm structure from the inode. + * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes +@@ -1283,36 +1330,9 @@ static void check_unsafe_exec(struct linux_binprm *bprm) + */ + int prepare_binprm(struct linux_binprm *bprm) + { +- struct inode *inode = file_inode(bprm->file); +- umode_t mode = inode->i_mode; + int retval; + +- +- /* clear any previous set[ug]id data from a previous binary */ +- bprm->cred->euid = current_euid(); +- bprm->cred->egid = current_egid(); +- +- if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) && +- !task_no_new_privs(current) && +- kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) && +- kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) { +- /* Set-uid? */ +- if (mode & S_ISUID) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->euid = inode->i_uid; +- } +- +- /* Set-gid? */ +- /* +- * If setgid is set but no group execute bit then this +- * is a candidate for mandatory locking, not a setgid +- * executable. +- */ +- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->egid = inode->i_gid; +- } +- } ++ bprm_fill_uid(bprm); + + /* fill in binprm security blob */ + retval = security_bprm_set_creds(bprm); diff --git a/Patches/Linux_CVEs/CVE-2015-3339/1.patch b/Patches/Linux_CVEs/CVE-2015-3339/1.patch new file mode 100644 index 00000000..f1e7d799 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-3339/1.patch @@ -0,0 +1,116 @@ +From 470e517be17dd6ef8670bec7bd7831ea0d3ad8a6 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Sun, 19 Apr 2015 02:48:39 +0200 +Subject: fs: take i_mutex during prepare_binprm for set[ug]id executables + +commit 8b01fc86b9f425899f8a3a8fc1c47d73c2c20543 upstream. + +This prevents a race between chown() and execve(), where chowning a +setuid-user binary to root would momentarily make the binary setuid +root. + +This patch was mostly written by Linus Torvalds. + +Signed-off-by: Jann Horn +Signed-off-by: Linus Torvalds +[bwh: Backported to 3.2: + - Drop the task_no_new_privs() and user namespace checks + - Open-code file_inode() + - s/READ_ONCE/ACCESS_ONCE/ + - Adjust context] +Signed-off-by: Ben Hutchings +--- + fs/exec.c | 65 +++++++++++++++++++++++++++++++++++++++------------------------ + 1 file changed, 40 insertions(+), 25 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index 78199eb..7adb43f 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1282,6 +1282,45 @@ int check_unsafe_exec(struct linux_binprm *bprm) + return res; + } + ++static void bprm_fill_uid(struct linux_binprm *bprm) ++{ ++ struct inode *inode; ++ unsigned int mode; ++ uid_t uid; ++ gid_t gid; ++ ++ /* clear any previous set[ug]id data from a previous binary */ ++ bprm->cred->euid = current_euid(); ++ bprm->cred->egid = current_egid(); ++ ++ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ++ return; ++ ++ inode = bprm->file->f_path.dentry->d_inode; ++ mode = ACCESS_ONCE(inode->i_mode); ++ if (!(mode & (S_ISUID|S_ISGID))) ++ return; ++ ++ /* Be careful if suid/sgid is set */ ++ mutex_lock(&inode->i_mutex); ++ ++ /* reload atomically mode/uid/gid now that lock held */ ++ mode = inode->i_mode; ++ uid = inode->i_uid; ++ gid = inode->i_gid; ++ mutex_unlock(&inode->i_mutex); ++ ++ if (mode & S_ISUID) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->euid = uid; ++ } ++ ++ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->egid = gid; ++ } ++} ++ + /* + * Fill the binprm structure from the inode. + * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes +@@ -1290,36 +1329,12 @@ int check_unsafe_exec(struct linux_binprm *bprm) + */ + int prepare_binprm(struct linux_binprm *bprm) + { +- umode_t mode; +- struct inode * inode = bprm->file->f_path.dentry->d_inode; + int retval; + +- mode = inode->i_mode; + if (bprm->file->f_op == NULL) + return -EACCES; + +- /* clear any previous set[ug]id data from a previous binary */ +- bprm->cred->euid = current_euid(); +- bprm->cred->egid = current_egid(); +- +- if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) { +- /* Set-uid? */ +- if (mode & S_ISUID) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->euid = inode->i_uid; +- } +- +- /* Set-gid? */ +- /* +- * If setgid is set but no group execute bit then this +- * is a candidate for mandatory locking, not a setgid +- * executable. +- */ +- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->egid = inode->i_gid; +- } +- } ++ bprm_fill_uid(bprm); + + /* fill in binprm security blob */ + retval = security_bprm_set_creds(bprm); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-3636/0.patch b/Patches/Linux_CVEs/CVE-2015-3636/0.patch new file mode 100644 index 00000000..86cee79c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-3636/0.patch @@ -0,0 +1,29 @@ +From a134f083e79fb4c3d0a925691e732c56911b4326 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Fri, 1 May 2015 22:02:47 -0400 +Subject: [PATCH] ipv4: Missing sk_nulls_node_init() in ping_unhash(). + +If we don't do that, then the poison value is left in the ->pprev +backlink. + +This can cause crashes if we do a disconnect, followed by a connect(). + +Tested-by: Linus Torvalds +Reported-by: Wen Xu +Signed-off-by: David S. Miller +--- + net/ipv4/ping.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index a93f260cf24ca..05ff44b758dfe 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -158,6 +158,7 @@ void ping_unhash(struct sock *sk) + if (sk_hashed(sk)) { + write_lock_bh(&ping_table.lock); + hlist_nulls_del(&sk->sk_nulls_node); ++ sk_nulls_node_init(&sk->sk_nulls_node); + sock_put(sk); + isk->inet_num = 0; + isk->inet_sport = 0; diff --git a/Patches/Linux_CVEs/CVE-2015-4170/0.patch b/Patches/Linux_CVEs/CVE-2015-4170/0.patch new file mode 100644 index 00000000..eced29e8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-4170/0.patch @@ -0,0 +1,121 @@ +From cf872776fc84128bb779ce2b83a37c884c3203ae Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Wed, 11 Dec 2013 21:11:58 -0500 +Subject: tty: Fix hang at ldsem_down_read() + +When a controlling tty is being hung up and the hang up is +waiting for a just-signalled tty reader or writer to exit, and a new tty +reader/writer tries to acquire an ldisc reference concurrently with the +ldisc reference release from the signalled reader/writer, the hangup +can hang. The new reader/writer is sleeping in ldsem_down_read() and the +hangup is sleeping in ldsem_down_write() [1]. + +The new reader/writer fails to wakeup the waiting hangup because the +wrong lock count value is checked (the old lock count rather than the new +lock count) to see if the lock is unowned. + +Change helper function to return the new lock count if the cmpxchg was +successful; document this behavior. + +[1] edited dmesg log from reporter + +SysRq : Show Blocked State + task PC stack pid father +systemd D ffff88040c4f0000 0 1 0 0x00000000 + ffff88040c49fbe0 0000000000000046 ffff88040c4a0000 ffff88040c49ffd8 + 00000000001d3980 00000000001d3980 ffff88040c4a0000 ffff88040593d840 + ffff88040c49fb40 ffffffff810a4cc0 0000000000000006 0000000000000023 +Call Trace: + [] ? sched_clock_cpu+0x9f/0xe4 + [] ? sched_clock_cpu+0x9f/0xe4 + [] ? sched_clock_cpu+0x9f/0xe4 + [] ? sched_clock_cpu+0x9f/0xe4 + [] schedule+0x24/0x5e + [] schedule_timeout+0x15b/0x1ec + [] ? sched_clock_cpu+0x9f/0xe4 + [] ? _raw_spin_unlock_irq+0x24/0x26 + [] down_read_failed+0xe3/0x1b9 + [] ldsem_down_read+0x8b/0xa5 + [] ? tty_ldisc_ref_wait+0x1b/0x44 + [] tty_ldisc_ref_wait+0x1b/0x44 + [] tty_write+0x7d/0x28a + [] redirected_tty_write+0x8d/0x98 + [] ? tty_write+0x28a/0x28a + [] do_loop_readv_writev+0x56/0x79 + [] do_readv_writev+0x1b0/0x1ff + [] ? do_vfs_ioctl+0x32a/0x489 + [] ? final_putname+0x1d/0x3a + [] vfs_writev+0x2e/0x49 + [] SyS_writev+0x47/0xaa + [] system_call_fastpath+0x16/0x1b +bash D ffffffff81c104c0 0 5469 5302 0x00000082 + ffff8800cf817ac0 0000000000000046 ffff8804086b22a0 ffff8800cf817fd8 + 00000000001d3980 00000000001d3980 ffff8804086b22a0 ffff8800cf817a48 + 000000000000b9a0 ffff8800cf817a78 ffffffff81004675 ffff8800cf817a44 +Call Trace: + [] ? dump_trace+0x165/0x29c + [] ? sched_clock_cpu+0x9f/0xe4 + [] ? save_stack_trace+0x26/0x41 + [] schedule+0x24/0x5e + [] schedule_timeout+0x15b/0x1ec + [] ? sched_clock_cpu+0x9f/0xe4 + [] ? down_write_failed+0xa3/0x1c9 + [] ? _raw_spin_unlock_irq+0x24/0x26 + [] down_write_failed+0xab/0x1c9 + [] ldsem_down_write+0x79/0xb1 + [] ? tty_ldisc_lock_pair_timeout+0xa5/0xd9 + [] tty_ldisc_lock_pair_timeout+0xa5/0xd9 + [] tty_ldisc_hangup+0xc4/0x218 + [] __tty_hangup+0x2e2/0x3ed + [] disassociate_ctty+0x63/0x226 + [] do_exit+0x79f/0xa11 + [] ? get_signal_to_deliver+0x206/0x62f + [] ? lock_release_holdtime.part.8+0xf/0x16e + [] do_group_exit+0x47/0xb5 + [] get_signal_to_deliver+0x241/0x62f + [] do_signal+0x43/0x59d + [] ? __audit_syscall_exit+0x21a/0x2a8 + [] ? lock_release_holdtime.part.8+0xf/0x16e + [] do_notify_resume+0x54/0x6c + [] int_signal+0x12/0x17 + +Reported-by: Sami Farin +Cc: # 3.12.x +Signed-off-by: Peter Hurley +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/tty_ldsem.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c +index 22fad8a..d8a55e8 100644 +--- a/drivers/tty/tty_ldsem.c ++++ b/drivers/tty/tty_ldsem.c +@@ -86,11 +86,21 @@ static inline long ldsem_atomic_update(long delta, struct ld_semaphore *sem) + return atomic_long_add_return(delta, (atomic_long_t *)&sem->count); + } + ++/* ++ * ldsem_cmpxchg() updates @*old with the last-known sem->count value. ++ * Returns 1 if count was successfully changed; @*old will have @new value. ++ * Returns 0 if count was not changed; @*old will have most recent sem->count ++ */ + static inline int ldsem_cmpxchg(long *old, long new, struct ld_semaphore *sem) + { +- long tmp = *old; +- *old = atomic_long_cmpxchg(&sem->count, *old, new); +- return *old == tmp; ++ long tmp = atomic_long_cmpxchg(&sem->count, *old, new); ++ if (tmp == *old) { ++ *old = new; ++ return 1; ++ } else { ++ *old = tmp; ++ return 0; ++ } + } + + /* +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-4177/0.patch b/Patches/Linux_CVEs/CVE-2015-4177/0.patch new file mode 100644 index 00000000..c56630e2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-4177/0.patch @@ -0,0 +1,46 @@ +From cd4a40174b71acd021877341684d8bb1dc8ea4ae Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 7 Jan 2015 14:28:26 -0600 +Subject: [PATCH] mnt: Fail collect_mounts when applied to unmounted mounts + +The only users of collect_mounts are in audit_tree.c + +In audit_trim_trees and audit_add_tree_rule the path passed into +collect_mounts is generated from kern_path passed an audit_tree +pathname which is guaranteed to be an absolute path. In those cases +collect_mounts is obviously intended to work on mounted paths and +if a race results in paths that are unmounted when collect_mounts +it is reasonable to fail early. + +The paths passed into audit_tag_tree don't have the absolute path +check. But are used to play with fsnotify and otherwise interact with +the audit_trees, so again operating only on mounted paths appears +reasonable. + +Avoid having to worry about what happens when we try and audit +unmounted filesystems by restricting collect_mounts to mounts +that appear in the mount tree. + +Signed-off-by: "Eric W. Biederman" +--- + fs/namespace.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 2b12b7a9455d0..acc5583764dc0 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1669,8 +1669,11 @@ struct vfsmount *collect_mounts(struct path *path) + { + struct mount *tree; + namespace_lock(); +- tree = copy_tree(real_mount(path->mnt), path->dentry, +- CL_COPY_ALL | CL_PRIVATE); ++ if (!check_mnt(real_mount(path->mnt))) ++ tree = ERR_PTR(-EINVAL); ++ else ++ tree = copy_tree(real_mount(path->mnt), path->dentry, ++ CL_COPY_ALL | CL_PRIVATE); + namespace_unlock(); + if (IS_ERR(tree)) + return ERR_CAST(tree); diff --git a/Patches/Linux_CVEs/CVE-2015-5366/0.patch b/Patches/Linux_CVEs/CVE-2015-5366/0.patch new file mode 100644 index 00000000..4d1978db --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-5366/0.patch @@ -0,0 +1,62 @@ +From beb39db59d14990e401e235faf66a6b9b31240b0 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 30 May 2015 09:16:53 -0700 +Subject: [PATCH] udp: fix behavior of wrong checksums + +We have two problems in UDP stack related to bogus checksums : + +1) We return -EAGAIN to application even if receive queue is not empty. + This breaks applications using edge trigger epoll() + +2) Under UDP flood, we can loop forever without yielding to other + processes, potentially hanging the host, especially on non SMP. + +This patch is an attempt to make things better. + +We might in the future add extra support for rt applications +wanting to better control time spent doing a recv() in a hostile +environment. For example we could validate checksums before queuing +packets in socket receive queue. + +Signed-off-by: Eric Dumazet +Cc: Willem de Bruijn +Signed-off-by: David S. Miller +--- + net/ipv4/udp.c | 6 ++---- + net/ipv6/udp.c | 6 ++---- + 2 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index d10b7e0112ebd..1c92ea67baefe 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1345,10 +1345,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, + } + unlock_sock_fast(sk, slow); + +- if (noblock) +- return -EAGAIN; +- +- /* starting over for a new packet */ ++ /* starting over for a new packet, but check if we need to yield */ ++ cond_resched(); + msg->msg_flags &= ~MSG_TRUNC; + goto try_again; + } +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index c2ec41617a354..e51fc3eee6dbd 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -525,10 +525,8 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + } + unlock_sock_fast(sk, slow); + +- if (noblock) +- return -EAGAIN; +- +- /* starting over for a new packet */ ++ /* starting over for a new packet, but check if we need to yield */ ++ cond_resched(); + msg->msg_flags &= ~MSG_TRUNC; + goto try_again; + } diff --git a/Patches/Linux_CVEs/CVE-2015-5697/0.patch b/Patches/Linux_CVEs/CVE-2015-5697/0.patch new file mode 100644 index 00000000..d230b3aa --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-5697/0.patch @@ -0,0 +1,45 @@ +From b6878d9e03043695dbf3fa1caa6dfc09db225b16 Mon Sep 17 00:00:00 2001 +From: Benjamin Randazzo +Date: Sat, 25 Jul 2015 16:36:50 +0200 +Subject: [PATCH] md: use kzalloc() when bitmap is disabled + +In drivers/md/md.c get_bitmap_file() uses kmalloc() for creating a +mdu_bitmap_file_t called "file". + +5769 file = kmalloc(sizeof(*file), GFP_NOIO); +5770 if (!file) +5771 return -ENOMEM; + +This structure is copied to user space at the end of the function. + +5786 if (err == 0 && +5787 copy_to_user(arg, file, sizeof(*file))) +5788 err = -EFAULT + +But if bitmap is disabled only the first byte of "file" is initialized +with zero, so it's possible to read some bytes (up to 4095) of kernel +space memory from user space. This is an information leak. + +5775 /* bitmap disabled, zero the first byte and copy out */ +5776 if (!mddev->bitmap_info.file) +5777 file->pathname[0] = '\0'; + +Signed-off-by: Benjamin Randazzo +Signed-off-by: NeilBrown +--- + drivers/md/md.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 0c2a4e8b873c6..e25f00f0138a7 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5759,7 +5759,7 @@ static int get_bitmap_file(struct mddev *mddev, void __user * arg) + char *ptr; + int err; + +- file = kmalloc(sizeof(*file), GFP_NOIO); ++ file = kzalloc(sizeof(*file), GFP_NOIO); + if (!file) + return -ENOMEM; + diff --git a/Patches/Linux_CVEs/CVE-2015-5706/0.patch b/Patches/Linux_CVEs/CVE-2015-5706/0.patch new file mode 100644 index 00000000..f63b5535 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-5706/0.patch @@ -0,0 +1,39 @@ +From f15133df088ecadd141ea1907f2c96df67c729f0 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 8 May 2015 22:53:15 -0400 +Subject: path_openat(): fix double fput() + +path_openat() jumps to the wrong place after do_tmpfile() - it has +already done path_cleanup() (as part of path_lookupat() called by +do_tmpfile()), so doing that again can lead to double fput(). + +Cc: stable@vger.kernel.org # v3.11+ +Signed-off-by: Al Viro +--- + fs/namei.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/namei.c b/fs/namei.c +index f67cf6c..fe30d3b 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -3233,7 +3233,7 @@ static struct file *path_openat(int dfd, struct filename *pathname, + + if (unlikely(file->f_flags & __O_TMPFILE)) { + error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened); +- goto out; ++ goto out2; + } + + error = path_init(dfd, pathname, flags, nd); +@@ -3263,6 +3263,7 @@ static struct file *path_openat(int dfd, struct filename *pathname, + } + out: + path_cleanup(nd); ++out2: + if (!(opened & FILE_OPENED)) { + BUG_ON(!error); + put_filp(file); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-5707/0.patch b/Patches/Linux_CVEs/CVE-2015-5707/0.patch new file mode 100644 index 00000000..d462c86f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-5707/0.patch @@ -0,0 +1,36 @@ +From 451a2886b6bf90e2fb378f7c46c655450fb96e81 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sat, 21 Mar 2015 20:08:18 -0400 +Subject: sg_start_req(): make sure that there's not too many elements in iovec + +unfortunately, allowing an arbitrary 16bit value means a possibility of +overflow in the calculation of total number of pages in bio_map_user_iov() - +we rely on there being no more than PAGE_SIZE members of sum in the +first loop there. If that sum wraps around, we end up allocating +too small array of pointers to pages and it's easy to overflow it in +the second loop. + +X-Coverup: TINC (and there's no lumber cartel either) +Cc: stable@vger.kernel.org # way, way back +Signed-off-by: Al Viro +--- + drivers/scsi/sg.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index d383f84..b5a4db8 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -1744,6 +1744,9 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) + md->from_user = 0; + } + ++ if (unlikely(iov_count > MAX_UIOVEC)) ++ return -EINVAL; ++ + if (iov_count) { + int size = sizeof(struct iovec) * iov_count; + struct iovec *iov; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-5707/1.patch b/Patches/Linux_CVEs/CVE-2015-5707/1.patch new file mode 100644 index 00000000..124912ab --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-5707/1.patch @@ -0,0 +1,44 @@ +From fdc81f45e9f57858da6351836507fbcf1b7583ee Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sat, 21 Mar 2015 20:25:30 -0400 +Subject: sg_start_req(): use import_iovec() + +Signed-off-by: Al Viro +--- + drivers/scsi/sg.c | 16 +++++----------- + 1 file changed, 5 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index b5a4db8..9d7b7db 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -1744,21 +1744,15 @@ sg_start_req(Sg_request *srp, unsigned char *cmd) + md->from_user = 0; + } + +- if (unlikely(iov_count > MAX_UIOVEC)) +- return -EINVAL; +- + if (iov_count) { +- int size = sizeof(struct iovec) * iov_count; +- struct iovec *iov; ++ struct iovec *iov = NULL; + struct iov_iter i; + +- iov = memdup_user(hp->dxferp, size); +- if (IS_ERR(iov)) +- return PTR_ERR(iov); ++ res = import_iovec(rw, hp->dxferp, iov_count, 0, &iov, &i); ++ if (res < 0) ++ return res; + +- iov_iter_init(&i, rw, iov, iov_count, +- min_t(size_t, hp->dxfer_len, +- iov_length(iov, iov_count))); ++ iov_iter_truncate(&i, hp->dxfer_len); + + res = blk_rq_map_user_iov(q, rq, md, &i, GFP_ATOMIC); + kfree(iov); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-7509/0.patch b/Patches/Linux_CVEs/CVE-2015-7509/0.patch new file mode 100644 index 00000000..2aff5f4a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-7509/0.patch @@ -0,0 +1,51 @@ +From c9b92530a723ac5ef8e352885a1862b18f31b2f5 Mon Sep 17 00:00:00 2001 +From: Anatol Pomozov +Date: Tue, 18 Sep 2012 13:38:59 -0400 +Subject: ext4: make orphan functions be no-op in no-journal mode + +Instead of checking whether the handle is valid, we check if journal +is enabled. This avoids taking the s_orphan_lock mutex in all cases +when there is no journal in use, including the error paths where +ext4_orphan_del() is called with a handle set to NULL. + +Signed-off-by: Anatol Pomozov +Signed-off-by: "Theodore Ts'o" +--- + fs/ext4/namei.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 37c03b3..8f4bda7 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2369,7 +2369,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode) + struct ext4_iloc iloc; + int err = 0, rc; + +- if (!ext4_handle_valid(handle)) ++ if (!EXT4_SB(sb)->s_journal) + return 0; + + mutex_lock(&EXT4_SB(sb)->s_orphan_lock); +@@ -2443,8 +2443,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) + struct ext4_iloc iloc; + int err = 0; + +- /* ext4_handle_valid() assumes a valid handle_t pointer */ +- if (handle && !ext4_handle_valid(handle)) ++ if (!EXT4_SB(inode->i_sb)->s_journal) + return 0; + + mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock); +@@ -2463,7 +2462,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) + * transaction handle with which to update the orphan list on + * disk, but we still need to remove the inode from the linked + * list in memory. */ +- if (sbi->s_journal && !handle) ++ if (!handle) + goto out; + + err = ext4_reserve_inode_write(handle, inode, &iloc); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-7515/0.patch b/Patches/Linux_CVEs/CVE-2015-7515/0.patch new file mode 100644 index 00000000..629f71b4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-7515/0.patch @@ -0,0 +1,45 @@ +From 8e20cf2bce122ce9262d6034ee5d5b76fbb92f96 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Tue, 1 Dec 2015 13:09:17 -0800 +Subject: [PATCH] Input: aiptek - fix crash on detecting device without + endpoints + +The aiptek driver crashes in aiptek_probe() when a specially crafted USB +device without endpoints is detected. This fix adds a check that the device +has proper configuration expected by the driver. Also an error return value +is changed to more matching one in one of the error paths. + +Reported-by: Ralf Spenneberg +Signed-off-by: Vladis Dronov +Signed-off-by: Dmitry Torokhov +--- + drivers/input/tablet/aiptek.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c +index e7f966da6efa3..78ca44840d60c 100644 +--- a/drivers/input/tablet/aiptek.c ++++ b/drivers/input/tablet/aiptek.c +@@ -1819,6 +1819,14 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) + input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); + input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0); + ++ /* Verify that a device really has an endpoint */ ++ if (intf->altsetting[0].desc.bNumEndpoints < 1) { ++ dev_err(&intf->dev, ++ "interface has %d endpoints, but must have minimum 1\n", ++ intf->altsetting[0].desc.bNumEndpoints); ++ err = -EINVAL; ++ goto fail3; ++ } + endpoint = &intf->altsetting[0].endpoint[0].desc; + + /* Go set up our URB, which is called when the tablet receives +@@ -1861,6 +1869,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (i == ARRAY_SIZE(speeds)) { + dev_info(&intf->dev, + "Aiptek tried all speeds, no sane response\n"); ++ err = -EINVAL; + goto fail3; + } + diff --git a/Patches/Linux_CVEs/CVE-2015-7515/1.patch b/Patches/Linux_CVEs/CVE-2015-7515/1.patch new file mode 100644 index 00000000..070fe315 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-7515/1.patch @@ -0,0 +1,51 @@ +From 90eb3c037fe3f0f25f01713a92725a8daa2b41f3 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Tue, 1 Dec 2015 13:09:17 -0800 +Subject: Input: aiptek - fix crash on detecting device without endpoints + +commit 8e20cf2bce122ce9262d6034ee5d5b76fbb92f96 upstream. + +The aiptek driver crashes in aiptek_probe() when a specially crafted USB +device without endpoints is detected. This fix adds a check that the device +has proper configuration expected by the driver. Also an error return value +is changed to more matching one in one of the error paths. + +Reported-by: Ralf Spenneberg +Signed-off-by: Vladis Dronov +Signed-off-by: Dmitry Torokhov +[bwh: Backported to 3.2: adjust context] +Signed-off-by: Ben Hutchings +--- + drivers/input/tablet/aiptek.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c +index 6d89fd1..5657018 100644 +--- a/drivers/input/tablet/aiptek.c ++++ b/drivers/input/tablet/aiptek.c +@@ -1810,6 +1810,14 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) + input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); + input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0); + ++ /* Verify that a device really has an endpoint */ ++ if (intf->altsetting[0].desc.bNumEndpoints < 1) { ++ dev_err(&intf->dev, ++ "interface has %d endpoints, but must have minimum 1\n", ++ intf->altsetting[0].desc.bNumEndpoints); ++ err = -EINVAL; ++ goto fail3; ++ } + endpoint = &intf->altsetting[0].endpoint[0].desc; + + /* Go set up our URB, which is called when the tablet receives +@@ -1852,6 +1860,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (i == ARRAY_SIZE(speeds)) { + dev_info(&intf->dev, + "Aiptek tried all speeds, no sane response\n"); ++ err = -EINVAL; + goto fail2; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-7550/0.patch b/Patches/Linux_CVEs/CVE-2015-7550/0.patch new file mode 100644 index 00000000..4a7afa91 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-7550/0.patch @@ -0,0 +1,112 @@ +From b4a1b4f5047e4f54e194681125c74c0aa64d637d Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 18 Dec 2015 01:34:26 +0000 +Subject: [PATCH] KEYS: Fix race between read and revoke + +This fixes CVE-2015-7550. + +There's a race between keyctl_read() and keyctl_revoke(). If the revoke +happens between keyctl_read() checking the validity of a key and the key's +semaphore being taken, then the key type read method will see a revoked key. + +This causes a problem for the user-defined key type because it assumes in +its read method that there will always be a payload in a non-revoked key +and doesn't check for a NULL pointer. + +Fix this by making keyctl_read() check the validity of a key after taking +semaphore instead of before. + +I think the bug was introduced with the original keyrings code. + +This was discovered by a multithreaded test program generated by syzkaller +(http://github.com/google/syzkaller). Here's a cleaned up version: + + #include + #include + #include + void *thr0(void *arg) + { + key_serial_t key = (unsigned long)arg; + keyctl_revoke(key); + return 0; + } + void *thr1(void *arg) + { + key_serial_t key = (unsigned long)arg; + char buffer[16]; + keyctl_read(key, buffer, 16); + return 0; + } + int main() + { + key_serial_t key = add_key("user", "%", "foo", 3, KEY_SPEC_USER_KEYRING); + pthread_t th[5]; + pthread_create(&th[0], 0, thr0, (void *)(unsigned long)key); + pthread_create(&th[1], 0, thr1, (void *)(unsigned long)key); + pthread_create(&th[2], 0, thr0, (void *)(unsigned long)key); + pthread_create(&th[3], 0, thr1, (void *)(unsigned long)key); + pthread_join(th[0], 0); + pthread_join(th[1], 0); + pthread_join(th[2], 0); + pthread_join(th[3], 0); + return 0; + } + +Build as: + + cc -o keyctl-race keyctl-race.c -lkeyutils -lpthread + +Run as: + + while keyctl-race; do :; done + +as it may need several iterations to crash the kernel. The crash can be +summarised as: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 + IP: [] user_read+0x56/0xa3 + ... + Call Trace: + [] keyctl_read_key+0xb6/0xd7 + [] SyS_keyctl+0x83/0xe0 + [] entry_SYSCALL_64_fastpath+0x12/0x6f + +Reported-by: Dmitry Vyukov +Signed-off-by: David Howells +Tested-by: Dmitry Vyukov +Cc: stable@vger.kernel.org +Signed-off-by: James Morris +--- + security/keys/keyctl.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index fb111eafcb893..1c3872aeed14a 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -751,16 +751,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) + + /* the key is probably readable - now try to read it */ + can_read_key: +- ret = key_validate(key); +- if (ret == 0) { +- ret = -EOPNOTSUPP; +- if (key->type->read) { +- /* read the data with the semaphore held (since we +- * might sleep) */ +- down_read(&key->sem); ++ ret = -EOPNOTSUPP; ++ if (key->type->read) { ++ /* Read the data with the semaphore held (since we might sleep) ++ * to protect against the key being updated or revoked. ++ */ ++ down_read(&key->sem); ++ ret = key_validate(key); ++ if (ret == 0) + ret = key->type->read(key, buffer, buflen); +- up_read(&key->sem); +- } ++ up_read(&key->sem); + } + + error2: diff --git a/Patches/Linux_CVEs/CVE-2015-8019/0.patch b/Patches/Linux_CVEs/CVE-2015-8019/0.patch new file mode 100644 index 00000000..5dd1912b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8019/0.patch @@ -0,0 +1,99 @@ +From 813658e0c448f2f5fb3301762076ba5e0f61411c Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 30 Dec 2015 08:51:12 -0500 +Subject: udp: properly support MSG_PEEK with truncated buffers + +Backport of this upstream commit into stable kernels : +89c22d8c3b27 ("net: Fix skb csum races when peeking") +exposed a bug in udp stack vs MSG_PEEK support, when user provides +a buffer smaller than skb payload. + +In this case, +skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov); +returns -EFAULT. + +This bug does not happen in upstream kernels since Al Viro did a great +job to replace this into : +skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), msg); +This variant is safe vs short buffers. + +For the time being, instead reverting Herbert Xu patch and add back +skb->ip_summed invalid changes, simply store the result of +udp_lib_checksum_complete() so that we avoid computing the checksum a +second time, and avoid the problematic +skb_copy_and_csum_datagram_iovec() call. + +This patch can be applied on recent kernels as it avoids a double +checksumming, then backported to stable kernels as a bug fix. + +Signed-off-by: Eric Dumazet +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +[d-cagle@codeaurora.org: Resolve trivial merge conflicts] +Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git +Git-commit: 197c949e7798fbf28cfadc69d9ca0c2abbf93191 +Change-Id: I70f19a362f627bd2d9d8e10e31bbcdb4b0600792 +Signed-off-by: Dennis Cagle +--- + net/ipv4/udp.c | 6 ++++-- + net/ipv6/udp.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 463710f..23d991a 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1215,6 +1215,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + int peeked, off = 0; + int err; + int is_udplite = IS_UDPLITE(sk); ++ bool checksum_valid = false; + bool slow; + + if (flags & MSG_ERRQUEUE) +@@ -1240,11 +1241,12 @@ try_again: + */ + + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { +- if (udp_lib_checksum_complete(skb)) ++ checksum_valid = !udp_lib_checksum_complete(skb); ++ if (!checksum_valid) + goto csum_copy_err; + } + +- if (skb_csum_unnecessary(skb)) ++ if (checksum_valid || skb_csum_unnecessary(skb)) + err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov, copied); + else { +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 2adb069..d689b25 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -370,6 +370,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, + int peeked, off = 0; + int err; + int is_udplite = IS_UDPLITE(sk); ++ bool checksum_valid = false; + int is_udp4; + bool slow; + +@@ -401,11 +402,12 @@ try_again: + */ + + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { +- if (udp_lib_checksum_complete(skb)) ++ checksum_valid = !udp_lib_checksum_complete(skb); ++ if (!checksum_valid) + goto csum_copy_err; + } + +- if (skb_csum_unnecessary(skb)) ++ if (checksum_valid || skb_csum_unnecessary(skb)) + err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov, copied); + else { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8019/1.patch b/Patches/Linux_CVEs/CVE-2015-8019/1.patch new file mode 100644 index 00000000..efb1aaf5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8019/1.patch @@ -0,0 +1,99 @@ +From f1c121b78e68c03f7fe5e9fa7319e53ad29392f3 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 30 Dec 2015 08:51:12 -0500 +Subject: udp: properly support MSG_PEEK with truncated buffers + +Backport of this upstream commit into stable kernels : +89c22d8c3b27 ("net: Fix skb csum races when peeking") +exposed a bug in udp stack vs MSG_PEEK support, when user provides +a buffer smaller than skb payload. + +In this case, +skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov); +returns -EFAULT. + +This bug does not happen in upstream kernels since Al Viro did a great +job to replace this into : +skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), msg); +This variant is safe vs short buffers. + +For the time being, instead reverting Herbert Xu patch and add back +skb->ip_summed invalid changes, simply store the result of +udp_lib_checksum_complete() so that we avoid computing the checksum a +second time, and avoid the problematic +skb_copy_and_csum_datagram_iovec() call. + +This patch can be applied on recent kernels as it avoids a double +checksumming, then backported to stable kernels as a bug fix. + +Signed-off-by: Eric Dumazet +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +[d-cagle@codeaurora.org: Resolve trivial merge conflicts] +Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git +Git-commit: 197c949e7798fbf28cfadc69d9ca0c2abbf93191 +Change-Id: I70f19a362f627bd2d9d8e10e31bbcdb4b0600792 +Signed-off-by: Dennis Cagle +--- + net/ipv4/udp.c | 6 ++++-- + net/ipv6/udp.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 44a7c83..9f8f9ae5 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1258,6 +1258,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + int peeked, off = 0; + int err; + int is_udplite = IS_UDPLITE(sk); ++ bool checksum_valid = false; + bool slow; + + if (flags & MSG_ERRQUEUE) +@@ -1283,11 +1284,12 @@ try_again: + */ + + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { +- if (udp_lib_checksum_complete(skb)) ++ checksum_valid = !udp_lib_checksum_complete(skb); ++ if (!checksum_valid) + goto csum_copy_err; + } + +- if (skb_csum_unnecessary(skb)) ++ if (checksum_valid || skb_csum_unnecessary(skb)) + err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov, copied); + else { +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 9786416..c48441d 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -388,6 +388,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, + int peeked, off = 0; + int err; + int is_udplite = IS_UDPLITE(sk); ++ bool checksum_valid = false; + int is_udp4; + bool slow; + +@@ -419,11 +420,12 @@ try_again: + */ + + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { +- if (udp_lib_checksum_complete(skb)) ++ checksum_valid = !udp_lib_checksum_complete(skb); ++ if (!checksum_valid) + goto csum_copy_err; + } + +- if (skb_csum_unnecessary(skb)) ++ if (checksum_valid || skb_csum_unnecessary(skb)) + err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov, copied); + else { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8019/2.patch b/Patches/Linux_CVEs/CVE-2015-8019/2.patch new file mode 100644 index 00000000..1d12eaa4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8019/2.patch @@ -0,0 +1,94 @@ +From 197c949e7798fbf28cfadc69d9ca0c2abbf93191 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 30 Dec 2015 08:51:12 -0500 +Subject: udp: properly support MSG_PEEK with truncated buffers + +Backport of this upstream commit into stable kernels : +89c22d8c3b27 ("net: Fix skb csum races when peeking") +exposed a bug in udp stack vs MSG_PEEK support, when user provides +a buffer smaller than skb payload. + +In this case, +skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov); +returns -EFAULT. + +This bug does not happen in upstream kernels since Al Viro did a great +job to replace this into : +skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), msg); +This variant is safe vs short buffers. + +For the time being, instead reverting Herbert Xu patch and add back +skb->ip_summed invalid changes, simply store the result of +udp_lib_checksum_complete() so that we avoid computing the checksum a +second time, and avoid the problematic +skb_copy_and_csum_datagram_iovec() call. + +This patch can be applied on recent kernels as it avoids a double +checksumming, then backported to stable kernels as a bug fix. + +Signed-off-by: Eric Dumazet +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +--- + net/ipv4/udp.c | 6 ++++-- + net/ipv6/udp.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 8841e98..ac14ae4 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1271,6 +1271,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, + int peeked, off = 0; + int err; + int is_udplite = IS_UDPLITE(sk); ++ bool checksum_valid = false; + bool slow; + + if (flags & MSG_ERRQUEUE) +@@ -1296,11 +1297,12 @@ try_again: + */ + + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { +- if (udp_lib_checksum_complete(skb)) ++ checksum_valid = !udp_lib_checksum_complete(skb); ++ if (!checksum_valid) + goto csum_copy_err; + } + +- if (skb_csum_unnecessary(skb)) ++ if (checksum_valid || skb_csum_unnecessary(skb)) + err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), + msg, copied); + else { +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 9da3287..00775ee 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -402,6 +402,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + int peeked, off = 0; + int err; + int is_udplite = IS_UDPLITE(sk); ++ bool checksum_valid = false; + int is_udp4; + bool slow; + +@@ -433,11 +434,12 @@ try_again: + */ + + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { +- if (udp_lib_checksum_complete(skb)) ++ checksum_valid = !udp_lib_checksum_complete(skb); ++ if (!checksum_valid) + goto csum_copy_err; + } + +- if (skb_csum_unnecessary(skb)) ++ if (checksum_valid || skb_csum_unnecessary(skb)) + err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), + msg, copied); + else { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8539/0.patch b/Patches/Linux_CVEs/CVE-2015-8539/0.patch new file mode 100644 index 00000000..f86c3c40 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8539/0.patch @@ -0,0 +1,125 @@ +From 096fe9eaea40a17e125569f9e657e34cdb6d73bd Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 24 Nov 2015 21:36:31 +0000 +Subject: KEYS: Fix handling of stored error in a negatively instantiated user + key + +If a user key gets negatively instantiated, an error code is cached in the +payload area. A negatively instantiated key may be then be positively +instantiated by updating it with valid data. However, the ->update key +type method must be aware that the error code may be there. + +The following may be used to trigger the bug in the user key type: + + keyctl request2 user user "" @u + keyctl add user user "a" @u + +which manifests itself as: + + BUG: unable to handle kernel paging request at 00000000ffffff8a + IP: [] __call_rcu.constprop.76+0x1f/0x280 kernel/rcu/tree.c:3046 + PGD 7cc30067 PUD 0 + Oops: 0002 [#1] SMP + Modules linked in: + CPU: 3 PID: 2644 Comm: a.out Not tainted 4.3.0+ #49 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + task: ffff88003ddea700 ti: ffff88003dd88000 task.ti: ffff88003dd88000 + RIP: 0010:[] [] __call_rcu.constprop.76+0x1f/0x280 + [] __call_rcu.constprop.76+0x1f/0x280 kernel/rcu/tree.c:3046 + RSP: 0018:ffff88003dd8bdb0 EFLAGS: 00010246 + RAX: 00000000ffffff82 RBX: 0000000000000000 RCX: 0000000000000001 + RDX: ffffffff81e3fe40 RSI: 0000000000000000 RDI: 00000000ffffff82 + RBP: ffff88003dd8bde0 R08: ffff88007d2d2da0 R09: 0000000000000000 + R10: 0000000000000000 R11: ffff88003e8073c0 R12: 00000000ffffff82 + R13: ffff88003dd8be68 R14: ffff88007d027600 R15: ffff88003ddea700 + FS: 0000000000b92880(0063) GS:ffff88007fd00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b + CR2: 00000000ffffff8a CR3: 000000007cc5f000 CR4: 00000000000006e0 + Stack: + ffff88003dd8bdf0 ffffffff81160a8a 0000000000000000 00000000ffffff82 + ffff88003dd8be68 ffff88007d027600 ffff88003dd8bdf0 ffffffff810a39e5 + ffff88003dd8be20 ffffffff812a31ab ffff88007d027600 ffff88007d027620 + Call Trace: + [] kfree_call_rcu+0x15/0x20 kernel/rcu/tree.c:3136 + [] user_update+0x8b/0xb0 security/keys/user_defined.c:129 + [< inline >] __key_update security/keys/key.c:730 + [] key_create_or_update+0x291/0x440 security/keys/key.c:908 + [< inline >] SYSC_add_key security/keys/keyctl.c:125 + [] SyS_add_key+0x101/0x1e0 security/keys/keyctl.c:60 + [] entry_SYSCALL_64_fastpath+0x12/0x6a arch/x86/entry/entry_64.S:185 + +Note the error code (-ENOKEY) in EDX. + +A similar bug can be tripped by: + + keyctl request2 trusted user "" @u + keyctl add trusted user "a" @u + +This should also affect encrypted keys - but that has to be correctly +parameterised or it will fail with EINVAL before getting to the bit that +will crashes. + +Reported-by: Dmitry Vyukov +Signed-off-by: David Howells +Acked-by: Mimi Zohar +Signed-off-by: James Morris +--- + security/keys/encrypted-keys/encrypted.c | 2 ++ + security/keys/trusted.c | 5 ++++- + security/keys/user_defined.c | 5 ++++- + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 927db9f..696ccfa 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -845,6 +845,8 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) + size_t datalen = prep->datalen; + int ret = 0; + ++ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) ++ return -ENOKEY; + if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + +diff --git a/security/keys/trusted.c b/security/keys/trusted.c +index 903dace..16dec53 100644 +--- a/security/keys/trusted.c ++++ b/security/keys/trusted.c +@@ -1007,13 +1007,16 @@ static void trusted_rcu_free(struct rcu_head *rcu) + */ + static int trusted_update(struct key *key, struct key_preparsed_payload *prep) + { +- struct trusted_key_payload *p = key->payload.data[0]; ++ struct trusted_key_payload *p; + struct trusted_key_payload *new_p; + struct trusted_key_options *new_o; + size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + ++ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) ++ return -ENOKEY; ++ p = key->payload.data[0]; + if (!p->migratable) + return -EPERM; + if (datalen <= 0 || datalen > 32767 || !prep->data) +diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c +index 28cb30f..8705d79 100644 +--- a/security/keys/user_defined.c ++++ b/security/keys/user_defined.c +@@ -120,7 +120,10 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) + + if (ret == 0) { + /* attach the new data, displacing the old */ +- zap = key->payload.data[0]; ++ if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) ++ zap = key->payload.data[0]; ++ else ++ zap = NULL; + rcu_assign_keypointer(key, upayload); + key->expiry = 0; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8543/0.patch b/Patches/Linux_CVEs/CVE-2015-8543/0.patch new file mode 100644 index 00000000..f66c0fb6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8543/0.patch @@ -0,0 +1,139 @@ +From 79462ad02e861803b3840cc782248c7359451cd9 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Mon, 14 Dec 2015 22:03:39 +0100 +Subject: net: add validation for the socket syscall protocol argument +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +郭永刚 reported that one could simply crash the kernel as root by +using a simple program: + + int socket_fd; + struct sockaddr_in addr; + addr.sin_port = 0; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = 10; + + socket_fd = socket(10,3,0x40000000); + connect(socket_fd , &addr,16); + +AF_INET, AF_INET6 sockets actually only support 8-bit protocol +identifiers. inet_sock's skc_protocol field thus is sized accordingly, +thus larger protocol identifiers simply cut off the higher bits and +store a zero in the protocol fields. + +This could lead to e.g. NULL function pointer because as a result of +the cut off inet_num is zero and we call down to inet_autobind, which +is NULL for raw sockets. + +kernel: Call Trace: +kernel: [] ? inet_autobind+0x2e/0x70 +kernel: [] inet_dgram_connect+0x54/0x80 +kernel: [] SYSC_connect+0xd9/0x110 +kernel: [] ? ptrace_notify+0x5b/0x80 +kernel: [] ? syscall_trace_enter_phase2+0x108/0x200 +kernel: [] SyS_connect+0xe/0x10 +kernel: [] tracesys_phase2+0x84/0x89 + +I found no particular commit which introduced this problem. + +CVE: CVE-2015-8543 +Cc: Cong Wang +Reported-by: 郭永刚 +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +--- + include/net/sock.h | 1 + + net/ax25/af_ax25.c | 3 +++ + net/decnet/af_decnet.c | 3 +++ + net/ipv4/af_inet.c | 3 +++ + net/ipv6/af_inet6.c | 3 +++ + net/irda/af_irda.c | 3 +++ + 6 files changed, 16 insertions(+) + +diff --git a/include/net/sock.h b/include/net/sock.h +index eaef414..c4205e0 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -403,6 +403,7 @@ struct sock { + sk_no_check_rx : 1, + sk_userlocks : 4, + sk_protocol : 8, ++#define SK_PROTOCOL_MAX U8_MAX + sk_type : 16; + kmemcheck_bitfield_end(flags); + int sk_wmem_queued; +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index ae3a47f..fbd0acf 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -805,6 +805,9 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol, + struct sock *sk; + ax25_cb *ax25; + ++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX) ++ return -EINVAL; ++ + if (!net_eq(net, &init_net)) + return -EAFNOSUPPORT; + +diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c +index eebf5ac..13d6b1a 100644 +--- a/net/decnet/af_decnet.c ++++ b/net/decnet/af_decnet.c +@@ -678,6 +678,9 @@ static int dn_create(struct net *net, struct socket *sock, int protocol, + { + struct sock *sk; + ++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX) ++ return -EINVAL; ++ + if (!net_eq(net, &init_net)) + return -EAFNOSUPPORT; + +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 11c4ca1..5c5db66 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -257,6 +257,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol, + int try_loading_module = 0; + int err; + ++ if (protocol < 0 || protocol >= IPPROTO_MAX) ++ return -EINVAL; ++ + sock->state = SS_UNCONNECTED; + + /* Look for the requested type/protocol pair. */ +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index 8ec0df7..9f5137c 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -109,6 +109,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, + int try_loading_module = 0; + int err; + ++ if (protocol < 0 || protocol >= IPPROTO_MAX) ++ return -EINVAL; ++ + /* Look for the requested type/protocol pair. */ + lookup_protocol: + err = -ESOCKTNOSUPPORT; +diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c +index e6aa48b..923abd6 100644 +--- a/net/irda/af_irda.c ++++ b/net/irda/af_irda.c +@@ -1086,6 +1086,9 @@ static int irda_create(struct net *net, struct socket *sock, int protocol, + struct sock *sk; + struct irda_sock *self; + ++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX) ++ return -EINVAL; ++ + if (net != &init_net) + return -EAFNOSUPPORT; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8575/0.patch b/Patches/Linux_CVEs/CVE-2015-8575/0.patch new file mode 100644 index 00000000..fc4f4b88 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8575/0.patch @@ -0,0 +1,27 @@ +From 5233252fce714053f0151680933571a2da9cbfb4 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 15 Dec 2015 15:39:08 -0500 +Subject: bluetooth: Validate socket address length in sco_sock_bind(). + +Signed-off-by: David S. Miller +--- + net/bluetooth/sco.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index fe12966..f52bcbf 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -526,6 +526,9 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, + if (!addr || addr->sa_family != AF_BLUETOOTH) + return -EINVAL; + ++ if (addr_len < sizeof(struct sockaddr_sco)) ++ return -EINVAL; ++ + lock_sock(sk); + + if (sk->sk_state != BT_OPEN) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8785/0.patch b/Patches/Linux_CVEs/CVE-2015-8785/0.patch new file mode 100644 index 00000000..a89c4805 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8785/0.patch @@ -0,0 +1,61 @@ +From 3ca8138f014a913f98e6ef40e939868e1e9ea876 Mon Sep 17 00:00:00 2001 +From: Roman Gushchin +Date: Mon, 12 Oct 2015 16:33:44 +0300 +Subject: fuse: break infinite loop in fuse_fill_write_pages() + +I got a report about unkillable task eating CPU. Further +investigation shows, that the problem is in the fuse_fill_write_pages() +function. If iov's first segment has zero length, we get an infinite +loop, because we never reach iov_iter_advance() call. + +Fix this by calling iov_iter_advance() before repeating an attempt to +copy data from userspace. + +A similar problem is described in 124d3b7041f ("fix writev regression: +pan hanging unkillable and un-straceable"). If zero-length segmend +is followed by segment with invalid address, +iov_iter_fault_in_readable() checks only first segment (zero-length), +iov_iter_copy_from_user_atomic() skips it, fails at second and +returns zero -> goto again without skipping zero-length segment. + +Patch calls iov_iter_advance() before goto again: we'll skip zero-length +segment at second iteraction and iov_iter_fault_in_readable() will detect +invalid address. + +Special thanks to Konstantin Khlebnikov, who helped a lot with the commit +description. + +Cc: Andrew Morton +Cc: Maxim Patlasov +Cc: Konstantin Khlebnikov +Signed-off-by: Roman Gushchin +Signed-off-by: Miklos Szeredi +Fixes: ea9b9907b82a ("fuse: implement perform_write") +Cc: +--- + fs/fuse/file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index f523f2f..195476a 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1049,6 +1049,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, + tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); + flush_dcache_page(page); + ++ iov_iter_advance(ii, tmp); + if (!tmp) { + unlock_page(page); + page_cache_release(page); +@@ -1061,7 +1062,6 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, + req->page_descs[req->num_pages].length = tmp; + req->num_pages++; + +- iov_iter_advance(ii, tmp); + count += tmp; + pos += tmp; + offset += tmp; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8830/0.patch b/Patches/Linux_CVEs/CVE-2015-8830/0.patch new file mode 100644 index 00000000..06b89153 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8830/0.patch @@ -0,0 +1,84 @@ +From 4c185ce06dca14f5cea192f5a2c981ef50663f2b Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 20 Mar 2015 20:17:32 -0400 +Subject: aio: lift iov_iter_init() into aio_setup_..._rw() + +the only non-trivial detail is that we do it before rw_verify_area(), +so we'd better cap the length ourselves in aio_setup_single_rw() +case (for vectored case rw_copy_check_uvector() will do that for us). + +Signed-off-by: Al Viro +--- + fs/aio.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/fs/aio.c b/fs/aio.c +index 435ca29..7816e8e 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -1357,7 +1357,8 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, + unsigned long *nr_segs, + size_t *len, + struct iovec **iovec, +- bool compat) ++ bool compat, ++ struct iov_iter *iter) + { + ssize_t ret; + +@@ -1378,6 +1379,7 @@ static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb, + + /* len now reflect bytes instead of segs */ + *len = ret; ++ iov_iter_init(iter, rw, *iovec, *nr_segs, *len); + return 0; + } + +@@ -1385,14 +1387,18 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb, + int rw, char __user *buf, + unsigned long *nr_segs, + size_t len, +- struct iovec *iovec) ++ struct iovec *iovec, ++ struct iov_iter *iter) + { ++ if (len > MAX_RW_COUNT) ++ len = MAX_RW_COUNT; + if (unlikely(!access_ok(!rw, buf, len))) + return -EFAULT; + + iovec->iov_base = buf; + iovec->iov_len = len; + *nr_segs = 1; ++ iov_iter_init(iter, rw, iovec, *nr_segs, len); + return 0; + } + +@@ -1438,10 +1444,10 @@ rw_common: + + if (opcode == IOCB_CMD_PREADV || opcode == IOCB_CMD_PWRITEV) + ret = aio_setup_vectored_rw(req, rw, buf, &nr_segs, +- &len, &iovec, compat); ++ &len, &iovec, compat, &iter); + else + ret = aio_setup_single_vector(req, rw, buf, &nr_segs, +- len, iovec); ++ len, iovec, &iter); + if (!ret) + ret = rw_verify_area(rw, file, &req->ki_pos, len); + if (ret < 0) { +@@ -1463,10 +1469,9 @@ rw_common: + file_start_write(file); + + if (iter_op) { +- iov_iter_init(&iter, rw, iovec, nr_segs, len); + ret = iter_op(req, &iter); + } else { +- ret = rw_op(req, iovec, nr_segs, req->ki_pos); ++ ret = rw_op(req, iter.iov, iter.nr_segs, req->ki_pos); + } + + if (rw == WRITE) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8830/1.patch b/Patches/Linux_CVEs/CVE-2015-8830/1.patch new file mode 100644 index 00000000..7b75df93 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8830/1.patch @@ -0,0 +1,106 @@ +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/Linux_CVEs/CVE-2015-8839/0.patch b/Patches/Linux_CVEs/CVE-2015-8839/0.patch new file mode 100644 index 00000000..16b5fa3f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8839/0.patch @@ -0,0 +1,442 @@ +From ea3d7209ca01da209cda6f0dea8be9cc4b7a933b Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 7 Dec 2015 14:28:03 -0500 +Subject: ext4: fix races between page faults and hole punching + +Currently, page faults and hole punching are completely unsynchronized. +This can result in page fault faulting in a page into a range that we +are punching after truncate_pagecache_range() has been called and thus +we can end up with a page mapped to disk blocks that will be shortly +freed. Filesystem corruption will shortly follow. Note that the same +race is avoided for truncate by checking page fault offset against +i_size but there isn't similar mechanism available for punching holes. + +Fix the problem by creating new rw semaphore i_mmap_sem in inode and +grab it for writing over truncate, hole punching, and other functions +removing blocks from extent tree and for read over page faults. We +cannot easily use i_data_sem for this since that ranks below transaction +start and we need something ranking above it so that it can be held over +the whole truncate / hole punching operation. Also remove various +workarounds we had in the code to reduce race window when page fault +could have created pages with stale mapping information. + +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +--- + fs/ext4/ext4.h | 10 +++++++++ + fs/ext4/extents.c | 54 ++++++++++++++++++++++++-------------------- + fs/ext4/file.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++-------- + fs/ext4/inode.c | 36 +++++++++++++++++++++-------- + fs/ext4/super.c | 1 + + fs/ext4/truncate.h | 2 ++ + 6 files changed, 127 insertions(+), 42 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index cc7ca4e..348a5ff 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -910,6 +910,15 @@ struct ext4_inode_info { + * by other means, so we have i_data_sem. + */ + struct rw_semaphore i_data_sem; ++ /* ++ * i_mmap_sem is for serializing page faults with truncate / punch hole ++ * operations. We have to make sure that new page cannot be faulted in ++ * a section of the inode that is being punched. We cannot easily use ++ * i_data_sem for this since we need protection for the whole punch ++ * operation and i_data_sem ranks below transaction start so we have ++ * to occasionally drop it. ++ */ ++ struct rw_semaphore i_mmap_sem; + struct inode vfs_inode; + struct jbd2_inode *jinode; + +@@ -2484,6 +2493,7 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); + extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode, + loff_t lstart, loff_t lend); + extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); ++extern int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf); + extern qsize_t *ext4_get_reserved_space(struct inode *inode); + extern void ext4_da_update_reserve_space(struct inode *inode, + int used, int quota_claim); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 551353b..5be9ca5 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4770,7 +4770,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, + int partial_begin, partial_end; + loff_t start, end; + ext4_lblk_t lblk; +- struct address_space *mapping = inode->i_mapping; + unsigned int blkbits = inode->i_blkbits; + + trace_ext4_zero_range(inode, offset, len, mode); +@@ -4786,17 +4785,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, + } + + /* +- * Write out all dirty pages to avoid race conditions +- * Then release them. +- */ +- if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { +- ret = filemap_write_and_wait_range(mapping, offset, +- offset + len - 1); +- if (ret) +- return ret; +- } +- +- /* + * Round up offset. This is not fallocate, we neet to zero out + * blocks, so convert interior block aligned part of the range to + * unwritten and possibly manually zero out unaligned parts of the +@@ -4856,16 +4844,22 @@ static long ext4_zero_range(struct file *file, loff_t offset, + flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | + EXT4_EX_NOCACHE); + +- /* Now release the pages and zero block aligned part of pages*/ +- truncate_pagecache_range(inode, start, end - 1); +- inode->i_mtime = inode->i_ctime = ext4_current_time(inode); +- + /* Wait all existing dio workers, newcomers will block on i_mutex */ + ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); + ++ /* ++ * Prevent page faults from reinstantiating pages we have ++ * released from page cache. ++ */ ++ down_write(&EXT4_I(inode)->i_mmap_sem); ++ /* Now release the pages and zero block aligned part of pages */ ++ truncate_pagecache_range(inode, start, end - 1); ++ inode->i_mtime = inode->i_ctime = ext4_current_time(inode); ++ + ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size, + flags, mode); ++ up_write(&EXT4_I(inode)->i_mmap_sem); + if (ret) + goto out_dio; + } +@@ -5524,17 +5518,22 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + goto out_mutex; + } + +- truncate_pagecache(inode, ioffset); +- + /* Wait for existing dio to complete */ + ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); + ++ /* ++ * Prevent page faults from reinstantiating pages we have released from ++ * page cache. ++ */ ++ down_write(&EXT4_I(inode)->i_mmap_sem); ++ truncate_pagecache(inode, ioffset); ++ + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); +- goto out_dio; ++ goto out_mmap; + } + + down_write(&EXT4_I(inode)->i_data_sem); +@@ -5573,7 +5572,8 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + + out_stop: + ext4_journal_stop(handle); +-out_dio: ++out_mmap: ++ up_write(&EXT4_I(inode)->i_mmap_sem); + ext4_inode_resume_unlocked_dio(inode); + out_mutex: + mutex_unlock(&inode->i_mutex); +@@ -5660,17 +5660,22 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) + goto out_mutex; + } + +- truncate_pagecache(inode, ioffset); +- + /* Wait for existing dio to complete */ + ext4_inode_block_unlocked_dio(inode); + inode_dio_wait(inode); + ++ /* ++ * Prevent page faults from reinstantiating pages we have released from ++ * page cache. ++ */ ++ down_write(&EXT4_I(inode)->i_mmap_sem); ++ truncate_pagecache(inode, ioffset); ++ + credits = ext4_writepage_trans_blocks(inode); + handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); +- goto out_dio; ++ goto out_mmap; + } + + /* Expand file to avoid data loss if there is error while shifting */ +@@ -5741,7 +5746,8 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len) + + out_stop: + ext4_journal_stop(handle); +-out_dio: ++out_mmap: ++ up_write(&EXT4_I(inode)->i_mmap_sem); + ext4_inode_resume_unlocked_dio(inode); + out_mutex: + mutex_unlock(&inode->i_mutex); +diff --git a/fs/ext4/file.c b/fs/ext4/file.c +index 113837e..0d24ebc 100644 +--- a/fs/ext4/file.c ++++ b/fs/ext4/file.c +@@ -209,15 +209,18 @@ static int ext4_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf) + { + int result; + handle_t *handle = NULL; +- struct super_block *sb = file_inode(vma->vm_file)->i_sb; ++ struct inode *inode = file_inode(vma->vm_file); ++ struct super_block *sb = inode->i_sb; + bool write = vmf->flags & FAULT_FLAG_WRITE; + + if (write) { + sb_start_pagefault(sb); + file_update_time(vma->vm_file); ++ down_read(&EXT4_I(inode)->i_mmap_sem); + handle = ext4_journal_start_sb(sb, EXT4_HT_WRITE_PAGE, + EXT4_DATA_TRANS_BLOCKS(sb)); +- } ++ } else ++ down_read(&EXT4_I(inode)->i_mmap_sem); + + if (IS_ERR(handle)) + result = VM_FAULT_SIGBUS; +@@ -228,8 +231,10 @@ static int ext4_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf) + if (write) { + if (!IS_ERR(handle)) + ext4_journal_stop(handle); ++ up_read(&EXT4_I(inode)->i_mmap_sem); + sb_end_pagefault(sb); +- } ++ } else ++ up_read(&EXT4_I(inode)->i_mmap_sem); + + return result; + } +@@ -246,10 +251,12 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, + if (write) { + sb_start_pagefault(sb); + file_update_time(vma->vm_file); ++ down_read(&EXT4_I(inode)->i_mmap_sem); + handle = ext4_journal_start_sb(sb, EXT4_HT_WRITE_PAGE, + ext4_chunk_trans_blocks(inode, + PMD_SIZE / PAGE_SIZE)); +- } ++ } else ++ down_read(&EXT4_I(inode)->i_mmap_sem); + + if (IS_ERR(handle)) + result = VM_FAULT_SIGBUS; +@@ -260,30 +267,71 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr, + if (write) { + if (!IS_ERR(handle)) + ext4_journal_stop(handle); ++ up_read(&EXT4_I(inode)->i_mmap_sem); + sb_end_pagefault(sb); +- } ++ } else ++ up_read(&EXT4_I(inode)->i_mmap_sem); + + return result; + } + + static int ext4_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) + { +- return dax_mkwrite(vma, vmf, ext4_get_block_dax, +- ext4_end_io_unwritten); ++ int err; ++ struct inode *inode = file_inode(vma->vm_file); ++ ++ sb_start_pagefault(inode->i_sb); ++ file_update_time(vma->vm_file); ++ down_read(&EXT4_I(inode)->i_mmap_sem); ++ err = __dax_mkwrite(vma, vmf, ext4_get_block_dax, ++ ext4_end_io_unwritten); ++ up_read(&EXT4_I(inode)->i_mmap_sem); ++ sb_end_pagefault(inode->i_sb); ++ ++ return err; ++} ++ ++/* ++ * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_mkwrite() ++ * handler we check for races agaist truncate. Note that since we cycle through ++ * i_mmap_sem, we are sure that also any hole punching that began before we ++ * were called is finished by now and so if it included part of the file we ++ * are working on, our pte will get unmapped and the check for pte_same() in ++ * wp_pfn_shared() fails. Thus fault gets retried and things work out as ++ * desired. ++ */ ++static int ext4_dax_pfn_mkwrite(struct vm_area_struct *vma, ++ struct vm_fault *vmf) ++{ ++ struct inode *inode = file_inode(vma->vm_file); ++ struct super_block *sb = inode->i_sb; ++ int ret = VM_FAULT_NOPAGE; ++ loff_t size; ++ ++ sb_start_pagefault(sb); ++ file_update_time(vma->vm_file); ++ down_read(&EXT4_I(inode)->i_mmap_sem); ++ size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT; ++ if (vmf->pgoff >= size) ++ ret = VM_FAULT_SIGBUS; ++ up_read(&EXT4_I(inode)->i_mmap_sem); ++ sb_end_pagefault(sb); ++ ++ return ret; + } + + static const struct vm_operations_struct ext4_dax_vm_ops = { + .fault = ext4_dax_fault, + .pmd_fault = ext4_dax_pmd_fault, + .page_mkwrite = ext4_dax_mkwrite, +- .pfn_mkwrite = dax_pfn_mkwrite, ++ .pfn_mkwrite = ext4_dax_pfn_mkwrite, + }; + #else + #define ext4_dax_vm_ops ext4_file_vm_ops + #endif + + static const struct vm_operations_struct ext4_file_vm_ops = { +- .fault = filemap_fault, ++ .fault = ext4_filemap_fault, + .map_pages = filemap_map_pages, + .page_mkwrite = ext4_page_mkwrite, + }; +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index ea433a7..d1207d0 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3623,6 +3623,15 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + + } + ++ /* Wait all existing dio workers, newcomers will block on i_mutex */ ++ ext4_inode_block_unlocked_dio(inode); ++ inode_dio_wait(inode); ++ ++ /* ++ * Prevent page faults from reinstantiating pages we have released from ++ * page cache. ++ */ ++ down_write(&EXT4_I(inode)->i_mmap_sem); + first_block_offset = round_up(offset, sb->s_blocksize); + last_block_offset = round_down((offset + length), sb->s_blocksize) - 1; + +@@ -3631,10 +3640,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + truncate_pagecache_range(inode, first_block_offset, + last_block_offset); + +- /* Wait all existing dio workers, newcomers will block on i_mutex */ +- ext4_inode_block_unlocked_dio(inode); +- inode_dio_wait(inode); +- + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) + credits = ext4_writepage_trans_blocks(inode); + else +@@ -3680,16 +3685,12 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + if (IS_SYNC(inode)) + ext4_handle_sync(handle); + +- /* Now release the pages again to reduce race window */ +- if (last_block_offset > first_block_offset) +- truncate_pagecache_range(inode, first_block_offset, +- last_block_offset); +- + inode->i_mtime = inode->i_ctime = ext4_current_time(inode); + ext4_mark_inode_dirty(handle, inode); + out_stop: + ext4_journal_stop(handle); + out_dio: ++ up_write(&EXT4_I(inode)->i_mmap_sem); + ext4_inode_resume_unlocked_dio(inode); + out_mutex: + mutex_unlock(&inode->i_mutex); +@@ -4823,6 +4824,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + } else + ext4_wait_for_tail_page_commit(inode); + } ++ down_write(&EXT4_I(inode)->i_mmap_sem); + /* + * Truncate pagecache after we've waited for commit + * in data=journal mode to make pages freeable. +@@ -4830,6 +4832,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) + truncate_pagecache(inode, inode->i_size); + if (shrink) + ext4_truncate(inode); ++ up_write(&EXT4_I(inode)->i_mmap_sem); + } + + if (!rc) { +@@ -5278,6 +5281,8 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) + + sb_start_pagefault(inode->i_sb); + file_update_time(vma->vm_file); ++ ++ down_read(&EXT4_I(inode)->i_mmap_sem); + /* Delalloc case is easy... */ + if (test_opt(inode->i_sb, DELALLOC) && + !ext4_should_journal_data(inode) && +@@ -5347,6 +5352,19 @@ retry_alloc: + out_ret: + ret = block_page_mkwrite_return(ret); + out: ++ up_read(&EXT4_I(inode)->i_mmap_sem); + sb_end_pagefault(inode->i_sb); + return ret; + } ++ ++int ext4_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++{ ++ struct inode *inode = file_inode(vma->vm_file); ++ int err; ++ ++ down_read(&EXT4_I(inode)->i_mmap_sem); ++ err = filemap_fault(vma, vmf); ++ up_read(&EXT4_I(inode)->i_mmap_sem); ++ ++ return err; ++} +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index c9ab67d..493370e 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -958,6 +958,7 @@ static void init_once(void *foo) + INIT_LIST_HEAD(&ei->i_orphan); + init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->i_data_sem); ++ init_rwsem(&ei->i_mmap_sem); + inode_init_once(&ei->vfs_inode); + } + +diff --git a/fs/ext4/truncate.h b/fs/ext4/truncate.h +index 011ba66..c70d06a 100644 +--- a/fs/ext4/truncate.h ++++ b/fs/ext4/truncate.h +@@ -10,8 +10,10 @@ + */ + static inline void ext4_truncate_failed_write(struct inode *inode) + { ++ down_write(&EXT4_I(inode)->i_mmap_sem); + truncate_inode_pages(inode->i_mapping, inode->i_size); + ext4_truncate(inode); ++ up_write(&EXT4_I(inode)->i_mmap_sem); + } + + /* +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8839/1.patch b/Patches/Linux_CVEs/CVE-2015-8839/1.patch new file mode 100644 index 00000000..d3684165 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8839/1.patch @@ -0,0 +1,37 @@ +From f0ac071fc6660c1d8d4b0d0dbe7642dd1274e4a5 Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Mon, 18 Jul 2016 12:45:17 -0700 +Subject: [PATCH] fs: ext4: disable support for fallocate FALLOC_FL_PUNCH_HOLE + +Bug: 28760453 +Change-Id: I019c2de559db9e4b95860ab852211b456d78c4ca +Signed-off-by: Nick Desaulniers +--- + fs/ext4/inode.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 589d6d3134e01..bf37388aa01b7 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3503,6 +3503,7 @@ int ext4_can_truncate(struct inode *inode) + + int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + { ++#if 0 + struct super_block *sb = inode->i_sb; + ext4_lblk_t first_block, stop_block; + struct address_space *mapping = inode->i_mapping; +@@ -3626,6 +3627,12 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length) + out_mutex: + mutex_unlock(&inode->i_mutex); + return ret; ++#else ++ /* ++ * Disabled as per b/28760453 ++ */ ++ return -EOPNOTSUPP; ++#endif + } + + int ext4_inode_attach_jinode(struct inode *inode) diff --git a/Patches/Linux_CVEs/CVE-2015-8937/0.patch b/Patches/Linux_CVEs/CVE-2015-8937/0.patch new file mode 100644 index 00000000..65ec4018 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8937/0.patch @@ -0,0 +1,36 @@ +From c66202b9288cc4ab1c38f7c928fa1005c285c170 Mon Sep 17 00:00:00 2001 +From: Ravi Aravamudhan +Date: Wed, 11 Feb 2015 17:21:11 -0800 +Subject: diag: Make fixes to diag_switch_logging + +Diag driver holds on to the socket process task structure even +after signaling the process to exit. This patch clears the internal +handle after signaling. + +Change-Id: I642fb595fc2caebc6f2f5419efed4fb560e4e4db +Signed-off-by: Ravi Aravamudhan +--- + drivers/char/diag/diagchar_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c +index 331ed97..b8343c3 100644 +--- a/drivers/char/diag/diagchar_core.c ++++ b/drivers/char/diag/diagchar_core.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2008-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2008-2015, The 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 +@@ -930,6 +930,7 @@ static int diag_switch_logging(int requested_mode) + pr_err("socket process, status: %d\n", + status); + } ++ driver->socket_process = NULL; + } + } else if (driver->logging_mode == SOCKET_MODE) { + driver->socket_process = current; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8938/0.patch b/Patches/Linux_CVEs/CVE-2015-8938/0.patch new file mode 100644 index 00000000..8eae46ad --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8938/0.patch @@ -0,0 +1,255 @@ +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/Linux_CVEs/CVE-2015-8939/0.patch b/Patches/Linux_CVEs/CVE-2015-8939/0.patch new file mode 100644 index 00000000..05b7d3ad --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8939/0.patch @@ -0,0 +1,67 @@ +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/Linux_CVEs/CVE-2015-8940/0.patch b/Patches/Linux_CVEs/CVE-2015-8940/0.patch new file mode 100644 index 00000000..40f6f6f5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8940/0.patch @@ -0,0 +1,48 @@ +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/Linux_CVEs/CVE-2015-8941/0.patch b/Patches/Linux_CVEs/CVE-2015-8941/0.patch new file mode 100644 index 00000000..b52c04b1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8941/0.patch @@ -0,0 +1,159 @@ +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/Linux_CVEs/CVE-2015-8942/0.patch b/Patches/Linux_CVEs/CVE-2015-8942/0.patch new file mode 100644 index 00000000..7bb486f8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8942/0.patch @@ -0,0 +1,31 @@ +From 9ec380c06bbd79493828fcc3c876d8a53fd3369f Mon Sep 17 00:00:00 2001 +From: Iliya Varadzhakov +Date: Fri, 13 Mar 2015 07:33:18 -0700 +Subject: msm: cpp: Update iommu handling + +CPP has to check for stream state before operate iommu +contexts. + +Change-Id: I69e6266e1ff2d1cd93e7191f2c43c887154abae0 +Signed-off-by: Iliya Varadzhakov +--- + drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +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 784e882..96b1641 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 +@@ -2662,7 +2662,8 @@ STREAM_BUFF_END: + break; + } + case VIDIOC_MSM_CPP_IOMMU_DETACH: { +- if (cpp_dev->iommu_state == CPP_IOMMU_STATE_ATTACHED) { ++ if ((cpp_dev->iommu_state == CPP_IOMMU_STATE_ATTACHED) && ++ (cpp_dev->stream_cnt == 0)) { + iommu_detach_device(cpp_dev->domain, + cpp_dev->iommu_ctx); + cpp_dev->iommu_state = CPP_IOMMU_STATE_DETACHED; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8943/0.patch b/Patches/Linux_CVEs/CVE-2015-8943/0.patch new file mode 100644 index 00000000..0121bbc2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8943/0.patch @@ -0,0 +1,62 @@ +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/Linux_CVEs/CVE-2015-8944/0.patch b/Patches/Linux_CVEs/CVE-2015-8944/0.patch new file mode 100644 index 00000000..7bce069e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8944/0.patch @@ -0,0 +1,33 @@ +From e758417e7c31b975c862aa55d0ceef28f3cc9104 Mon Sep 17 00:00:00 2001 +From: Biswajit Paul +Date: Mon, 9 Feb 2015 15:21:12 -0800 +Subject: kernel: Restrict permissions of /proc/iomem. + +The permissions of /proc/iomem currently are -r--r--r--. Everyone can +see its content. As iomem contains information about the physical memory +content of the device, restrict the information only to root. + +Change-Id: If0be35c3fac5274151bea87b738a48e6ec0ae891 +CRs-Fixed: 786116 +Signed-off-by: Biswajit Paul +Signed-off-by: Avijit Kanti Das +--- + kernel/resource.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/resource.c b/kernel/resource.c +index a5a8086..91c35c3 100644 +--- a/kernel/resource.c ++++ b/kernel/resource.c +@@ -153,7 +153,7 @@ static const struct file_operations proc_iomem_operations = { + static int __init ioresources_init(void) + { + proc_create("ioports", 0, NULL, &proc_ioports_operations); +- proc_create("iomem", 0, NULL, &proc_iomem_operations); ++ proc_create("iomem", S_IRUSR, NULL, &proc_iomem_operations); + return 0; + } + __initcall(ioresources_init); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8951/0.patch b/Patches/Linux_CVEs/CVE-2015-8951/0.patch new file mode 100644 index 00000000..910b5c61 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8951/0.patch @@ -0,0 +1,76 @@ +From ccff36b07bfc49efc77b9f1b55ed2bf0900b1d5b Mon Sep 17 00:00:00 2001 +From: Vidyakumar Athota +Date: Wed, 16 Dec 2015 15:42:39 -0800 +Subject: ASoC: msm-lsm-client: free lsm client data in msm_lsm_close + +Currently lsm client data is deallocated when q6lsm_open() fails +which can cause memory corruption if lsm client data is accessed +after freed. Fix this issue by deallocating the client data only +in msm_lsm_close(). + +Change-Id: If048c26a0ffd8a346a28622183cbf2ba1e7e5ff3 +Signed-off-by: Vidyakumar Athota +--- + include/sound/q6lsm.h | 1 + + sound/soc/msm/qdsp6v2/msm-lsm-client.c | 10 +++++++--- + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h +index 6045b7f..d410a9b 100644 +--- a/include/sound/q6lsm.h ++++ b/include/sound/q6lsm.h +@@ -71,6 +71,7 @@ struct lsm_client { + uint16_t connect_to_port; + uint8_t num_confidence_levels; + uint8_t *confidence_levels; ++ bool opened; + bool started; + dma_addr_t lsm_cal_phy_addr; + uint32_t lsm_cal_size; +diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +index f0a164f..2337f91 100644 +--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c ++++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +@@ -747,10 +747,9 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: lsm open failed, %d\n", + __func__, ret); +- q6lsm_client_free(prtd->lsm_client); +- kfree(prtd); + return ret; + } ++ prtd->lsm_client->opened = true; + dev_dbg(rtd->dev, "%s: Session_ID = %d, APP ID = %d\n", + __func__, + prtd->lsm_client->session, +@@ -1697,6 +1696,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) + runtime->private_data = NULL; + return -ENOMEM; + } ++ prtd->lsm_client->opened = false; + return 0; + } + +@@ -1769,7 +1769,10 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) + __func__); + } + +- q6lsm_close(prtd->lsm_client); ++ if (prtd->lsm_client->opened) { ++ q6lsm_close(prtd->lsm_client); ++ prtd->lsm_client->opened = false; ++ } + q6lsm_client_free(prtd->lsm_client); + + spin_lock_irqsave(&prtd->event_lock, flags); +@@ -1777,6 +1780,7 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) + prtd->event_status = NULL; + spin_unlock_irqrestore(&prtd->event_lock, flags); + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8955/0.patch b/Patches/Linux_CVEs/CVE-2015-8955/0.patch new file mode 100644 index 00000000..913d1798 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8955/0.patch @@ -0,0 +1,110 @@ +From e429817b401f095ac483fcb02524b01faf45dad6 Mon Sep 17 00:00:00 2001 +From: "Suzuki K. Poulose" +Date: Tue, 17 Mar 2015 18:14:58 +0000 +Subject: ARM: perf: reject groups spanning multiple hardware PMUs + +The perf core implicitly rejects events spanning multiple HW PMUs, as in +these cases the event->ctx will differ. However this validation is +performed after pmu::event_init() is called in perf_init_event(), and +thus pmu::event_init() may be called with a group leader from a +different HW PMU. + +The ARM PMU driver does not take this fact into account, and when +validating groups assumes that it can call to_arm_pmu(event->pmu) for +any HW event. When the event in question is from another HW PMU this is +wrong, and results in dereferencing garbage. + +This patch updates the ARM PMU driver to first test for and reject +events from other PMUs, moving the to_arm_pmu and related logic after +this test. Fixes a crash triggered by perf_fuzzer on Linux-4.0-rc2, with +a CCI PMU present: + + --- +CPU: 0 PID: 1527 Comm: perf_fuzzer Not tainted 4.0.0-rc2 #57 +Hardware name: ARM-Versatile Express +task: bd8484c0 ti: be676000 task.ti: be676000 +PC is at 0xbf1bbc90 +LR is at validate_event+0x34/0x5c +pc : [] lr : [<80016060>] psr: 00000013 +... +[<80016060>] (validate_event) from [<80016198>] (validate_group+0x28/0x90) +[<80016198>] (validate_group) from [<80016398>] (armpmu_event_init+0x150/0x218) +[<80016398>] (armpmu_event_init) from [<800882e4>] (perf_try_init_event+0x30/0x48) +[<800882e4>] (perf_try_init_event) from [<8008f544>] (perf_init_event+0x5c/0xf4) +[<8008f544>] (perf_init_event) from [<8008f8a8>] (perf_event_alloc+0x2cc/0x35c) +[<8008f8a8>] (perf_event_alloc) from [<8009015c>] (SyS_perf_event_open+0x498/0xa70) +[<8009015c>] (SyS_perf_event_open) from [<8000e420>] (ret_fast_syscall+0x0/0x34) +Code: bf1be000 bf1bb380 802a2664 00000000 (00000002) +---[ end trace 01aff0ff00926a0a ]--- + +Also cleans up the code to use the arm_pmu only when we know that +we are dealing with an arm pmu event. + +Cc: Will Deacon +Acked-by: Mark Rutland +Acked-by: Peter Ziljstra (Intel) +Signed-off-by: Suzuki K. Poulose +Signed-off-by: Will Deacon +--- + arch/arm/kernel/perf_event.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c +index 557e128..4a86a01 100644 +--- a/arch/arm/kernel/perf_event.c ++++ b/arch/arm/kernel/perf_event.c +@@ -259,20 +259,29 @@ out: + } + + static int +-validate_event(struct pmu_hw_events *hw_events, +- struct perf_event *event) ++validate_event(struct pmu *pmu, struct pmu_hw_events *hw_events, ++ struct perf_event *event) + { +- struct arm_pmu *armpmu = to_arm_pmu(event->pmu); ++ struct arm_pmu *armpmu; + + if (is_software_event(event)) + return 1; + ++ /* ++ * Reject groups spanning multiple HW PMUs (e.g. CPU + CCI). The ++ * core perf code won't check that the pmu->ctx == leader->ctx ++ * until after pmu->event_init(event). ++ */ ++ if (event->pmu != pmu) ++ return 0; ++ + if (event->state < PERF_EVENT_STATE_OFF) + return 1; + + if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec) + return 1; + ++ armpmu = to_arm_pmu(event->pmu); + return armpmu->get_event_idx(hw_events, event) >= 0; + } + +@@ -288,15 +297,15 @@ validate_group(struct perf_event *event) + */ + memset(&fake_pmu.used_mask, 0, sizeof(fake_pmu.used_mask)); + +- if (!validate_event(&fake_pmu, leader)) ++ if (!validate_event(event->pmu, &fake_pmu, leader)) + return -EINVAL; + + list_for_each_entry(sibling, &leader->sibling_list, group_entry) { +- if (!validate_event(&fake_pmu, sibling)) ++ if (!validate_event(event->pmu, &fake_pmu, sibling)) + return -EINVAL; + } + +- if (!validate_event(&fake_pmu, event)) ++ if (!validate_event(event->pmu, &fake_pmu, event)) + return -EINVAL; + + return 0; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8961/0.patch b/Patches/Linux_CVEs/CVE-2015-8961/0.patch new file mode 100644 index 00000000..343a8b22 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8961/0.patch @@ -0,0 +1,44 @@ +From 6934da9238da947628be83635e365df41064b09b Mon Sep 17 00:00:00 2001 +From: Lukas Czerner +Date: Sat, 17 Oct 2015 22:57:06 -0400 +Subject: ext4: fix potential use after free in __ext4_journal_stop + +There is a use-after-free possibility in __ext4_journal_stop() in the +case that we free the handle in the first jbd2_journal_stop() because +we're referencing handle->h_err afterwards. This was introduced in +9705acd63b125dee8b15c705216d7186daea4625 and it is wrong. Fix it by +storing the handle->h_err value beforehand and avoid referencing +potentially freed handle. + +Fixes: 9705acd63b125dee8b15c705216d7186daea4625 +Signed-off-by: Lukas Czerner +Reviewed-by: Andreas Dilger +Cc: stable@vger.kernel.org +--- + fs/ext4/ext4_jbd2.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c +index d418431..e770c1ee 100644 +--- a/fs/ext4/ext4_jbd2.c ++++ b/fs/ext4/ext4_jbd2.c +@@ -88,13 +88,13 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) + return 0; + } + ++ err = handle->h_err; + if (!handle->h_transaction) { +- err = jbd2_journal_stop(handle); +- return handle->h_err ? handle->h_err : err; ++ rc = jbd2_journal_stop(handle); ++ return err ? err : rc; + } + + sb = handle->h_transaction->t_journal->j_private; +- err = handle->h_err; + rc = jbd2_journal_stop(handle); + + if (!err) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8962/0.patch b/Patches/Linux_CVEs/CVE-2015-8962/0.patch new file mode 100644 index 00000000..4520a6fb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8962/0.patch @@ -0,0 +1,67 @@ +From f3951a3709ff50990bf3e188c27d346792103432 Mon Sep 17 00:00:00 2001 +From: Calvin Owens +Date: Fri, 30 Oct 2015 16:57:00 -0700 +Subject: [PATCH] sg: Fix double-free when drives detach during SG_IO + +In sg_common_write(), we free the block request and return -ENODEV if +the device is detached in the middle of the SG_IO ioctl(). + +Unfortunately, sg_finish_rem_req() also tries to free srp->rq, so we +end up freeing rq->cmd in the already free rq object, and then free +the object itself out from under the current user. + +This ends up corrupting random memory via the list_head on the rq +object. The most common crash trace I saw is this: + + ------------[ cut here ]------------ + kernel BUG at block/blk-core.c:1420! + Call Trace: + [] blk_put_request+0x5b/0x80 + [] sg_finish_rem_req+0x6b/0x120 [sg] + [] sg_common_write.isra.14+0x459/0x5a0 [sg] + [] ? selinux_file_alloc_security+0x48/0x70 + [] sg_new_write.isra.17+0x195/0x2d0 [sg] + [] sg_ioctl+0x644/0xdb0 [sg] + [] do_vfs_ioctl+0x90/0x520 + [] ? file_has_perm+0x97/0xb0 + [] SyS_ioctl+0x91/0xb0 + [] tracesys+0xdd/0xe2 + RIP [] __blk_put_request+0x154/0x1a0 + +The solution is straightforward: just set srp->rq to NULL in the +failure branch so that sg_finish_rem_req() doesn't attempt to re-free +it. + +Additionally, since sg_rq_end_io() will never be called on the object +when this happens, we need to free memory backing ->cmd if it isn't +embedded in the object itself. + +KASAN was extremely helpful in finding the root cause of this bug. + +Signed-off-by: Calvin Owens +Acked-by: Douglas Gilbert +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/sg.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 9d7b7db75e4b9..503ab8b46c0b4 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -787,8 +787,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, + return k; /* probably out of space --> ENOMEM */ + } + if (atomic_read(&sdp->detaching)) { +- if (srp->bio) ++ if (srp->bio) { ++ if (srp->rq->cmd != srp->rq->__cmd) ++ kfree(srp->rq->cmd); ++ + blk_end_request_all(srp->rq, -EIO); ++ srp->rq = NULL; ++ } ++ + sg_finish_rem_req(srp); + return -ENODEV; + } diff --git a/Patches/Linux_CVEs/CVE-2015-8963/0.patch b/Patches/Linux_CVEs/CVE-2015-8963/0.patch new file mode 100644 index 00000000..3701d036 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8963/0.patch @@ -0,0 +1,96 @@ +From 12ca6ad2e3a896256f086497a7c7406a547ee373 Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra +Date: Tue, 15 Dec 2015 13:49:05 +0100 +Subject: perf: Fix race in swevent hash + +There's a race on CPU unplug where we free the swevent hash array +while it can still have events on. This will result in a +use-after-free which is BAD. + +Simply do not free the hash array on unplug. This leaves the thing +around and no use-after-free takes place. + +When the last swevent dies, we do a for_each_possible_cpu() iteration +anyway to clean these up, at which time we'll free it, so no leakage +will occur. + +Reported-by: Sasha Levin +Tested-by: Sasha Levin +Signed-off-by: Peter Zijlstra (Intel) +Cc: Arnaldo Carvalho de Melo +Cc: Frederic Weisbecker +Cc: Jiri Olsa +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Stephane Eranian +Cc: Thomas Gleixner +Cc: Vince Weaver +Signed-off-by: Ingo Molnar +--- + kernel/events/core.c | 20 +------------------- + 1 file changed, 1 insertion(+), 19 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index fd7de04..0a791a2 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -6488,9 +6488,6 @@ struct swevent_htable { + + /* Recursion avoidance in each contexts */ + int recursion[PERF_NR_CONTEXTS]; +- +- /* Keeps track of cpu being initialized/exited */ +- bool online; + }; + + static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); +@@ -6748,14 +6745,8 @@ static int perf_swevent_add(struct perf_event *event, int flags) + hwc->state = !(flags & PERF_EF_START); + + head = find_swevent_head(swhash, event); +- if (!head) { +- /* +- * We can race with cpu hotplug code. Do not +- * WARN if the cpu just got unplugged. +- */ +- WARN_ON_ONCE(swhash->online); ++ if (WARN_ON_ONCE(!head)) + return -EINVAL; +- } + + hlist_add_head_rcu(&event->hlist_entry, head); + perf_event_update_userpage(event); +@@ -6823,7 +6814,6 @@ static int swevent_hlist_get_cpu(struct perf_event *event, int cpu) + int err = 0; + + mutex_lock(&swhash->hlist_mutex); +- + if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) { + struct swevent_hlist *hlist; + +@@ -9286,7 +9276,6 @@ static void perf_event_init_cpu(int cpu) + struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); + + mutex_lock(&swhash->hlist_mutex); +- swhash->online = true; + if (swhash->hlist_refcount > 0) { + struct swevent_hlist *hlist; + +@@ -9328,14 +9317,7 @@ static void perf_event_exit_cpu_context(int cpu) + + static void perf_event_exit_cpu(int cpu) + { +- struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); +- + perf_event_exit_cpu_context(cpu); +- +- mutex_lock(&swhash->hlist_mutex); +- swhash->online = false; +- swevent_hlist_release(swhash); +- mutex_unlock(&swhash->hlist_mutex); + } + #else + static inline void perf_event_exit_cpu(int cpu) { } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8964/0.patch b/Patches/Linux_CVEs/CVE-2015-8964/0.patch new file mode 100644 index 00000000..3da3aa42 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8964/0.patch @@ -0,0 +1,78 @@ +From dd42bf1197144ede075a9d4793123f7689e164bc Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Fri, 27 Nov 2015 14:30:21 -0500 +Subject: tty: Prevent ldisc drivers from re-using stale tty fields + +Line discipline drivers may mistakenly misuse ldisc-related fields +when initializing. For example, a failure to initialize tty->receive_room +in the N_GIGASET_M101 line discipline was recently found and fixed [1]. +Now, the N_X25 line discipline has been discovered accessing the previous +line discipline's already-freed private data [2]. + +Harden the ldisc interface against misuse by initializing revelant +tty fields before instancing the new line discipline. + +[1] + commit fd98e9419d8d622a4de91f76b306af6aa627aa9c + Author: Tilman Schmidt + Date: Tue Jul 14 00:37:13 2015 +0200 + + isdn/gigaset: reset tty->receive_room when attaching ser_gigaset + +[2] Report from Sasha Levin + [ 634.336761] ================================================================== + [ 634.338226] BUG: KASAN: use-after-free in x25_asy_open_tty+0x13d/0x490 at addr ffff8800a743efd0 + [ 634.339558] Read of size 4 by task syzkaller_execu/8981 + [ 634.340359] ============================================================================= + [ 634.341598] BUG kmalloc-512 (Not tainted): kasan: bad access detected + ... + [ 634.405018] Call Trace: + [ 634.405277] dump_stack (lib/dump_stack.c:52) + [ 634.405775] print_trailer (mm/slub.c:655) + [ 634.406361] object_err (mm/slub.c:662) + [ 634.406824] kasan_report_error (mm/kasan/report.c:138 mm/kasan/report.c:236) + [ 634.409581] __asan_report_load4_noabort (mm/kasan/report.c:279) + [ 634.411355] x25_asy_open_tty (drivers/net/wan/x25_asy.c:559 (discriminator 1)) + [ 634.413997] tty_ldisc_open.isra.2 (drivers/tty/tty_ldisc.c:447) + [ 634.414549] tty_set_ldisc (drivers/tty/tty_ldisc.c:567) + [ 634.415057] tty_ioctl (drivers/tty/tty_io.c:2646 drivers/tty/tty_io.c:2879) + [ 634.423524] do_vfs_ioctl (fs/ioctl.c:43 fs/ioctl.c:607) + [ 634.427491] SyS_ioctl (fs/ioctl.c:622 fs/ioctl.c:613) + [ 634.427945] entry_SYSCALL_64_fastpath (arch/x86/entry/entry_64.S:188) + +Cc: Tilman Schmidt +Cc: Sasha Levin +Signed-off-by: Peter Hurley +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/tty_ldisc.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c +index 9ec1250..a054d03 100644 +--- a/drivers/tty/tty_ldisc.c ++++ b/drivers/tty/tty_ldisc.c +@@ -417,6 +417,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); + * they are not on hot paths so a little discipline won't do + * any harm. + * ++ * The line discipline-related tty_struct fields are reset to ++ * prevent the ldisc driver from re-using stale information for ++ * the new ldisc instance. ++ * + * Locking: takes termios_rwsem + */ + +@@ -425,6 +429,9 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) + down_write(&tty->termios_rwsem); + tty->termios.c_line = num; + up_write(&tty->termios_rwsem); ++ ++ tty->disc_data = NULL; ++ tty->receive_room = 0; + } + + /** +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8964/1.patch b/Patches/Linux_CVEs/CVE-2015-8964/1.patch new file mode 100644 index 00000000..fab720b6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8964/1.patch @@ -0,0 +1,80 @@ +From 1a0220ebac77da3d9e2989528e64e1683c63fb58 Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Fri, 27 Nov 2015 14:30:21 -0500 +Subject: [PATCH] BACKPORT: tty: Prevent ldisc drivers from re-using stale tty + fields + +(cherry picked from commit dd42bf1197144ede075a9d4793123f7689e164bc) + +Line discipline drivers may mistakenly misuse ldisc-related fields +when initializing. For example, a failure to initialize tty->receive_room +in the N_GIGASET_M101 line discipline was recently found and fixed [1]. +Now, the N_X25 line discipline has been discovered accessing the previous +line discipline's already-freed private data [2]. + +Harden the ldisc interface against misuse by initializing revelant +tty fields before instancing the new line discipline. + +[1] + commit fd98e9419d8d622a4de91f76b306af6aa627aa9c + Author: Tilman Schmidt + Date: Tue Jul 14 00:37:13 2015 +0200 + + isdn/gigaset: reset tty->receive_room when attaching ser_gigaset + +[2] Report from Sasha Levin + [ 634.336761] ================================================================== + [ 634.338226] BUG: KASAN: use-after-free in x25_asy_open_tty+0x13d/0x490 at addr ffff8800a743efd0 + [ 634.339558] Read of size 4 by task syzkaller_execu/8981 + [ 634.340359] ============================================================================= + [ 634.341598] BUG kmalloc-512 (Not tainted): kasan: bad access detected + ... + [ 634.405018] Call Trace: + [ 634.405277] dump_stack (lib/dump_stack.c:52) + [ 634.405775] print_trailer (mm/slub.c:655) + [ 634.406361] object_err (mm/slub.c:662) + [ 634.406824] kasan_report_error (mm/kasan/report.c:138 mm/kasan/report.c:236) + [ 634.409581] __asan_report_load4_noabort (mm/kasan/report.c:279) + [ 634.411355] x25_asy_open_tty (drivers/net/wan/x25_asy.c:559 (discriminator 1)) + [ 634.413997] tty_ldisc_open.isra.2 (drivers/tty/tty_ldisc.c:447) + [ 634.414549] tty_set_ldisc (drivers/tty/tty_ldisc.c:567) + [ 634.415057] tty_ioctl (drivers/tty/tty_io.c:2646 drivers/tty/tty_io.c:2879) + [ 634.423524] do_vfs_ioctl (fs/ioctl.c:43 fs/ioctl.c:607) + [ 634.427491] SyS_ioctl (fs/ioctl.c:622 fs/ioctl.c:613) + [ 634.427945] entry_SYSCALL_64_fastpath (arch/x86/entry/entry_64.S:188) + +Cc: Tilman Schmidt +Cc: Sasha Levin +Signed-off-by: Peter Hurley +Signed-off-by: Greg Kroah-Hartman +Change-Id: Ibed6feadfb9706d478f93feec3b240aecfc64af3 +Bug: 30951112 +--- + drivers/tty/tty_ldisc.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c +index b7b8048f12539..420dd6e52a279 100644 +--- a/drivers/tty/tty_ldisc.c ++++ b/drivers/tty/tty_ldisc.c +@@ -415,6 +415,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); + * they are not on hot paths so a little discipline won't do + * any harm. + * ++ * The line discipline-related tty_struct fields are reset to ++ * prevent the ldisc driver from re-using stale information for ++ * the new ldisc instance. ++ * + * Locking: takes termios_mutex + */ + +@@ -423,6 +427,9 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) + mutex_lock(&tty->termios_mutex); + tty->termios.c_line = num; + mutex_unlock(&tty->termios_mutex); ++ ++ tty->disc_data = NULL; ++ tty->receive_room = 0; + } + + /** diff --git a/Patches/Linux_CVEs/CVE-2015-8966/0.patch b/Patches/Linux_CVEs/CVE-2015-8966/0.patch new file mode 100644 index 00000000..6019371a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8966/0.patch @@ -0,0 +1,112 @@ +From 76cc404bfdc0d419c720de4daaf2584542734f42 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Mon, 28 Dec 2015 20:47:08 -0500 +Subject: [PATCH] arm: fix handling of F_OFD_... in oabi_fcntl64() + +Cc: stable@vger.kernel.org # 3.15+ +Reviewed-by: Jeff Layton +Signed-off-by: Al Viro +--- + arch/arm/kernel/sys_oabi-compat.c | 73 ++++++++++++++++++++------------------- + 1 file changed, 37 insertions(+), 36 deletions(-) + +diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c +index b83f3b7..087acb5 100644 +--- a/arch/arm/kernel/sys_oabi-compat.c ++++ b/arch/arm/kernel/sys_oabi-compat.c +@@ -193,15 +193,44 @@ struct oabi_flock64 { + pid_t l_pid; + } __attribute__ ((packed,aligned(4))); + +-asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, ++static long do_locks(unsigned int fd, unsigned int cmd, + unsigned long arg) + { +- struct oabi_flock64 user; + struct flock64 kernel; +- mm_segment_t fs = USER_DS; /* initialized to kill a warning */ +- unsigned long local_arg = arg; +- int ret; ++ struct oabi_flock64 user; ++ mm_segment_t fs; ++ long ret; ++ ++ if (copy_from_user(&user, (struct oabi_flock64 __user *)arg, ++ sizeof(user))) ++ return -EFAULT; ++ kernel.l_type = user.l_type; ++ kernel.l_whence = user.l_whence; ++ kernel.l_start = user.l_start; ++ kernel.l_len = user.l_len; ++ kernel.l_pid = user.l_pid; ++ ++ fs = get_fs(); ++ set_fs(KERNEL_DS); ++ ret = sys_fcntl64(fd, cmd, (unsigned long)&kernel); ++ set_fs(fs); ++ ++ if (!ret && (cmd == F_GETLK64 || cmd == F_OFD_GETLK)) { ++ user.l_type = kernel.l_type; ++ user.l_whence = kernel.l_whence; ++ user.l_start = kernel.l_start; ++ user.l_len = kernel.l_len; ++ user.l_pid = kernel.l_pid; ++ if (copy_to_user((struct oabi_flock64 __user *)arg, ++ &user, sizeof(user))) ++ ret = -EFAULT; ++ } ++ return ret; ++} + ++asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, ++ unsigned long arg) ++{ + switch (cmd) { + case F_OFD_GETLK: + case F_OFD_SETLK: +@@ -209,39 +238,11 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, + case F_GETLK64: + case F_SETLK64: + case F_SETLKW64: +- if (copy_from_user(&user, (struct oabi_flock64 __user *)arg, +- sizeof(user))) +- return -EFAULT; +- kernel.l_type = user.l_type; +- kernel.l_whence = user.l_whence; +- kernel.l_start = user.l_start; +- kernel.l_len = user.l_len; +- kernel.l_pid = user.l_pid; +- local_arg = (unsigned long)&kernel; +- fs = get_fs(); +- set_fs(KERNEL_DS); +- } +- +- ret = sys_fcntl64(fd, cmd, local_arg); ++ return do_locks(fd, cmd, arg); + +- switch (cmd) { +- case F_GETLK64: +- if (!ret) { +- user.l_type = kernel.l_type; +- user.l_whence = kernel.l_whence; +- user.l_start = kernel.l_start; +- user.l_len = kernel.l_len; +- user.l_pid = kernel.l_pid; +- if (copy_to_user((struct oabi_flock64 __user *)arg, +- &user, sizeof(user))) +- ret = -EFAULT; +- } +- case F_SETLK64: +- case F_SETLKW64: +- set_fs(fs); ++ default: ++ return sys_fcntl64(fd, cmd, arg); + } +- +- return ret; + } + + struct oabi_epoll_event { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-8967/0.patch b/Patches/Linux_CVEs/CVE-2015-8967/0.patch new file mode 100644 index 00000000..d87953ea --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-8967/0.patch @@ -0,0 +1,34 @@ +From c623b33b4e9599c6ac5076f7db7369eb9869aa04 Mon Sep 17 00:00:00 2001 +From: Mark Rutland +Date: Thu, 8 Jan 2015 11:42:59 +0000 +Subject: arm64: make sys_call_table const + +As with x86, mark the sys_call_table const such that it will be placed +in the .rodata section. This will cause attempts to modify the table +(accidental or deliberate) to fail when strict page permissions are in +place. In the absence of strict page permissions, there should be no +functional change. + +Signed-off-by: Mark Rutland +Acked-by: Will Deacon +Signed-off-by: Catalin Marinas +--- + arch/arm64/kernel/sys.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c +index dec351a..75151aa 100644 +--- a/arch/arm64/kernel/sys.c ++++ b/arch/arm64/kernel/sys.c +@@ -49,7 +49,7 @@ asmlinkage long sys_rt_sigreturn_wrapper(void); + * The sys_call_table array must be 4K aligned to be accessible from + * kernel/entry.S. + */ +-void *sys_call_table[__NR_syscalls] __aligned(4096) = { ++void * const sys_call_table[__NR_syscalls] __aligned(4096) = { + [0 ... __NR_syscalls - 1] = sys_ni_syscall, + #include + }; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2015-9004/0.patch b/Patches/Linux_CVEs/CVE-2015-9004/0.patch new file mode 100644 index 00000000..bbc24aca --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2015-9004/0.patch @@ -0,0 +1,91 @@ +From c3c87e770458aa004bd7ed3f29945ff436fd6511 Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra +Date: Fri, 23 Jan 2015 11:19:48 +0100 +Subject: perf: Tighten (and fix) the grouping condition + +The fix from 9fc81d87420d ("perf: Fix events installation during +moving group") was incomplete in that it failed to recognise that +creating a group with events for different CPUs is semantically +broken -- they cannot be co-scheduled. + +Furthermore, it leads to real breakage where, when we create an event +for CPU Y and then migrate it to form a group on CPU X, the code gets +confused where the counter is programmed -- triggered in practice +as well by me via the perf fuzzer. + +Fix this by tightening the rules for creating groups. Only allow +grouping of counters that can be co-scheduled in the same context. +This means for the same task and/or the same cpu. + +Fixes: 9fc81d87420d ("perf: Fix events installation during moving group") +Signed-off-by: Peter Zijlstra (Intel) +Cc: Arnaldo Carvalho de Melo +Cc: Jiri Olsa +Cc: Linus Torvalds +Link: http://lkml.kernel.org/r/20150123125834.090683288@infradead.org +Signed-off-by: Ingo Molnar +--- + include/linux/perf_event.h | 6 ------ + kernel/events/core.c | 15 +++++++++++++-- + 2 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 4f7a61c..664de5a 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -450,11 +450,6 @@ struct perf_event { + #endif /* CONFIG_PERF_EVENTS */ + }; + +-enum perf_event_context_type { +- task_context, +- cpu_context, +-}; +- + /** + * struct perf_event_context - event context structure + * +@@ -462,7 +457,6 @@ enum perf_event_context_type { + */ + struct perf_event_context { + struct pmu *pmu; +- enum perf_event_context_type type; + /* + * Protect the states of the events in the list, + * nr_active, and the list: +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 882f835a..19efcf1 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -6776,7 +6776,6 @@ skip_type: + __perf_event_init_context(&cpuctx->ctx); + lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex); + lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock); +- cpuctx->ctx.type = cpu_context; + cpuctx->ctx.pmu = pmu; + + __perf_cpu_hrtimer_init(cpuctx, cpu); +@@ -7420,7 +7419,19 @@ SYSCALL_DEFINE5(perf_event_open, + * task or CPU context: + */ + if (move_group) { +- if (group_leader->ctx->type != ctx->type) ++ /* ++ * Make sure we're both on the same task, or both ++ * per-cpu events. ++ */ ++ if (group_leader->ctx->task != ctx->task) ++ goto err_context; ++ ++ /* ++ * Make sure we're both events for the same CPU; ++ * grouping events for different CPUs is broken; since ++ * you can never concurrently schedule them anyhow. ++ */ ++ if (group_leader->cpu != event->cpu) + goto err_context; + } else { + if (group_leader->ctx != ctx) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-0723/0.patch b/Patches/Linux_CVEs/CVE-2016-0723/0.patch new file mode 100644 index 00000000..6061ad90 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0723/0.patch @@ -0,0 +1,69 @@ +From 5c17c861a357e9458001f021a7afa7aab9937439 Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Sun, 10 Jan 2016 22:40:55 -0800 +Subject: tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) + +ioctl(TIOCGETD) retrieves the line discipline id directly from the +ldisc because the line discipline id (c_line) in termios is untrustworthy; +userspace may have set termios via ioctl(TCSETS*) without actually +changing the line discipline via ioctl(TIOCSETD). + +However, directly accessing the current ldisc via tty->ldisc is +unsafe; the ldisc ptr dereferenced may be stale if the line discipline +is changing via ioctl(TIOCSETD) or hangup. + +Wait for the line discipline reference (just like read() or write()) +to retrieve the "current" line discipline id. + +Cc: +Signed-off-by: Peter Hurley +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/tty_io.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index a1b36bf..5cec01c 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -2659,6 +2659,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) + } + + /** ++ * tiocgetd - get line discipline ++ * @tty: tty device ++ * @p: pointer to user data ++ * ++ * Retrieves the line discipline id directly from the ldisc. ++ * ++ * Locking: waits for ldisc reference (in case the line discipline ++ * is changing or the tty is being hungup) ++ */ ++ ++static int tiocgetd(struct tty_struct *tty, int __user *p) ++{ ++ struct tty_ldisc *ld; ++ int ret; ++ ++ ld = tty_ldisc_ref_wait(tty); ++ ret = put_user(ld->ops->num, p); ++ tty_ldisc_deref(ld); ++ return ret; ++} ++ ++/** + * send_break - performed time break + * @tty: device to break on + * @duration: timeout in mS +@@ -2884,7 +2906,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case TIOCGSID: + return tiocgsid(tty, real_tty, p); + case TIOCGETD: +- return put_user(tty->ldisc->ops->num, (int __user *)p); ++ return tiocgetd(tty, p); + case TIOCSETD: + return tiocsetd(tty, p); + case TIOCVHANGUP: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-0728/0.patch b/Patches/Linux_CVEs/CVE-2016-0728/0.patch new file mode 100644 index 00000000..d402663a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0728/0.patch @@ -0,0 +1,81 @@ +From 23567fd052a9abb6d67fe8e7a9ccdd9800a540f2 Mon Sep 17 00:00:00 2001 +From: Yevgeny Pats +Date: Tue, 19 Jan 2016 22:09:04 +0000 +Subject: KEYS: Fix keyring ref leak in join_session_keyring() + +This fixes CVE-2016-0728. + +If a thread is asked to join as a session keyring the keyring that's already +set as its session, we leak a keyring reference. + +This can be tested with the following program: + + #include + #include + #include + #include + + int main(int argc, const char *argv[]) + { + int i = 0; + key_serial_t serial; + + serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, + "leaked-keyring"); + if (serial < 0) { + perror("keyctl"); + return -1; + } + + if (keyctl(KEYCTL_SETPERM, serial, + KEY_POS_ALL | KEY_USR_ALL) < 0) { + perror("keyctl"); + return -1; + } + + for (i = 0; i < 100; i++) { + serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, + "leaked-keyring"); + if (serial < 0) { + perror("keyctl"); + return -1; + } + } + + return 0; + } + +If, after the program has run, there something like the following line in +/proc/keys: + +3f3d898f I--Q--- 100 perm 3f3f0000 0 0 keyring leaked-keyring: empty + +with a usage count of 100 * the number of times the program has been run, +then the kernel is malfunctioning. If leaked-keyring has zero usages or +has been garbage collected, then the problem is fixed. + +Reported-by: Yevgeny Pats +Signed-off-by: David Howells +Acked-by: Don Zickus +Acked-by: Prarit Bhargava +Acked-by: Jarod Wilson +Signed-off-by: James Morris +--- + security/keys/process_keys.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c +index a3f85d2..e6d50172 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -794,6 +794,7 @@ long join_session_keyring(const char *name) + ret = PTR_ERR(keyring); + goto error2; + } else if (keyring == new->session_keyring) { ++ key_put(keyring); + ret = 0; + goto error2; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-0758/0.patch b/Patches/Linux_CVEs/CVE-2016-0758/0.patch new file mode 100644 index 00000000..1c8b2139 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0758/0.patch @@ -0,0 +1,88 @@ +From 23c8a812dc3c621009e4f0e5342aa4e2ede1ceaa Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 23 Feb 2016 11:03:12 +0000 +Subject: [PATCH] KEYS: Fix ASN.1 indefinite length object parsing + +This fixes CVE-2016-0758. + +In the ASN.1 decoder, when the length field of an ASN.1 value is extracted, +it isn't validated against the remaining amount of data before being added +to the cursor. With a sufficiently large size indicated, the check: + + datalen - dp < 2 + +may then fail due to integer overflow. + +Fix this by checking the length indicated against the amount of remaining +data in both places a definite length is determined. + +Whilst we're at it, make the following changes: + + (1) Check the maximum size of extended length does not exceed the capacity + of the variable it's being stored in (len) rather than the type that + variable is assumed to be (size_t). + + (2) Compare the EOC tag to the symbolic constant ASN1_EOC rather than the + integer 0. + + (3) To reduce confusion, move the initialisation of len outside of: + + for (len = 0; n > 0; n--) { + + since it doesn't have anything to do with the loop counter n. + +Signed-off-by: David Howells +Reviewed-by: Mimi Zohar +Acked-by: David Woodhouse +Acked-by: Peter Jones +--- + lib/asn1_decoder.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c +index 2b3f46c049d45..554522934c442 100644 +--- a/lib/asn1_decoder.c ++++ b/lib/asn1_decoder.c +@@ -74,7 +74,7 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen + + /* Extract a tag from the data */ + tag = data[dp++]; +- if (tag == 0) { ++ if (tag == ASN1_EOC) { + /* It appears to be an EOC. */ + if (data[dp++] != 0) + goto invalid_eoc; +@@ -96,10 +96,8 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen + + /* Extract the length */ + len = data[dp++]; +- if (len <= 0x7f) { +- dp += len; +- goto next_tag; +- } ++ if (len <= 0x7f) ++ goto check_length; + + if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { + /* Indefinite length */ +@@ -110,14 +108,18 @@ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen + } + + n = len - 0x80; +- if (unlikely(n > sizeof(size_t) - 1)) ++ if (unlikely(n > sizeof(len) - 1)) + goto length_too_long; + if (unlikely(n > datalen - dp)) + goto data_overrun_error; +- for (len = 0; n > 0; n--) { ++ len = 0; ++ for (; n > 0; n--) { + len <<= 8; + len |= data[dp++]; + } ++check_length: ++ if (len > datalen - dp) ++ goto data_overrun_error; + dp += len; + goto next_tag; + diff --git a/Patches/Linux_CVEs/CVE-2016-0774/0.patch b/Patches/Linux_CVEs/CVE-2016-0774/0.patch new file mode 100644 index 00000000..b77c1a66 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0774/0.patch @@ -0,0 +1,63 @@ +From b381fbc509052d07ccf8641fd7560a25d46aaf1e Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sat, 13 Feb 2016 02:34:52 +0000 +Subject: pipe: Fix buffer offset after partially failed read + +Quoting the RHEL advisory: + +> It was found that the fix for CVE-2015-1805 incorrectly kept buffer +> offset and buffer length in sync on a failed atomic read, potentially +> resulting in a pipe buffer state corruption. A local, unprivileged user +> could use this flaw to crash the system or leak kernel memory to user +> space. (CVE-2016-0774, Moderate) + +The same flawed fix was applied to stable branches from 2.6.32.y to +3.14.y inclusive, and I was able to reproduce the issue on 3.2.y. +We need to give pipe_iov_copy_to_user() a separate offset variable +and only update the buffer offset if it succeeds. + +References: https://rhn.redhat.com/errata/RHSA-2016-0103.html +Signed-off-by: Ben Hutchings +Cc: Jeffrey Vander Stoep +Signed-off-by: Zefan Li +--- + fs/pipe.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +(limited to 'fs/pipe.c') + +diff --git a/fs/pipe.c b/fs/pipe.c +index abfb935..6049235 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -390,6 +390,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + void *addr; + size_t chars = buf->len, remaining; + int error, atomic; ++ int offset; + + if (chars > total_len) + chars = total_len; +@@ -403,9 +404,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + + atomic = !iov_fault_in_pages_write(iov, chars); + remaining = chars; ++ offset = buf->offset; + redo: + addr = ops->map(pipe, buf, atomic); +- error = pipe_iov_copy_to_user(iov, addr, &buf->offset, ++ error = pipe_iov_copy_to_user(iov, addr, &offset, + &remaining, atomic); + ops->unmap(pipe, buf, addr); + if (unlikely(error)) { +@@ -421,6 +423,7 @@ redo: + break; + } + ret += chars; ++ buf->offset += chars; + buf->len -= chars; + + /* Was it a packet buffer? Clean up and exit */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-0774/1.patch b/Patches/Linux_CVEs/CVE-2016-0774/1.patch new file mode 100644 index 00000000..f873145e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0774/1.patch @@ -0,0 +1,60 @@ +From 4bb62b96dc3d2ef4943d3b78b9db160f545a631f Mon Sep 17 00:00:00 2001 +From: Jeff Vander Stoep +Date: Wed, 23 Mar 2016 15:32:14 -0700 +Subject: [PATCH] pipe: iovec: Fix OOB read in pipe_read() + +Previous upstream *stable* fix 14f81062 was incomplete. + +A local process can trigger a system crash with an OOB read on buf. +This occurs when the state of buf gets out of sync. After an error in +pipe_iov_copy_to_user() read_pipe may exit having updated buf->offset +but not buf->len. Upon retrying pipe_read() while in +pipe_iov_copy_to_user() *remaining will be larger than the space left +after buf->offset e.g. *remaing = PAGE_SIZE, buf->len = PAGE_SIZE, +buf->offset = 0x300. + +This is fixed by not updating the state of buf->offset until after the +full copy is completed, similar to how pipe_write() is implemented. + +For stable kernels < 3.16. + +Bug: 27721803 +Change-Id: Iefffbcc6cfd159dba69c31bcd98c6d5c1f21ff2e +Signed-off-by: Jeff Vander Stoep +--- + fs/pipe.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/pipe.c b/fs/pipe.c +index 3e7ab278bb0c0..14b58f9f26f2e 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -400,7 +400,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + const struct pipe_buf_operations *ops = buf->ops; + void *addr; + size_t chars = buf->len, remaining; +- int error, atomic; ++ int error, atomic, offset; + + if (chars > total_len) + chars = total_len; +@@ -414,9 +414,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + + atomic = !iov_fault_in_pages_write(iov, chars); + remaining = chars; ++ offset = buf->offset; + redo: + addr = ops->map(pipe, buf, atomic); +- error = pipe_iov_copy_to_user(iov, addr, &buf->offset, ++ error = pipe_iov_copy_to_user(iov, addr, &offset, + &remaining, atomic); + ops->unmap(pipe, buf, addr); + if (unlikely(error)) { +@@ -432,6 +433,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, + break; + } + ret += chars; ++ buf->offset += chars; + buf->len -= chars; + + /* Was it a packet buffer? Clean up and exit */ diff --git a/Patches/Linux_CVEs/CVE-2016-0805/0.patch b/Patches/Linux_CVEs/CVE-2016-0805/0.patch new file mode 100644 index 00000000..7bcaa942 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0805/0.patch @@ -0,0 +1,58 @@ +From b3f0b1f694258b3b3debc5256eec94bb2a9eb454 Mon Sep 17 00:00:00 2001 +From: Swetha Chikkaboraiah +Date: Wed, 27 Jan 2016 11:46:54 +0530 +Subject: [PATCH] msm: perf: Protect buffer overflow due to malicious user + +In function krait_pmu_disable_event, parameter hwc comes from +userspace and is untrusted.The function krait_clearpmu is called +after the function get_krait_evtinfo. +Function get_krait_evtinfo as parameter krait_evt_type variable +which is used to extract the groupcode(reg) which is bound to + KRAIT_MAX_L1_REG (is 3). After validation,one code path modifies +groupcode(reg):If this code path executes, groupcode(reg) can be +3,4, 5, or 6. In krait_clearpmu groupcode used to access array +krait_functions whose size is 3. Since groupcode can be 3,4,5,6 +accessing array krait_functions lead to bufferoverlflow. +This change will validate groupcode not to exceed 3. + +CVE-2016-0805 Bug:ANDROID-25773204 + +Change-Id: I48c92adda137d8a074b4e1a367a468195a810ca1 +CRs-fixed: 962450 +Signed-off-by: Swetha Chikkaboraiah +Signed-off-by: Karthik Jadala +--- + arch/arm/kernel/perf_event_msm_krait.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c +index 49aae5a66b650..34f9b4e5b099d 100644 +--- a/arch/arm/kernel/perf_event_msm_krait.c ++++ b/arch/arm/kernel/perf_event_msm_krait.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2011-2014, 2016 The 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 +@@ -208,9 +208,6 @@ static unsigned int get_krait_evtinfo(unsigned int krait_evt_type, + code = (krait_evt_type & 0x00FF0) >> 4; + group = krait_evt_type & 0x0000F; + +- if ((group > 3) || (reg > KRAIT_MAX_L1_REG)) +- return -EINVAL; +- + if (prefix != KRAIT_EVT_PREFIX && prefix != KRAIT_VENUMEVT_PREFIX) + return -EINVAL; + +@@ -221,6 +218,9 @@ static unsigned int get_krait_evtinfo(unsigned int krait_evt_type, + reg += VENUM_BASE_OFFSET; + } + ++ if ((group > 3) || (reg > KRAIT_MAX_L1_REG)) ++ return -EINVAL; ++ + evtinfo->group_setval = 0x80000000 | (code << (group * 8)); + evtinfo->groupcode = reg; + evtinfo->armv7_evt_type = evt_type_base[reg] | group; diff --git a/Patches/Linux_CVEs/CVE-2016-0806/0.patch b/Patches/Linux_CVEs/CVE-2016-0806/0.patch new file mode 100644 index 00000000..78d88c1a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0806/0.patch @@ -0,0 +1,6574 @@ + + + +kernel/msm-3.10 - Unnamed repository + + + + + + + + + +
+ + + + +
+summaryrefslogtreecommitdiffstats
+ + + +
+
+
+ + + + + + + + + + + + + + + + +
AgeCommit message (Expand)AuthorFilesLines
2015-11-02wlan:Check priviledge permission for SET_CHANNEL_RANGEAmarnath Hullur Subramanyam1-0/+7
2015-10-29wlan:Check priviledge permission for SET_CHANNEL_RANGEAmarnath Hullur Subramanyam1-0/+7
2015-10-29wlan: ensure permission for WLAN_FTM_PRIV_SET_CHAR_GET_NONEAmarnath Hullur Subramanyam1-0/+7
2015-10-29wlan:Check priviledge permission for SET_VAR_INTS_GETNONE IOCTLAmarnath Hullur Subramanyam1-0/+5
2015-10-29wlan:Check priviledge permission for SET_THREE_INT_GET_NONEAmarnath Hullur Subramanyam1-0/+6
2015-10-29wlan:Check priviledge permission for CLEAR_MCBC_FILTER IOCTLAmarnath Hullur Subramanyam1-0/+6
2015-10-29wlan:Check priviledge permission for SET_POWER_PARAMS IOCTLAmarnath Hullur Subramanyam1-0/+6
2015-10-29wlan:Check priviledge permission for SET_BAND_CONFIG IOCTLAmarnath Hullur Subramanyam1-0/+6
2015-10-29wlan:Check priviledge permission for QCSAP_IOCTL_DISASSOC_STAAmarnath Hullur Subramanyam1-0/+7
2015-10-29wlan:Check priviledge permission for QCSAP_IOCTL_SETWPSIEAmarnath Hullur Subramanyam1-0/+6
2015-10-29wlan:Check priviledge permission before processing SET_PACKET_FILTER IOCTLAmarnath Hullur Subramanyam1-0/+6
2015-10-29wlan:Check priviledge permission before processing SET_CHAR_GET_NONE IOCTLAmarnath Hullur Subramanyam1-0/+6
2015-10-29wlan:Check priviledge permission before processing SET_OEM_DATA_REQ IOCTLAmarnath Hullur Subramanyam1-0/+6
2015-10-29qcacld 2.0: Validate ioctls for valid input lengthAmarnath Hullur Subramanyam1-14/+48
2015-10-29qcacld 2.0: Address buffer overflow due to invalid lengthAmarnath Hullur Subramanyam1-0/+3
2015-10-28qcacld 2.0: Validate WPA and RSN IE for valid lengthAmarnath Hullur Subramanyam1-10/+27
    + +
    + + diff --git a/Patches/Linux_CVEs/CVE-2016-0806/1.patch b/Patches/Linux_CVEs/CVE-2016-0806/1.patch new file mode 100644 index 00000000..c8f7f96d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0806/1.patch @@ -0,0 +1,6570 @@ + + + +kernel/msm-3.10 - Unnamed repository + + + + + + + + + +
    + + + + +
    +summaryrefslogtreecommitdiffstats
    + + + +
    +
    +
    + + + + + + + + + + + + +
    AgeCommit message (Expand)AuthorFilesLines
    2016-04-13qcacld 2.0: Validate ioctls for valid input lengthMahesh A Saptasagar1-11/+49
    2016-03-23qcacld 2.0: Validate WPA and RSN IE for valid lengthMahesh A Saptasagar1-8/+31
    2016-03-23wlan:Check priviledge permissionMukul Sharma1-0/+7
    2016-03-23wlan:Check priviledge permissionMukul Sharma1-0/+7
    2016-03-23wlan:Check priviledge permissionMukul Sharma1-0/+7
    2016-03-23wlan:Check priviledge permissionHanumantha Reddy Pothula1-0/+7
    2016-03-23wlan:Check priviledge permissionMukul Sharma1-1/+8
    2016-03-23wlan:Check priviledge permissionMukul Sharma1-0/+7
    2016-03-23wlan:Check priviledge permissionMukul Sharma1-0/+7
    2016-03-23wlan:Check priviledge permission before processingMukul Sharma1-0/+7
    2016-03-23wlan:Check priviledge permission before processingMukul Sharma1-0/+7
    2016-03-23wlan:Check priviledge permission before processingMukul Sharma1-0/+6
      + +
      + + diff --git a/Patches/Linux_CVEs/CVE-2016-0819/0.patch b/Patches/Linux_CVEs/CVE-2016-0819/0.patch new file mode 100644 index 00000000..63017fa5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0819/0.patch @@ -0,0 +1,35 @@ +From e32c1b1a3d368afe1b09e81b3087ab8810282e93 Mon Sep 17 00:00:00 2001 +From: Srinivasarao P +Date: Tue, 1 Mar 2016 12:16:03 +0530 +Subject: perf: duplicate deletion of perf event + +a malicious app can open a perf event with constraint_duplicate +bit set, disable the event, and close the fd. On closing the fd, +the perf_release() modification causes the kernel to clean up +the event as if it still were enabled, leading to the event +being removed from a list twice. + +CRs-Fixed: 977563 +Change-Id: I5fbec3722407d2f3d0ff0d9f7097c5889e31fd62 +Signed-off-by: Srinivasarao P +--- + kernel/events/core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 7dd822b..868300d 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -6243,6 +6243,9 @@ SYSCALL_DEFINE5(perf_event_open, + if (err) + return err; + ++ if (attr.constraint_duplicate || attr.__reserved_1) ++ return -EINVAL; ++ + if (!attr.exclude_kernel) { + if (perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) + return -EACCES; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-0821/0.patch b/Patches/Linux_CVEs/CVE-2016-0821/0.patch new file mode 100644 index 00000000..3a985b3a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0821/0.patch @@ -0,0 +1,48 @@ +From 8a5e5e02fc83aaf67053ab53b359af08c6c49aaf Mon Sep 17 00:00:00 2001 +From: Vasily Kulikov +Date: Wed, 9 Sep 2015 15:36:00 -0700 +Subject: include/linux/poison.h: fix LIST_POISON{1,2} offset + +Poison pointer values should be small enough to find a room in +non-mmap'able/hardly-mmap'able space. E.g. on x86 "poison pointer space" +is located starting from 0x0. Given unprivileged users cannot mmap +anything below mmap_min_addr, it should be safe to use poison pointers +lower than mmap_min_addr. + +The current poison pointer values of LIST_POISON{1,2} might be too big for +mmap_min_addr values equal or less than 1 MB (common case, e.g. Ubuntu +uses only 0x10000). There is little point to use such a big value given +the "poison pointer space" below 1 MB is not yet exhausted. Changing it +to a smaller value solves the problem for small mmap_min_addr setups. + +The values are suggested by Solar Designer: +http://www.openwall.com/lists/oss-security/2015/05/02/6 + +Signed-off-by: Vasily Kulikov +Cc: Solar Designer +Cc: Thomas Gleixner +Cc: "Kirill A. Shutemov" +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + include/linux/poison.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/poison.h b/include/linux/poison.h +index 2110a81..253c9b4 100644 +--- a/include/linux/poison.h ++++ b/include/linux/poison.h +@@ -19,8 +19,8 @@ + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +-#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA) +-#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA) ++#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) ++#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) + + /********** include/linux/timer.h **********/ + /* +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-0823/0.patch b/Patches/Linux_CVEs/CVE-2016-0823/0.patch new file mode 100644 index 00000000..f01f6922 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-0823/0.patch @@ -0,0 +1,45 @@ +From ab676b7d6fbf4b294bf198fb27ade5b0e865c7ce Mon Sep 17 00:00:00 2001 +From: "Kirill A. Shutemov" +Date: Mon, 9 Mar 2015 23:11:12 +0200 +Subject: pagemap: do not leak physical addresses to non-privileged userspace + +As pointed by recent post[1] on exploiting DRAM physical imperfection, +/proc/PID/pagemap exposes sensitive information which can be used to do +attacks. + +This disallows anybody without CAP_SYS_ADMIN to read the pagemap. + +[1] http://googleprojectzero.blogspot.com/2015/03/exploiting-dram-rowhammer-bug-to-gain.html + +[ Eventually we might want to do anything more finegrained, but for now + this is the simple model. - Linus ] + +Signed-off-by: Kirill A. Shutemov +Acked-by: Konstantin Khlebnikov +Acked-by: Andy Lutomirski +Cc: Pavel Emelyanov +Cc: Andrew Morton +Cc: Mark Seaborn +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +--- + fs/proc/task_mmu.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 956b75d..6dee68d 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -1325,6 +1325,9 @@ out: + + static int pagemap_open(struct inode *inode, struct file *file) + { ++ /* do not disclose physical addresses: attack vector */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; + pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about " + "to stop being page-shift some time soon. See the " + "linux/Documentation/vm/pagemap.txt for details.\n"); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10044/0.patch b/Patches/Linux_CVEs/CVE-2016-10044/0.patch new file mode 100644 index 00000000..ef0ce520 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10044/0.patch @@ -0,0 +1,66 @@ +From 22f6b4d34fcf039c63a94e7670e0da24f8575a5a Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Fri, 16 Sep 2016 00:31:22 +0200 +Subject: aio: mark AIO pseudo-fs noexec + +This ensures that do_mmap() won't implicitly make AIO memory mappings +executable if the READ_IMPLIES_EXEC personality flag is set. Such +behavior is problematic because the security_mmap_file LSM hook doesn't +catch this case, potentially permitting an attacker to bypass a W^X +policy enforced by SELinux. + +I have tested the patch on my machine. + +To test the behavior, compile and run this: + + #define _GNU_SOURCE + #include + #include + #include + #include + #include + #include + #include + + int main(void) { + personality(READ_IMPLIES_EXEC); + aio_context_t ctx = 0; + if (syscall(__NR_io_setup, 1, &ctx)) + err(1, "io_setup"); + + char cmd[1000]; + sprintf(cmd, "cat /proc/%d/maps | grep -F '/[aio]'", + (int)getpid()); + system(cmd); + return 0; + } + +In the output, "rw-s" is good, "rwxs" is bad. + +Signed-off-by: Jann Horn +Signed-off-by: Linus Torvalds +--- + fs/aio.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/fs/aio.c b/fs/aio.c +index fb8e45b..4fe81d1 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -239,7 +239,12 @@ static struct dentry *aio_mount(struct file_system_type *fs_type, + static const struct dentry_operations ops = { + .d_dname = simple_dname, + }; +- return mount_pseudo(fs_type, "aio:", NULL, &ops, AIO_RING_MAGIC); ++ struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, &ops, ++ AIO_RING_MAGIC); ++ ++ if (!IS_ERR(root)) ++ root->d_sb->s_iflags |= SB_I_NOEXEC; ++ return root; + } + + /* aio_setup +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10088/0.patch b/Patches/Linux_CVEs/CVE-2016-10088/0.patch new file mode 100644 index 00000000..695b415d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10088/0.patch @@ -0,0 +1,48 @@ +From 128394eff343fc6d2f32172f03e24829539c5835 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 16 Dec 2016 13:42:06 -0500 +Subject: sg_write()/bsg_write() is not fit to be called under KERNEL_DS + +Both damn things interpret userland pointers embedded into the payload; +worse, they are actually traversing those. Leaving aside the bad +API design, this is very much _not_ safe to call with KERNEL_DS. +Bail out early if that happens. + +Cc: stable@vger.kernel.org +Signed-off-by: Al Viro +--- + block/bsg.c | 3 +++ + drivers/scsi/sg.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/block/bsg.c b/block/bsg.c +index 8a05a40..a57046d 100644 +--- a/block/bsg.c ++++ b/block/bsg.c +@@ -655,6 +655,9 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) + + dprintk("%s: write %Zd bytes\n", bd->name, count); + ++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) ++ return -EINVAL; ++ + bsg_set_block(bd, file); + + bytes_written = 0; +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 070332e..dbe5b4b 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -581,6 +581,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) + sg_io_hdr_t *hp; + unsigned char cmnd[SG_MAX_CDB_SIZE]; + ++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) ++ return -EINVAL; ++ + if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) + return -ENXIO; + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10153/0.patch b/Patches/Linux_CVEs/CVE-2016-10153/0.patch new file mode 100644 index 00000000..ee3c5296 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10153/0.patch @@ -0,0 +1,144 @@ +From a45f795c65b479b4ba107b6ccde29b896d51ee98 Mon Sep 17 00:00:00 2001 +From: Ilya Dryomov +Date: Fri, 2 Dec 2016 16:35:07 +0100 +Subject: libceph: introduce ceph_crypt() for in-place en/decryption + +Starting with 4.9, kernel stacks may be vmalloced and therefore not +guaranteed to be physically contiguous; the new CONFIG_VMAP_STACK +option is enabled by default on x86. This makes it invalid to use +on-stack buffers with the crypto scatterlist API, as sg_set_buf() +expects a logical address and won't work with vmalloced addresses. + +There isn't a different (e.g. kvec-based) crypto API we could switch +net/ceph/crypto.c to and the current scatterlist.h API isn't getting +updated to accommodate this use case. Allocating a new header and +padding for each operation is a non-starter, so do the en/decryption +in-place on a single pre-assembled (header + data + padding) heap +buffer. This is explicitly supported by the crypto API: + + "... the caller may provide the same scatter/gather list for the + plaintext and cipher text. After the completion of the cipher + operation, the plaintext data is replaced with the ciphertext data + in case of an encryption and vice versa for a decryption." + +Signed-off-by: Ilya Dryomov +Reviewed-by: Sage Weil +--- + net/ceph/crypto.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + net/ceph/crypto.h | 2 ++ + 2 files changed, 89 insertions(+) + +diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c +index db2847a..32099c5 100644 +--- a/net/ceph/crypto.c ++++ b/net/ceph/crypto.c +@@ -526,6 +526,93 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, + } + } + ++static int ceph_aes_crypt(const struct ceph_crypto_key *key, bool encrypt, ++ void *buf, int buf_len, int in_len, int *pout_len) ++{ ++ struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); ++ SKCIPHER_REQUEST_ON_STACK(req, tfm); ++ struct sg_table sgt; ++ struct scatterlist prealloc_sg; ++ char iv[AES_BLOCK_SIZE]; ++ int pad_byte = AES_BLOCK_SIZE - (in_len & (AES_BLOCK_SIZE - 1)); ++ int crypt_len = encrypt ? in_len + pad_byte : in_len; ++ int ret; ++ ++ if (IS_ERR(tfm)) ++ return PTR_ERR(tfm); ++ ++ WARN_ON(crypt_len > buf_len); ++ if (encrypt) ++ memset(buf + in_len, pad_byte, pad_byte); ++ ret = setup_sgtable(&sgt, &prealloc_sg, buf, crypt_len); ++ if (ret) ++ goto out_tfm; ++ ++ crypto_skcipher_setkey((void *)tfm, key->key, key->len); ++ memcpy(iv, aes_iv, AES_BLOCK_SIZE); ++ ++ skcipher_request_set_tfm(req, tfm); ++ skcipher_request_set_callback(req, 0, NULL, NULL); ++ skcipher_request_set_crypt(req, sgt.sgl, sgt.sgl, crypt_len, iv); ++ ++ /* ++ print_hex_dump(KERN_ERR, "key: ", DUMP_PREFIX_NONE, 16, 1, ++ key->key, key->len, 1); ++ print_hex_dump(KERN_ERR, " in: ", DUMP_PREFIX_NONE, 16, 1, ++ buf, crypt_len, 1); ++ */ ++ if (encrypt) ++ ret = crypto_skcipher_encrypt(req); ++ else ++ ret = crypto_skcipher_decrypt(req); ++ skcipher_request_zero(req); ++ if (ret) { ++ pr_err("%s %scrypt failed: %d\n", __func__, ++ encrypt ? "en" : "de", ret); ++ goto out_sgt; ++ } ++ /* ++ print_hex_dump(KERN_ERR, "out: ", DUMP_PREFIX_NONE, 16, 1, ++ buf, crypt_len, 1); ++ */ ++ ++ if (encrypt) { ++ *pout_len = crypt_len; ++ } else { ++ pad_byte = *(char *)(buf + in_len - 1); ++ if (pad_byte > 0 && pad_byte <= AES_BLOCK_SIZE && ++ in_len >= pad_byte) { ++ *pout_len = in_len - pad_byte; ++ } else { ++ pr_err("%s got bad padding %d on in_len %d\n", ++ __func__, pad_byte, in_len); ++ ret = -EPERM; ++ goto out_sgt; ++ } ++ } ++ ++out_sgt: ++ teardown_sgtable(&sgt); ++out_tfm: ++ crypto_free_skcipher(tfm); ++ return ret; ++} ++ ++int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt, ++ void *buf, int buf_len, int in_len, int *pout_len) ++{ ++ switch (key->type) { ++ case CEPH_CRYPTO_NONE: ++ *pout_len = in_len; ++ return 0; ++ case CEPH_CRYPTO_AES: ++ return ceph_aes_crypt(key, encrypt, buf, buf_len, in_len, ++ pout_len); ++ default: ++ return -ENOTSUPP; ++ } ++} ++ + static int ceph_key_preparse(struct key_preparsed_payload *prep) + { + struct ceph_crypto_key *ckey; +diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h +index 2e9cab0..73da34e 100644 +--- a/net/ceph/crypto.h ++++ b/net/ceph/crypto.h +@@ -43,6 +43,8 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, + void *dst, size_t *dst_len, + const void *src1, size_t src1_len, + const void *src2, size_t src2_len); ++int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt, ++ void *buf, int buf_len, int in_len, int *pout_len); + int ceph_crypto_init(void); + void ceph_crypto_shutdown(void); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10154/0.patch b/Patches/Linux_CVEs/CVE-2016-10154/0.patch new file mode 100644 index 00000000..084f55e0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10154/0.patch @@ -0,0 +1,93 @@ +From 06deeec77a5a689cc94b21a8a91a76e42176685d Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Mon, 12 Dec 2016 12:54:37 -0800 +Subject: cifs: Fix smbencrypt() to stop pointing a scatterlist at the stack + +smbencrypt() points a scatterlist to the stack, which is breaks if +CONFIG_VMAP_STACK=y. + +Fix it by switching to crypto_cipher_encrypt_one(). The new code +should be considerably faster as an added benefit. + +This code is nearly identical to some code that Eric Biggers +suggested. + +Cc: stable@vger.kernel.org # 4.9 only +Reported-by: Eric Biggers +Signed-off-by: Andy Lutomirski +Acked-by: Jeff Layton +Signed-off-by: Steve French +--- + fs/cifs/smbencrypt.c | 40 ++++++++-------------------------------- + 1 file changed, 8 insertions(+), 32 deletions(-) + +diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c +index 699b786..c12bffe 100644 +--- a/fs/cifs/smbencrypt.c ++++ b/fs/cifs/smbencrypt.c +@@ -23,7 +23,7 @@ + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +-#include ++#include + #include + #include + #include +@@ -69,46 +69,22 @@ str_to_key(unsigned char *str, unsigned char *key) + static int + smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) + { +- int rc; + unsigned char key2[8]; +- struct crypto_skcipher *tfm_des; +- struct scatterlist sgin, sgout; +- struct skcipher_request *req; ++ struct crypto_cipher *tfm_des; + + str_to_key(key, key2); + +- tfm_des = crypto_alloc_skcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC); ++ tfm_des = crypto_alloc_cipher("des", 0, 0); + if (IS_ERR(tfm_des)) { +- rc = PTR_ERR(tfm_des); +- cifs_dbg(VFS, "could not allocate des crypto API\n"); +- goto smbhash_err; +- } +- +- req = skcipher_request_alloc(tfm_des, GFP_KERNEL); +- if (!req) { +- rc = -ENOMEM; + cifs_dbg(VFS, "could not allocate des crypto API\n"); +- goto smbhash_free_skcipher; ++ return PTR_ERR(tfm_des); + } + +- crypto_skcipher_setkey(tfm_des, key2, 8); +- +- sg_init_one(&sgin, in, 8); +- sg_init_one(&sgout, out, 8); ++ crypto_cipher_setkey(tfm_des, key2, 8); ++ crypto_cipher_encrypt_one(tfm_des, out, in); ++ crypto_free_cipher(tfm_des); + +- skcipher_request_set_callback(req, 0, NULL, NULL); +- skcipher_request_set_crypt(req, &sgin, &sgout, 8, NULL); +- +- rc = crypto_skcipher_encrypt(req); +- if (rc) +- cifs_dbg(VFS, "could not encrypt crypt key rc: %d\n", rc); +- +- skcipher_request_free(req); +- +-smbhash_free_skcipher: +- crypto_free_skcipher(tfm_des); +-smbhash_err: +- return rc; ++ return 0; + } + + static int +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10200/0.patch b/Patches/Linux_CVEs/CVE-2016-10200/0.patch new file mode 100644 index 00000000..6ed7d488 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10200/0.patch @@ -0,0 +1,167 @@ +From 32c231164b762dddefa13af5a0101032c70b50ef Mon Sep 17 00:00:00 2001 +From: Guillaume Nault +Date: Fri, 18 Nov 2016 22:13:00 +0100 +Subject: l2tp: fix racy SOCK_ZAPPED flag check in l2tp_ip{,6}_bind() + +Lock socket before checking the SOCK_ZAPPED flag in l2tp_ip6_bind(). +Without lock, a concurrent call could modify the socket flags between +the sock_flag(sk, SOCK_ZAPPED) test and the lock_sock() call. This way, +a socket could be inserted twice in l2tp_ip6_bind_table. Releasing it +would then leave a stale pointer there, generating use-after-free +errors when walking through the list or modifying adjacent entries. + +BUG: KASAN: use-after-free in l2tp_ip6_close+0x22e/0x290 at addr ffff8800081b0ed8 +Write of size 8 by task syz-executor/10987 +CPU: 0 PID: 10987 Comm: syz-executor Not tainted 4.8.0+ #39 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 + ffff880031d97838 ffffffff829f835b ffff88001b5a1640 ffff8800081b0ec0 + ffff8800081b15a0 ffff8800081b6d20 ffff880031d97860 ffffffff8174d3cc + ffff880031d978f0 ffff8800081b0e80 ffff88001b5a1640 ffff880031d978e0 +Call Trace: + [] dump_stack+0xb3/0x118 lib/dump_stack.c:15 + [] kasan_object_err+0x1c/0x70 mm/kasan/report.c:156 + [< inline >] print_address_description mm/kasan/report.c:194 + [] kasan_report_error+0x1f6/0x4d0 mm/kasan/report.c:283 + [< inline >] kasan_report mm/kasan/report.c:303 + [] __asan_report_store8_noabort+0x3e/0x40 mm/kasan/report.c:329 + [< inline >] __write_once_size ./include/linux/compiler.h:249 + [< inline >] __hlist_del ./include/linux/list.h:622 + [< inline >] hlist_del_init ./include/linux/list.h:637 + [] l2tp_ip6_close+0x22e/0x290 net/l2tp/l2tp_ip6.c:239 + [] inet_release+0xed/0x1c0 net/ipv4/af_inet.c:415 + [] inet6_release+0x50/0x70 net/ipv6/af_inet6.c:422 + [] sock_release+0x8d/0x1d0 net/socket.c:570 + [] sock_close+0x16/0x20 net/socket.c:1017 + [] __fput+0x28c/0x780 fs/file_table.c:208 + [] ____fput+0x15/0x20 fs/file_table.c:244 + [] task_work_run+0xf9/0x170 + [] do_exit+0x85e/0x2a00 + [] do_group_exit+0x108/0x330 + [] get_signal+0x617/0x17a0 kernel/signal.c:2307 + [] do_signal+0x7f/0x18f0 + [] exit_to_usermode_loop+0xbf/0x150 arch/x86/entry/common.c:156 + [< inline >] prepare_exit_to_usermode arch/x86/entry/common.c:190 + [] syscall_return_slowpath+0x1a0/0x1e0 arch/x86/entry/common.c:259 + [] entry_SYSCALL_64_fastpath+0xc4/0xc6 +Object at ffff8800081b0ec0, in cache L2TP/IPv6 size: 1448 +Allocated: +PID = 10987 + [ 1116.897025] [] save_stack_trace+0x16/0x20 + [ 1116.897025] [] save_stack+0x46/0xd0 + [ 1116.897025] [] kasan_kmalloc+0xad/0xe0 + [ 1116.897025] [] kasan_slab_alloc+0x12/0x20 + [ 1116.897025] [< inline >] slab_post_alloc_hook mm/slab.h:417 + [ 1116.897025] [< inline >] slab_alloc_node mm/slub.c:2708 + [ 1116.897025] [< inline >] slab_alloc mm/slub.c:2716 + [ 1116.897025] [] kmem_cache_alloc+0xc8/0x2b0 mm/slub.c:2721 + [ 1116.897025] [] sk_prot_alloc+0x69/0x2b0 net/core/sock.c:1326 + [ 1116.897025] [] sk_alloc+0x38/0xae0 net/core/sock.c:1388 + [ 1116.897025] [] inet6_create+0x2d7/0x1000 net/ipv6/af_inet6.c:182 + [ 1116.897025] [] __sock_create+0x37b/0x640 net/socket.c:1153 + [ 1116.897025] [< inline >] sock_create net/socket.c:1193 + [ 1116.897025] [< inline >] SYSC_socket net/socket.c:1223 + [ 1116.897025] [] SyS_socket+0xef/0x1b0 net/socket.c:1203 + [ 1116.897025] [] entry_SYSCALL_64_fastpath+0x23/0xc6 +Freed: +PID = 10987 + [ 1116.897025] [] save_stack_trace+0x16/0x20 + [ 1116.897025] [] save_stack+0x46/0xd0 + [ 1116.897025] [] kasan_slab_free+0x71/0xb0 + [ 1116.897025] [< inline >] slab_free_hook mm/slub.c:1352 + [ 1116.897025] [< inline >] slab_free_freelist_hook mm/slub.c:1374 + [ 1116.897025] [< inline >] slab_free mm/slub.c:2951 + [ 1116.897025] [] kmem_cache_free+0xc8/0x330 mm/slub.c:2973 + [ 1116.897025] [< inline >] sk_prot_free net/core/sock.c:1369 + [ 1116.897025] [] __sk_destruct+0x32b/0x4f0 net/core/sock.c:1444 + [ 1116.897025] [] sk_destruct+0x44/0x80 net/core/sock.c:1452 + [ 1116.897025] [] __sk_free+0x53/0x220 net/core/sock.c:1460 + [ 1116.897025] [] sk_free+0x23/0x30 net/core/sock.c:1471 + [ 1116.897025] [] sk_common_release+0x28c/0x3e0 ./include/net/sock.h:1589 + [ 1116.897025] [] l2tp_ip6_close+0x1fe/0x290 net/l2tp/l2tp_ip6.c:243 + [ 1116.897025] [] inet_release+0xed/0x1c0 net/ipv4/af_inet.c:415 + [ 1116.897025] [] inet6_release+0x50/0x70 net/ipv6/af_inet6.c:422 + [ 1116.897025] [] sock_release+0x8d/0x1d0 net/socket.c:570 + [ 1116.897025] [] sock_close+0x16/0x20 net/socket.c:1017 + [ 1116.897025] [] __fput+0x28c/0x780 fs/file_table.c:208 + [ 1116.897025] [] ____fput+0x15/0x20 fs/file_table.c:244 + [ 1116.897025] [] task_work_run+0xf9/0x170 + [ 1116.897025] [] do_exit+0x85e/0x2a00 + [ 1116.897025] [] do_group_exit+0x108/0x330 + [ 1116.897025] [] get_signal+0x617/0x17a0 kernel/signal.c:2307 + [ 1116.897025] [] do_signal+0x7f/0x18f0 + [ 1116.897025] [] exit_to_usermode_loop+0xbf/0x150 arch/x86/entry/common.c:156 + [ 1116.897025] [< inline >] prepare_exit_to_usermode arch/x86/entry/common.c:190 + [ 1116.897025] [] syscall_return_slowpath+0x1a0/0x1e0 arch/x86/entry/common.c:259 + [ 1116.897025] [] entry_SYSCALL_64_fastpath+0xc4/0xc6 +Memory state around the buggy address: + ffff8800081b0d80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ffff8800081b0e00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +>ffff8800081b0e80: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb + ^ + ffff8800081b0f00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff8800081b0f80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + +================================================================== + +The same issue exists with l2tp_ip_bind() and l2tp_ip_bind_table. + +Fixes: c51ce49735c1 ("l2tp: fix oops in L2TP IP sockets for connect() AF_UNSPEC case") +Reported-by: Baozeng Ding +Reported-by: Andrey Konovalov +Tested-by: Baozeng Ding +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +--- + net/l2tp/l2tp_ip.c | 5 +++-- + net/l2tp/l2tp_ip6.c | 5 +++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c +index fce25af..982f6c4 100644 +--- a/net/l2tp/l2tp_ip.c ++++ b/net/l2tp/l2tp_ip.c +@@ -251,8 +251,6 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) + int ret; + int chk_addr_ret; + +- if (!sock_flag(sk, SOCK_ZAPPED)) +- return -EINVAL; + if (addr_len < sizeof(struct sockaddr_l2tpip)) + return -EINVAL; + if (addr->l2tp_family != AF_INET) +@@ -267,6 +265,9 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) + read_unlock_bh(&l2tp_ip_lock); + + lock_sock(sk); ++ if (!sock_flag(sk, SOCK_ZAPPED)) ++ goto out; ++ + if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_l2tpip)) + goto out; + +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index ad3468c..9978d01 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -269,8 +269,6 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) + int addr_type; + int err; + +- if (!sock_flag(sk, SOCK_ZAPPED)) +- return -EINVAL; + if (addr->l2tp_family != AF_INET6) + return -EINVAL; + if (addr_len < sizeof(*addr)) +@@ -296,6 +294,9 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) + lock_sock(sk); + + err = -EINVAL; ++ if (!sock_flag(sk, SOCK_ZAPPED)) ++ goto out_unlock; ++ + if (sk->sk_state != TCP_CLOSE) + goto out_unlock; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10208/0.patch b/Patches/Linux_CVEs/CVE-2016-10208/0.patch new file mode 100644 index 00000000..910a6af3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10208/0.patch @@ -0,0 +1,67 @@ +From 3a4b77cd47bb837b8557595ec7425f281f2ca1fe Mon Sep 17 00:00:00 2001 +From: Eryu Guan +Date: Thu, 1 Dec 2016 15:08:37 -0500 +Subject: ext4: validate s_first_meta_bg at mount time + +Ralf Spenneberg reported that he hit a kernel crash when mounting a +modified ext4 image. And it turns out that kernel crashed when +calculating fs overhead (ext4_calculate_overhead()), this is because +the image has very large s_first_meta_bg (debug code shows it's +842150400), and ext4 overruns the memory in count_overhead() when +setting bitmap buffer, which is PAGE_SIZE. + +ext4_calculate_overhead(): + buf = get_zeroed_page(GFP_NOFS); <=== PAGE_SIZE buffer + blks = count_overhead(sb, i, buf); + +count_overhead(): + for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { <=== j = 842150400 + ext4_set_bit(EXT4_B2C(sbi, s++), buf); <=== buffer overrun + count++; + } + +This can be reproduced easily for me by this script: + + #!/bin/bash + rm -f fs.img + mkdir -p /mnt/ext4 + fallocate -l 16M fs.img + mke2fs -t ext4 -O bigalloc,meta_bg,^resize_inode -F fs.img + debugfs -w -R "ssv first_meta_bg 842150400" fs.img + mount -o loop fs.img /mnt/ext4 + +Fix it by validating s_first_meta_bg first at mount time, and +refusing to mount if its value exceeds the largest possible meta_bg +number. + +Reported-by: Ralf Spenneberg +Signed-off-by: Eryu Guan +Signed-off-by: Theodore Ts'o +Reviewed-by: Andreas Dilger +--- + fs/ext4/super.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index a526956..32c0deb 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3842,6 +3842,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb))); + db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / + EXT4_DESC_PER_BLOCK(sb); ++ if (ext4_has_feature_meta_bg(sb)) { ++ if (le32_to_cpu(es->s_first_meta_bg) >= db_count) { ++ ext4_msg(sb, KERN_WARNING, ++ "first meta block group too large: %u " ++ "(group descriptor block count %u)", ++ le32_to_cpu(es->s_first_meta_bg), db_count); ++ goto failed_mount; ++ } ++ } + sbi->s_group_desc = ext4_kvmalloc(db_count * + sizeof(struct buffer_head *), + GFP_KERNEL); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10208/1.patch b/Patches/Linux_CVEs/CVE-2016-10208/1.patch new file mode 100644 index 00000000..a8320eed --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10208/1.patch @@ -0,0 +1,71 @@ +From cde863587b6809fdf61ea3c5391ecf06884b5516 Mon Sep 17 00:00:00 2001 +From: Eryu Guan +Date: Thu, 1 Dec 2016 15:08:37 -0500 +Subject: ext4: validate s_first_meta_bg at mount time + +commit 3a4b77cd47bb837b8557595ec7425f281f2ca1fe upstream. + +Ralf Spenneberg reported that he hit a kernel crash when mounting a +modified ext4 image. And it turns out that kernel crashed when +calculating fs overhead (ext4_calculate_overhead()), this is because +the image has very large s_first_meta_bg (debug code shows it's +842150400), and ext4 overruns the memory in count_overhead() when +setting bitmap buffer, which is PAGE_SIZE. + +ext4_calculate_overhead(): + buf = get_zeroed_page(GFP_NOFS); <=== PAGE_SIZE buffer + blks = count_overhead(sb, i, buf); + +count_overhead(): + for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { <=== j = 842150400 + ext4_set_bit(EXT4_B2C(sbi, s++), buf); <=== buffer overrun + count++; + } + +This can be reproduced easily for me by this script: + + #!/bin/bash + rm -f fs.img + mkdir -p /mnt/ext4 + fallocate -l 16M fs.img + mke2fs -t ext4 -O bigalloc,meta_bg,^resize_inode -F fs.img + debugfs -w -R "ssv first_meta_bg 842150400" fs.img + mount -o loop fs.img /mnt/ext4 + +Fix it by validating s_first_meta_bg first at mount time, and +refusing to mount if its value exceeds the largest possible meta_bg +number. + +Reported-by: Ralf Spenneberg +Signed-off-by: Eryu Guan +Signed-off-by: Theodore Ts'o +Reviewed-by: Andreas Dilger +[bwh: Backported to 3.16: use EXT4_HAS_INCOMPAT_FEATURE()] +Signed-off-by: Ben Hutchings +--- + fs/ext4/super.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index a1fed66..13a33c3 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3905,6 +3905,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb))); + db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / + EXT4_DESC_PER_BLOCK(sb); ++ if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG)) { ++ if (le32_to_cpu(es->s_first_meta_bg) >= db_count) { ++ ext4_msg(sb, KERN_WARNING, ++ "first meta block group too large: %u " ++ "(group descriptor block count %u)", ++ le32_to_cpu(es->s_first_meta_bg), db_count); ++ goto failed_mount; ++ } ++ } + sbi->s_group_desc = ext4_kvmalloc(db_count * + sizeof(struct buffer_head *), + GFP_KERNEL); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10208/2.patch b/Patches/Linux_CVEs/CVE-2016-10208/2.patch new file mode 100644 index 00000000..e5f22a8e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10208/2.patch @@ -0,0 +1,31 @@ +From 2ba3e6e8afc9b6188b471f27cf2b5e3cf34e7af2 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 15 Feb 2017 01:26:39 -0500 +Subject: [PATCH] ext4: fix fencepost in s_first_meta_bg validation + +It is OK for s_first_meta_bg to be equal to the number of block group +descriptor blocks. (It rarely happens, but it shouldn't cause any +problems.) + +https://bugzilla.kernel.org/show_bug.cgi?id=194567 + +Fixes: 3a4b77cd47bb837b8557595ec7425f281f2ca1fe +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +--- + fs/ext4/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index dde14a7ac6d77..a673558fe5f86 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3860,7 +3860,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / + EXT4_DESC_PER_BLOCK(sb); + if (ext4_has_feature_meta_bg(sb)) { +- if (le32_to_cpu(es->s_first_meta_bg) >= db_count) { ++ if (le32_to_cpu(es->s_first_meta_bg) > db_count) { + ext4_msg(sb, KERN_WARNING, + "first meta block group too large: %u " + "(group descriptor block count %u)", diff --git a/Patches/Linux_CVEs/CVE-2016-10208/3.patch b/Patches/Linux_CVEs/CVE-2016-10208/3.patch new file mode 100644 index 00000000..ff617f15 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10208/3.patch @@ -0,0 +1,37 @@ +From 6cc435bb47841104995c8668de8f5839d0040357 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 15 Feb 2017 01:26:39 -0500 +Subject: ext4: fix fencepost in s_first_meta_bg validation + +commit 2ba3e6e8afc9b6188b471f27cf2b5e3cf34e7af2 upstream. + +It is OK for s_first_meta_bg to be equal to the number of block group +descriptor blocks. (It rarely happens, but it shouldn't cause any +problems.) + +https://bugzilla.kernel.org/show_bug.cgi?id=194567 + +Fixes: 3a4b77cd47bb837b8557595ec7425f281f2ca1fe +Signed-off-by: Theodore Ts'o +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings +--- + fs/ext4/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index a0f6526..af0267f 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3916,7 +3916,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / + EXT4_DESC_PER_BLOCK(sb); + if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG)) { +- if (le32_to_cpu(es->s_first_meta_bg) >= db_count) { ++ if (le32_to_cpu(es->s_first_meta_bg) > db_count) { + ext4_msg(sb, KERN_WARNING, + "first meta block group too large: %u " + "(group descriptor block count %u)", +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10229/0.patch b/Patches/Linux_CVEs/CVE-2016-10229/0.patch new file mode 100644 index 00000000..1d12eaa4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10229/0.patch @@ -0,0 +1,94 @@ +From 197c949e7798fbf28cfadc69d9ca0c2abbf93191 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 30 Dec 2015 08:51:12 -0500 +Subject: udp: properly support MSG_PEEK with truncated buffers + +Backport of this upstream commit into stable kernels : +89c22d8c3b27 ("net: Fix skb csum races when peeking") +exposed a bug in udp stack vs MSG_PEEK support, when user provides +a buffer smaller than skb payload. + +In this case, +skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), + msg->msg_iov); +returns -EFAULT. + +This bug does not happen in upstream kernels since Al Viro did a great +job to replace this into : +skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), msg); +This variant is safe vs short buffers. + +For the time being, instead reverting Herbert Xu patch and add back +skb->ip_summed invalid changes, simply store the result of +udp_lib_checksum_complete() so that we avoid computing the checksum a +second time, and avoid the problematic +skb_copy_and_csum_datagram_iovec() call. + +This patch can be applied on recent kernels as it avoids a double +checksumming, then backported to stable kernels as a bug fix. + +Signed-off-by: Eric Dumazet +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +--- + net/ipv4/udp.c | 6 ++++-- + net/ipv6/udp.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 8841e98..ac14ae4 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1271,6 +1271,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, + int peeked, off = 0; + int err; + int is_udplite = IS_UDPLITE(sk); ++ bool checksum_valid = false; + bool slow; + + if (flags & MSG_ERRQUEUE) +@@ -1296,11 +1297,12 @@ try_again: + */ + + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { +- if (udp_lib_checksum_complete(skb)) ++ checksum_valid = !udp_lib_checksum_complete(skb); ++ if (!checksum_valid) + goto csum_copy_err; + } + +- if (skb_csum_unnecessary(skb)) ++ if (checksum_valid || skb_csum_unnecessary(skb)) + err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), + msg, copied); + else { +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 9da3287..00775ee 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -402,6 +402,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + int peeked, off = 0; + int err; + int is_udplite = IS_UDPLITE(sk); ++ bool checksum_valid = false; + int is_udp4; + bool slow; + +@@ -433,11 +434,12 @@ try_again: + */ + + if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { +- if (udp_lib_checksum_complete(skb)) ++ checksum_valid = !udp_lib_checksum_complete(skb); ++ if (!checksum_valid) + goto csum_copy_err; + } + +- if (skb_csum_unnecessary(skb)) ++ if (checksum_valid || skb_csum_unnecessary(skb)) + err = skb_copy_datagram_msg(skb, sizeof(struct udphdr), + msg, copied); + else { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10230/0.patch b/Patches/Linux_CVEs/CVE-2016-10230/0.patch new file mode 100644 index 00000000..91af1025 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10230/0.patch @@ -0,0 +1,35 @@ +From bd9a8fc6d7f6bd1a0b936994630006de450df657 Mon Sep 17 00:00:00 2001 +From: Neeraj Soni +Date: Mon, 28 Nov 2016 18:23:33 +0530 +Subject: qcrypto: protect potential integer overflow. + +Adding user passed parameters without check might +lead to Integer overflow and unpredictable system +behaviour. + +Change-Id: Iaf8259e3c4a157e1790f1447b1b62a646988b7c4 +Signed-off-by: Neeraj Soni +--- + drivers/crypto/msm/qce50.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c +index b33d879..9788e0e 100644 +--- a/drivers/crypto/msm/qce50.c ++++ b/drivers/crypto/msm/qce50.c +@@ -4913,6 +4913,12 @@ int qce_aead_req(void *handle, struct qce_req *q_req) + else + q_req->cryptlen = areq->cryptlen - authsize; + ++ if ((q_req->cryptlen > UINT_MAX - areq->assoclen) || ++ (q_req->cryptlen + areq->assoclen > UINT_MAX - ivsize)) { ++ pr_err("Integer overflow on total aead req length.\n"); ++ return -EINVAL; ++ } ++ + totallen = q_req->cryptlen + areq->assoclen + ivsize; + + if (pce_dev->support_cmd_dscr) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10231/0.patch b/Patches/Linux_CVEs/CVE-2016-10231/0.patch new file mode 100644 index 00000000..bd6cb256 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10231/0.patch @@ -0,0 +1,37 @@ +From 3bfe5a89916f7d29492e9f6d941d108b688cb804 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Mani +Date: Wed, 14 Dec 2016 11:46:35 -0800 +Subject: ASoC: wcd9335: Fix out of bounds for mad input value + +Add check in tasha_mad_input_put function to +return error on out of bounds access using +mad input value. + +CRs-fixed: 1096799 +Change-Id: Iddaa3fef362f7cb1919aa3bd8dd4b83133fe7c97 +Signed-off-by: Karthikeyan Mani +--- + sound/soc/codecs/wcd9335.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c +index c94623c..1f97326 100644 +--- a/sound/soc/codecs/wcd9335.c ++++ b/sound/soc/codecs/wcd9335.c +@@ -7575,6 +7575,13 @@ static int tasha_mad_input_put(struct snd_kcontrol *kcontrol, + + tasha_mad_input = ucontrol->value.integer.value[0]; + ++ if (tasha_mad_input >= ARRAY_SIZE(tasha_conn_mad_text)) { ++ dev_err(codec->dev, ++ "%s: tasha_mad_input = %d out of bounds\n", ++ __func__, tasha_mad_input); ++ return -EINVAL; ++ } ++ + if (!strcmp(tasha_conn_mad_text[tasha_mad_input], "NOTUSED1") || + !strcmp(tasha_conn_mad_text[tasha_mad_input], "NOTUSED2") || + !strcmp(tasha_conn_mad_text[tasha_mad_input], "NOTUSED3") || +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10231/1.patch b/Patches/Linux_CVEs/CVE-2016-10231/1.patch new file mode 100644 index 00000000..4668d712 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10231/1.patch @@ -0,0 +1,38 @@ +From 597b1ae4e29ecbc40dc21ea3646f5ee1ee61932e Mon Sep 17 00:00:00 2001 +From: Karthikeyan Mani +Date: Wed, 7 Dec 2016 18:19:31 -0800 +Subject: ASoC: wcd9320: Fix out of bounds for mad input value + +Add check in taiko_mad_input_put function to +return error on out of bounds access using +mad input value + +CRs-fixed: 1096799 +Change-Id: I75ce9e881cf05a50e874a555b2f8bd3286cdaed4 +Signed-off-by: Karthikeyan Mani +--- + sound/soc/codecs/wcd9320.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c +index 697a1b6..ee4af87 100644 +--- a/sound/soc/codecs/wcd9320.c ++++ b/sound/soc/codecs/wcd9320.c +@@ -1204,6 +1204,14 @@ static int taiko_mad_input_put(struct snd_kcontrol *kcontrol, + + taiko_mad_input = ucontrol->value.integer.value[0]; + ++ if (taiko_mad_input >= ARRAY_SIZE(taiko_conn_mad_text)) { ++ dev_err(codec->dev, ++ "%s: taiko_mad_input = %d out of bounds\n", ++ __func__, taiko_mad_input); ++ return -EINVAL; ++ } ++ ++ + micb_4_int_reg = taiko->resmgr.reg_addr->micb_4_int_rbias; + pr_debug("%s: taiko_mad_input = %s\n", __func__, + taiko_conn_mad_text[taiko_mad_input]); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10232/0.patch b/Patches/Linux_CVEs/CVE-2016-10232/0.patch new file mode 100644 index 00000000..6f3a9bf1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10232/0.patch @@ -0,0 +1,111 @@ +From 27f7b3b3059f6181e2786f886f4cd92f413bc30c Mon Sep 17 00:00:00 2001 +From: Shalini Krishnamoorthi +Date: Thu, 30 Jun 2016 14:00:04 -0700 +Subject: msm: mdss: Correct the format specifiers in sscanf function + +In many parts of the code the sscanf function was getting +an unsigned integer with a wrong format specifier. Changed +the format specifiers appropriately. Single variable sscanf +were replaced by kstrtouint at reported places. + +CRs-Fixed: 1024872 +Change-Id: I03ce718b0456d437d31d701586965d0aa7443b51 +Signed-off-by: Shalini Krishnamoorthi +--- + drivers/video/msm/mdss/mdss_debug.c | 8 ++++---- + drivers/video/msm/mdss/mdss_fb.c | 8 ++++---- + drivers/video/msm/mdss/mdss_mdp.c | 2 +- + drivers/video/msm/mdss/mdss_mdp_overlay.c | 2 +- + 4 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c +index 21c2394..861d70f 100644 +--- a/drivers/video/msm/mdss/mdss_debug.c ++++ b/drivers/video/msm/mdss/mdss_debug.c +@@ -81,7 +81,7 @@ static ssize_t panel_debug_base_offset_write(struct file *file, + + buf[count] = 0; /* end of string */ + +- if (sscanf(buf, "%x %d", &off, &cnt) != 2) ++ if (sscanf(buf, "%x %u", &off, &cnt) != 2) + return -EFAULT; + + if (off > dbg->max_offset) +@@ -735,11 +735,11 @@ static ssize_t mdss_debug_factor_write(struct file *file, + + if (strnchr(buf, count, '/')) { + /* Parsing buf as fraction */ +- if (sscanf(buf, "%d/%d", &numer, &denom) != 2) ++ if (sscanf(buf, "%u/%u", &numer, &denom) != 2) + return -EFAULT; + } else { + /* Parsing buf as percentage */ +- if (sscanf(buf, "%d", &numer) != 1) ++ if (kstrtouint(buf, 0, &numer)) + return -EFAULT; + denom = 100; + } +@@ -1047,7 +1047,7 @@ static ssize_t mdss_debug_perf_bw_limit_write(struct file *file, + + if (strnchr(buf, count, ' ')) { + /* Parsing buf */ +- if (sscanf(buf, "%d %d", &mode, &val) != 2) ++ if (sscanf(buf, "%u %u", &mode, &val) != 2) + return -EFAULT; + } + +diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c +index dc2e318..624b344 100644 +--- a/drivers/video/msm/mdss/mdss_fb.c ++++ b/drivers/video/msm/mdss/mdss_fb.c +@@ -600,8 +600,8 @@ static ssize_t mdss_fb_force_panel_dead(struct device *dev, + return len; + } + +- if (sscanf(buf, "%d", &pdata->panel_info.panel_force_dead) != 1) +- pr_err("sccanf buf error!\n"); ++ if (kstrtouint(buf, 0, &pdata->panel_info.panel_force_dead)) ++ pr_err("kstrtouint buf error!\n"); + + return len; + } +@@ -714,8 +714,8 @@ static ssize_t mdss_fb_change_dfps_mode(struct device *dev, + } + pinfo = &pdata->panel_info; + +- if (sscanf(buf, "%d", &dfps_mode) != 1) { +- pr_err("sccanf buf error!\n"); ++ if (kstrtouint(buf, 0, &dfps_mode)) { ++ pr_err("kstrtouint buf error!\n"); + return len; + } + +diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c +index e2697ca..7bfbdda 100644 +--- a/drivers/video/msm/mdss/mdss_mdp.c ++++ b/drivers/video/msm/mdss/mdss_mdp.c +@@ -2448,7 +2448,7 @@ static ssize_t mdss_mdp_store_max_limit_bw(struct device *dev, + struct mdss_data_type *mdata = dev_get_drvdata(dev); + u32 data = 0; + +- if (1 != sscanf(buf, "%d", &data)) { ++ if (kstrtouint(buf, 0, &data)) { + pr_info("Not able scan to bw_mode_bitmap\n"); + } else { + mdata->bw_mode_bitmap = data; +diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c +index 7e2325f..74cb38e 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c ++++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c +@@ -2973,7 +2973,7 @@ static ssize_t dynamic_fps_sysfs_wta_dfps(struct device *dev, + + if (pdata->panel_info.dfps_update == + DFPS_IMMEDIATE_MULTI_UPDATE_MODE_CLK_HFP) { +- if (sscanf(buf, "%d %d %d %d %d", ++ if (sscanf(buf, "%u %u %u %u %u", + &data.hfp, &data.hbp, &data.hpw, + &data.clk_rate, &data.fps) != 5) { + pr_err("could not read input\n"); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10232/1.patch b/Patches/Linux_CVEs/CVE-2016-10232/1.patch new file mode 100644 index 00000000..f01b45cf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10232/1.patch @@ -0,0 +1,83 @@ +From 21e0ead58e47798567d846b84f16f89cf69a57ae Mon Sep 17 00:00:00 2001 +From: Shalini Krishnamoorthi +Date: Thu, 30 Jun 2016 14:00:04 -0700 +Subject: msm: mdss: Correct the format specifiers in sscanf function + +In many parts of the code the sscanf function was getting +an unsigned integer with a wrong format specifier. Changed +the format specifiers appropriately. Single variable sscanf +were replaced by kstrtouint at reported places. + +CRs-Fixed: 1024872 +Change-Id: I03ce718b0456d437d31d701586965d0aa7443b51 +Signed-off-by: Shalini Krishnamoorthi +--- + drivers/video/msm/mdss/mdss_debug.c | 6 +++--- + drivers/video/msm/mdss/mdss_fb.c | 10 +++++----- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c +index 1d214ca..525cdbd 100644 +--- a/drivers/video/msm/mdss/mdss_debug.c ++++ b/drivers/video/msm/mdss/mdss_debug.c +@@ -78,7 +78,7 @@ static ssize_t panel_debug_base_offset_write(struct file *file, + + buf[count] = 0; /* end of string */ + +- if (sscanf(buf, "%x %x", &off, &cnt) != 2) ++ if (sscanf(buf, "%x %u", &off, &cnt) != 2) + return -EFAULT; + + if (off > dbg->max_offset) +@@ -679,11 +679,11 @@ static ssize_t mdss_debug_factor_write(struct file *file, + + if (strnchr(buf, count, '/')) { + /* Parsing buf as fraction */ +- if (sscanf(buf, "%d/%d", &numer, &denom) != 2) ++ if (sscanf(buf, "%u/%u", &numer, &denom) != 2) + return -EFAULT; + } else { + /* Parsing buf as percentage */ +- if (sscanf(buf, "%d", &numer) != 1) ++ if (kstrtouint(buf, 0, &numer)) + return -EFAULT; + denom = 100; + } +diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c +index 971fde4..ecc35c9 100644 +--- a/drivers/video/msm/mdss/mdss_fb.c ++++ b/drivers/video/msm/mdss/mdss_fb.c +@@ -2,7 +2,7 @@ + * Core MDSS framebuffer driver. + * + * Copyright (C) 2007 Google Incorporated +- * Copyright (c) 2008-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -593,8 +593,8 @@ static ssize_t mdss_fb_force_panel_dead(struct device *dev, + return len; + } + +- if (sscanf(buf, "%d", &pdata->panel_info.panel_force_dead) != 1) +- pr_err("sccanf buf error!\n"); ++ if (kstrtouint(buf, 0, &pdata->panel_info.panel_force_dead)) ++ pr_err("kstrtouint buf error\n"); + + return len; + } +@@ -707,8 +707,8 @@ static ssize_t mdss_fb_change_dfps_mode(struct device *dev, + } + pinfo = &pdata->panel_info; + +- if (sscanf(buf, "%d", &dfps_mode) != 1) { +- pr_err("sccanf buf error!\n"); ++ if (kstrtouint(buf, 0, &dfps_mode)) { ++ pr_err("kstrtouint buf error\n"); + return len; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10233/0.patch b/Patches/Linux_CVEs/CVE-2016-10233/0.patch new file mode 100644 index 00000000..1e482a70 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10233/0.patch @@ -0,0 +1,102 @@ +From d793c6d91ecba2a1fd206ad47a4fd408d290addf Mon Sep 17 00:00:00 2001 +From: Trilokesh Rangam +Date: Wed, 23 Nov 2016 09:41:36 +0530 +Subject: msm-camera: Addressing possible overflow conditions + +Changes to address possible integer overflow and incorrect +array indexing conditions. + +Change-Id: Ib134320cd6f7b34d7a10572ec347ec12127049a9 +Signed-off-by: Trilokesh Rangam +--- + drivers/media/video/msm/io/msm_camera_io_util.c | 6 +++++ + drivers/media/video/msm/msm_mctl_pp.c | 36 ++++++++++++++++++++++--- + 2 files changed, 38 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/video/msm/io/msm_camera_io_util.c b/drivers/media/video/msm/io/msm_camera_io_util.c +index cede05d..1d2a70c 100644 +--- a/drivers/media/video/msm/io/msm_camera_io_util.c ++++ b/drivers/media/video/msm/io/msm_camera_io_util.c +@@ -181,6 +181,12 @@ int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg, + pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__); + return -EINVAL; + } ++ ++ if (cam_vreg == NULL) { ++ pr_err("%s:%d cam_vreg sequence invalid\n", __func__, __LINE__); ++ return -EINVAL; ++ } ++ + if (!num_vreg_seq) + num_vreg_seq = num_vreg; + +diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c +index 8f4f004..61321bf 100644 +--- a/drivers/media/video/msm/msm_mctl_pp.c ++++ b/drivers/media/video/msm/msm_mctl_pp.c +@@ -36,6 +36,8 @@ + #define D(fmt, args...) do {} while (0) + #endif + ++#define UINT32_MAX (4294967295U) ++ + static int msm_mctl_pp_buf_divert( + struct msm_cam_media_controller *pmctl, + struct msm_cam_v4l2_dev_inst *pcam_inst, +@@ -668,11 +670,24 @@ int msm_mctl_pp_done( + dirty = 1; + } + } else { +- if (frame.num_planes > 1) ++ if (frame.num_planes > 1) { ++ if (frame.mp[0].phy_addr > ++ (UINT32_MAX - frame.mp[0].data_offset)) { ++ pr_err("%s:%d Invalid data offset\n", __func__, __LINE__); ++ return -EINVAL; ++ ++ } + buf.ch_paddr[0] = frame.mp[0].phy_addr + + frame.mp[0].data_offset; +- else ++ } else { ++ if (frame.sp.phy_addr > ++ (UINT32_MAX - frame.sp.y_off)) { ++ pr_err("%s:%d Invalid Y offset\n", __func__, __LINE__); ++ return -EINVAL; ++ ++ } + buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off; ++ } + } + spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags); + +@@ -713,11 +728,24 @@ int msm_mctl_pp_divert_done( + buf_handle.image_mode = frame.image_type; + } + +- if (frame.num_planes > 1) ++ if (frame.num_planes > 1) { ++ if (frame.mp[0].phy_addr > ++ (UINT32_MAX - frame.mp[0].data_offset)) { ++ pr_err("%s:%d Invalid data offset\n", __func__, __LINE__); ++ return -EINVAL; ++ ++ } + buf.ch_paddr[0] = frame.mp[0].phy_addr + + frame.mp[0].data_offset; +- else ++ } else { ++ if (frame.sp.phy_addr > ++ (UINT32_MAX - frame.sp.y_off)) { ++ pr_err("%s:%d Invalid Y offset\n", __func__, __LINE__); ++ return -EINVAL; ++ ++ } + buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off; ++ } + + spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10233/1.patch b/Patches/Linux_CVEs/CVE-2016-10233/1.patch new file mode 100644 index 00000000..139d25cf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10233/1.patch @@ -0,0 +1,37 @@ +From ada155f04184f09ed6972ac7bbe86205422275e0 Mon Sep 17 00:00:00 2001 +From: VijayaKumar T M +Date: Wed, 4 Jan 2017 13:12:38 +0530 +Subject: msm-camera: Addressing possible overflow conditions + +Changes to address possible integer overflow and incorrect +array indexing conditions. + +CRs-Fixed: 897259 +Change-Id: Ib134320cd6f7b34d7a10572ec347ec12127049a9 +Signed-off-by: Trilokesh Rangam +Signed-off-by: Yang Guang +Signed-off-by: VijayaKumar T M +--- + drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +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 41c784a..ffd1f1e 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 +@@ -253,6 +253,12 @@ int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg, + pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__); + return -EINVAL; + } ++ ++ if (cam_vreg == NULL) { ++ pr_err("%s:%d cam_vreg sequence invalid\n", __func__, __LINE__); ++ return -EINVAL; ++ } ++ + if (!num_vreg_seq) + num_vreg_seq = num_vreg; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10234/0.patch b/Patches/Linux_CVEs/CVE-2016-10234/0.patch new file mode 100644 index 00000000..a9937f0e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10234/0.patch @@ -0,0 +1,382 @@ +From d12370c7f3ecded1867fbd6b70ded35db55cab1d Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Wed, 19 Oct 2016 13:30:44 -0700 +Subject: msm: ipa: fix ioctl input param validation + +Fix input parameter validation in order to avoid +device crash because of incorrect parameter in IPA driver. + +Change-Id: Icbdb05aeb9211665420a872d3453dbbd24fd347b +CRs-Fixed: 1069060 +Acked-by: Ady Abraham +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa_v2/ipa_flt.c | 36 ++++++++++++--- + drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 2 +- + drivers/platform/msm/ipa/ipa_v2/ipa_nat.c | 77 ++++++++++++++++++++++++++++++- + drivers/platform/msm/ipa/ipa_v2/ipa_rt.c | 26 +++++++++-- + drivers/platform/msm/ipa/ipa_v3/ipa_nat.c | 76 ++++++++++++++++++++++++++++++ + 5 files changed, 205 insertions(+), 12 deletions(-) + +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c +index c36ecfe..d6e563b 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -235,7 +235,7 @@ static int ipa_generate_flt_hw_rule(enum ipa_ip_type ip, + * @ip: the ip address family type + * @hdr_sz: header size + * +- * Returns: 0 on success, negative on failure ++ * Returns: size on success, negative on failure + * + * caller needs to hold any needed locks to ensure integrity + * +@@ -373,7 +373,12 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, + ((long)body & + IPA_FLT_ENTRY_MEMORY_ALLIGNMENT)); + } else { +- WARN_ON(tbl->sz == 0); ++ if (tbl->sz == 0) { ++ IPAERR("tbl size is 0\n"); ++ WARN_ON(1); ++ goto proc_err; ++ } ++ + /* allocate memory for the flt tbl */ + flt_tbl_mem.size = tbl->sz; + flt_tbl_mem.base = +@@ -460,7 +465,12 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, + ((long)body & + IPA_FLT_ENTRY_MEMORY_ALLIGNMENT)); + } else { +- WARN_ON(tbl->sz == 0); ++ if (tbl->sz == 0) { ++ IPAERR("tbl size is 0\n"); ++ WARN_ON(1); ++ goto proc_err; ++ } ++ + /* allocate memory for the flt tbl */ + flt_tbl_mem.size = tbl->sz; + flt_tbl_mem.base = +@@ -534,8 +544,15 @@ static int ipa_generate_flt_hw_tbl_v1_1(enum ipa_ip_type ip, + u8 *hdr; + u8 *body; + u8 *base; ++ int res; ++ ++ res = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); ++ if (res < 0) { ++ IPAERR("ipa_get_flt_hw_tbl_size failed %d\n", res); ++ return res; ++ } + +- mem->size = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); ++ mem->size = res; + mem->size = IPA_HW_TABLE_ALIGNMENT(mem->size); + + if (mem->size == 0) { +@@ -720,6 +737,7 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip, + u32 *entr; + u32 body_start_offset; + u32 hdr_top; ++ int res; + + if (ip == IPA_IP_v4) + body_start_offset = IPA_MEM_PART(apps_v4_flt_ofst) - +@@ -756,7 +774,13 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip, + entr++; + } + +- mem->size = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); ++ res = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); ++ if (res < 0) { ++ IPAERR("ipa_get_flt_hw_tbl_size failed %d\n", res); ++ goto body_err; ++ } ++ ++ mem->size = res; + mem->size -= hdr_sz; + mem->size = IPA_HW_TABLE_ALIGNMENT(mem->size); + +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +index ba16682..1e3c098 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +@@ -137,7 +137,7 @@ + + #define IPA_HW_TABLE_ALIGNMENT(start_ofst) \ + (((start_ofst) + 127) & ~127) +-#define IPA_RT_FLT_HW_RULE_BUF_SIZE (128) ++#define IPA_RT_FLT_HW_RULE_BUF_SIZE (256) + + #define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT_BYTE 8 + #define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT(start_ofst) \ +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c +index 6202992..314b095 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -25,6 +25,16 @@ + #define IPA_NAT_SHARED_MEMORY 1 + #define IPA_NAT_TEMP_MEM_SIZE 128 + ++enum nat_table_type { ++ IPA_NAT_BASE_TBL = 0, ++ IPA_NAT_EXPN_TBL = 1, ++ IPA_NAT_INDX_TBL = 2, ++ IPA_NAT_INDEX_EXPN_TBL = 3, ++}; ++ ++#define NAT_TABLE_ENTRY_SIZE_BYTE 32 ++#define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 ++ + static int ipa_nat_vma_fault_remap( + struct vm_area_struct *vma, struct vm_fault *vmf) + { +@@ -568,6 +578,71 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) + goto bail; + } + ++ for (cnt = 0; cnt < dma->entries; cnt++) { ++ if (dma->dma[cnt].table_index >= 1) { ++ IPAERR("Invalid table index %d\n", ++ dma->dma[cnt].table_index); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ switch (dma->dma[cnt].base_addr) { ++ case IPA_NAT_BASE_TBL: ++ if (dma->dma[cnt].offset >= ++ (ipa_ctx->nat_mem.size_base_tables + 1) * ++ NAT_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_EXPN_TBL: ++ if (dma->dma[cnt].offset >= ++ ipa_ctx->nat_mem.size_expansion_tables * ++ NAT_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_INDX_TBL: ++ if (dma->dma[cnt].offset >= ++ (ipa_ctx->nat_mem.size_base_tables + 1) * ++ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_INDEX_EXPN_TBL: ++ if (dma->dma[cnt].offset >= ++ ipa_ctx->nat_mem.size_expansion_tables * ++ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ default: ++ IPAERR("Invalid base_addr %d\n", ++ dma->dma[cnt].base_addr); ++ ret = -EPERM; ++ goto bail; ++ } ++ } ++ + size = sizeof(struct ipa_desc) * NUM_OF_DESC; + desc = kzalloc(size, GFP_KERNEL); + if (desc == NULL) { +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +index 4ec43dd..8efc2d8 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +@@ -227,7 +227,7 @@ int __ipa_generate_rt_hw_rule_v2_6L(enum ipa_ip_type ip, + * @hdr_sz: header size + * @max_rt_idx: maximal index + * +- * Returns: 0 on success, negative on failure ++ * Returns: size on success, negative on failure + * + * caller needs to hold any needed locks to ensure integrity + * +@@ -356,7 +356,11 @@ static int ipa_generate_rt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, u8 *hdr, + ((long)body & + IPA_RT_ENTRY_MEMORY_ALLIGNMENT)); + } else { +- WARN_ON(tbl->sz == 0); ++ if (tbl->sz == 0) { ++ IPAERR("cannot generate 0 size table\n"); ++ goto proc_err; ++ } ++ + /* allocate memory for the RT tbl */ + rt_tbl_mem.size = tbl->sz; + rt_tbl_mem.base = +@@ -429,8 +433,15 @@ static int ipa_generate_rt_hw_tbl_v1_1(enum ipa_ip_type ip, + u8 *base; + int max_rt_idx; + int i; ++ int res; + +- mem->size = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); ++ res = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); ++ if (res < 0) { ++ IPAERR("ipa_get_rt_hw_tbl_size failed %d\n", res); ++ goto error; ++ } ++ ++ mem->size = res; + mem->size = (mem->size + IPA_RT_TABLE_MEMORY_ALLIGNMENT) & + ~IPA_RT_TABLE_MEMORY_ALLIGNMENT; + +@@ -603,6 +614,7 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip, + int num_index; + u32 body_start_offset; + u32 apps_start_idx; ++ int res; + + if (ip == IPA_IP_v4) { + num_index = IPA_MEM_PART(v4_apps_rt_index_hi) - +@@ -632,7 +644,13 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip, + entr++; + } + +- mem->size = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); ++ res = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); ++ if (res < 0) { ++ IPAERR("ipa_get_rt_hw_tbl_size failed %d\n", res); ++ goto base_err; ++ } ++ ++ mem->size = res; + mem->size -= hdr_sz; + mem->size = (mem->size + IPA_RT_TABLE_MEMORY_ALLIGNMENT) & + ~IPA_RT_TABLE_MEMORY_ALLIGNMENT; +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +index 67e9b39..e7e5cf1 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +@@ -24,6 +24,17 @@ + + #define IPA_NAT_TEMP_MEM_SIZE 128 + ++enum nat_table_type { ++ IPA_NAT_BASE_TBL = 0, ++ IPA_NAT_EXPN_TBL = 1, ++ IPA_NAT_INDX_TBL = 2, ++ IPA_NAT_INDEX_EXPN_TBL = 3, ++}; ++ ++#define NAT_TABLE_ENTRY_SIZE_BYTE 32 ++#define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 ++ ++ + static int ipa3_nat_vma_fault_remap( + struct vm_area_struct *vma, struct vm_fault *vmf) + { +@@ -571,6 +582,71 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) + goto bail; + } + ++ for (cnt = 0; cnt < dma->entries; cnt++) { ++ if (dma->dma[cnt].table_index >= 1) { ++ IPAERR("Invalid table index %d\n", ++ dma->dma[cnt].table_index); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ switch (dma->dma[cnt].base_addr) { ++ case IPA_NAT_BASE_TBL: ++ if (dma->dma[cnt].offset >= ++ (ipa3_ctx->nat_mem.size_base_tables + 1) * ++ NAT_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_EXPN_TBL: ++ if (dma->dma[cnt].offset >= ++ ipa3_ctx->nat_mem.size_expansion_tables * ++ NAT_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_INDX_TBL: ++ if (dma->dma[cnt].offset >= ++ (ipa3_ctx->nat_mem.size_base_tables + 1) * ++ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_INDEX_EXPN_TBL: ++ if (dma->dma[cnt].offset >= ++ ipa3_ctx->nat_mem.size_expansion_tables * ++ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ default: ++ IPAERR("Invalid base_addr %d\n", ++ dma->dma[cnt].base_addr); ++ ret = -EPERM; ++ goto bail; ++ } ++ } ++ + size = sizeof(struct ipa3_desc) * NUM_OF_DESC; + desc = kzalloc(size, GFP_KERNEL); + if (desc == NULL) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10234/1.patch b/Patches/Linux_CVEs/CVE-2016-10234/1.patch new file mode 100644 index 00000000..9b73a723 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10234/1.patch @@ -0,0 +1,287 @@ +From c7d7492c1e329fdeb28a7901c4cd634d41a996b1 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Mon, 31 Oct 2016 17:18:15 -0700 +Subject: msm: ipa: fix ioctl input param validation + +Fix input parameter validation in order to avoid +device crash because of incorrect parameter in IPA driver. + +Change-Id: Icbdb05aeb9211665420a872d3453dbbd24fd347b +CRs-Fixed: 1069060 +Acked-by: Ady Abraham +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa_flt.c | 36 +++++++++++++++--- + drivers/platform/msm/ipa/ipa_i.h | 2 +- + drivers/platform/msm/ipa/ipa_nat.c | 77 +++++++++++++++++++++++++++++++++++++- + drivers/platform/msm/ipa/ipa_rt.c | 26 +++++++++++-- + 4 files changed, 129 insertions(+), 12 deletions(-) + +diff --git a/drivers/platform/msm/ipa/ipa_flt.c b/drivers/platform/msm/ipa/ipa_flt.c +index f6ebd022..72342c2 100644 +--- a/drivers/platform/msm/ipa/ipa_flt.c ++++ b/drivers/platform/msm/ipa/ipa_flt.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -235,7 +235,7 @@ static int ipa_generate_flt_hw_rule(enum ipa_ip_type ip, + * @ip: the ip address family type + * @hdr_sz: header size + * +- * Returns: 0 on success, negative on failure ++ * Returns: size on success, negative on failure + * + * caller needs to hold any needed locks to ensure integrity + * +@@ -373,7 +373,12 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, + ((long)body & + IPA_FLT_ENTRY_MEMORY_ALLIGNMENT)); + } else { +- WARN_ON(tbl->sz == 0); ++ if (tbl->sz == 0) { ++ IPAERR("tbl size is 0\n"); ++ WARN_ON(1); ++ goto proc_err; ++ } ++ + /* allocate memory for the flt tbl */ + flt_tbl_mem.size = tbl->sz; + flt_tbl_mem.base = +@@ -460,7 +465,12 @@ static int ipa_generate_flt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, + ((long)body & + IPA_FLT_ENTRY_MEMORY_ALLIGNMENT)); + } else { +- WARN_ON(tbl->sz == 0); ++ if (tbl->sz == 0) { ++ IPAERR("tbl size is 0\n"); ++ WARN_ON(1); ++ goto proc_err; ++ } ++ + /* allocate memory for the flt tbl */ + flt_tbl_mem.size = tbl->sz; + flt_tbl_mem.base = +@@ -534,8 +544,15 @@ static int ipa_generate_flt_hw_tbl_v1_1(enum ipa_ip_type ip, + u8 *hdr; + u8 *body; + u8 *base; ++ int res; ++ ++ res = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); ++ if (res < 0) { ++ IPAERR("ipa_get_flt_hw_tbl_size failed %d\n", res); ++ return res; ++ } + +- mem->size = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); ++ mem->size = res; + mem->size = IPA_HW_TABLE_ALIGNMENT(mem->size); + + if (mem->size == 0) { +@@ -720,6 +737,7 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip, + u32 *entr; + u32 body_start_offset; + u32 hdr_top; ++ int res; + + if (ip == IPA_IP_v4) + body_start_offset = IPA_MEM_PART(apps_v4_flt_ofst) - +@@ -756,7 +774,13 @@ static int ipa_generate_flt_hw_tbl_v2(enum ipa_ip_type ip, + entr++; + } + +- mem->size = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); ++ res = ipa_get_flt_hw_tbl_size(ip, &hdr_sz); ++ if (res < 0) { ++ IPAERR("ipa_get_flt_hw_tbl_size failed %d\n", res); ++ goto body_err; ++ } ++ ++ mem->size = res; + mem->size -= hdr_sz; + mem->size = IPA_HW_TABLE_ALIGNMENT(mem->size); + +diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h +index f5bc437..adf6c0e 100644 +--- a/drivers/platform/msm/ipa/ipa_i.h ++++ b/drivers/platform/msm/ipa/ipa_i.h +@@ -129,7 +129,7 @@ + + #define IPA_HW_TABLE_ALIGNMENT(start_ofst) \ + (((start_ofst) + 127) & ~127) +-#define IPA_RT_FLT_HW_RULE_BUF_SIZE (128) ++#define IPA_RT_FLT_HW_RULE_BUF_SIZE (256) + + #define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT_BYTE 8 + #define IPA_HDR_PROC_CTX_TABLE_ALIGNMENT(start_ofst) \ +diff --git a/drivers/platform/msm/ipa/ipa_nat.c b/drivers/platform/msm/ipa/ipa_nat.c +index 299e5d1..b44de4f 100644 +--- a/drivers/platform/msm/ipa/ipa_nat.c ++++ b/drivers/platform/msm/ipa/ipa_nat.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -25,6 +25,16 @@ + #define IPA_NAT_SHARED_MEMORY 1 + #define IPA_NAT_TEMP_MEM_SIZE 128 + ++enum nat_table_type { ++ IPA_NAT_BASE_TBL = 0, ++ IPA_NAT_EXPN_TBL = 1, ++ IPA_NAT_INDX_TBL = 2, ++ IPA_NAT_INDEX_EXPN_TBL = 3, ++}; ++ ++#define NAT_TABLE_ENTRY_SIZE_BYTE 32 ++#define NAT_INTEX_TABLE_ENTRY_SIZE_BYTE 4 ++ + static int ipa_nat_vma_fault_remap( + struct vm_area_struct *vma, struct vm_fault *vmf) + { +@@ -561,6 +571,71 @@ int ipa_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) + ret = -EPERM; + goto bail; + } ++ ++ for (cnt = 0; cnt < dma->entries; cnt++) { ++ if (dma->dma[cnt].table_index >= 1) { ++ IPAERR("Invalid table index %d\n", ++ dma->dma[cnt].table_index); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ switch (dma->dma[cnt].base_addr) { ++ case IPA_NAT_BASE_TBL: ++ if (dma->dma[cnt].offset >= ++ (ipa_ctx->nat_mem.size_base_tables + 1) * ++ NAT_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_EXPN_TBL: ++ if (dma->dma[cnt].offset >= ++ ipa_ctx->nat_mem.size_expansion_tables * ++ NAT_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_INDX_TBL: ++ if (dma->dma[cnt].offset >= ++ (ipa_ctx->nat_mem.size_base_tables + 1) * ++ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ case IPA_NAT_INDEX_EXPN_TBL: ++ if (dma->dma[cnt].offset >= ++ ipa_ctx->nat_mem.size_expansion_tables * ++ NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { ++ IPAERR("Invalid offset %d\n", ++ dma->dma[cnt].offset); ++ ret = -EPERM; ++ goto bail; ++ } ++ ++ break; ++ ++ default: ++ IPAERR("Invalid base_addr %d\n", ++ dma->dma[cnt].base_addr); ++ ret = -EPERM; ++ goto bail; ++ } ++ } + size = sizeof(struct ipa_desc) * dma->entries; + desc = kzalloc(size, GFP_KERNEL); + if (desc == NULL) { +diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c +index 6e1e44f..47767cd 100644 +--- a/drivers/platform/msm/ipa/ipa_rt.c ++++ b/drivers/platform/msm/ipa/ipa_rt.c +@@ -189,7 +189,7 @@ int __ipa_generate_rt_hw_rule_v2_5(enum ipa_ip_type ip, + * @hdr_sz: header size + * @max_rt_idx: maximal index + * +- * Returns: 0 on success, negative on failure ++ * Returns: size on success, negative on failure + * + * caller needs to hold any needed locks to ensure integrity + * +@@ -318,7 +318,11 @@ static int ipa_generate_rt_hw_tbl_common(enum ipa_ip_type ip, u8 *base, u8 *hdr, + ((long)body & + IPA_RT_ENTRY_MEMORY_ALLIGNMENT)); + } else { +- WARN_ON(tbl->sz == 0); ++ if (tbl->sz == 0) { ++ IPAERR("cannot generate 0 size table\n"); ++ goto proc_err; ++ } ++ + /* allocate memory for the RT tbl */ + rt_tbl_mem.size = tbl->sz; + rt_tbl_mem.base = +@@ -391,8 +395,15 @@ static int ipa_generate_rt_hw_tbl_v1_1(enum ipa_ip_type ip, + u8 *base; + int max_rt_idx; + int i; ++ int res; + +- mem->size = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); ++ res = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); ++ if (res < 0) { ++ IPAERR("ipa_get_rt_hw_tbl_size failed %d\n", res); ++ goto error; ++ } ++ ++ mem->size = res; + mem->size = (mem->size + IPA_RT_TABLE_MEMORY_ALLIGNMENT) & + ~IPA_RT_TABLE_MEMORY_ALLIGNMENT; + +@@ -565,6 +576,7 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip, + int num_index; + u32 body_start_offset; + u32 apps_start_idx; ++ int res; + + if (ip == IPA_IP_v4) { + num_index = IPA_MEM_PART(v4_apps_rt_index_hi) - +@@ -594,7 +606,13 @@ static int ipa_generate_rt_hw_tbl_v2(enum ipa_ip_type ip, + entr++; + } + +- mem->size = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); ++ res = ipa_get_rt_hw_tbl_size(ip, &hdr_sz, &max_rt_idx); ++ if (res < 0) { ++ IPAERR("ipa_get_rt_hw_tbl_size failed %d\n", res); ++ goto base_err; ++ } ++ ++ mem->size = res; + mem->size -= hdr_sz; + mem->size = (mem->size + IPA_RT_TABLE_MEMORY_ALLIGNMENT) & + ~IPA_RT_TABLE_MEMORY_ALLIGNMENT; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10235/0.patch b/Patches/Linux_CVEs/CVE-2016-10235/0.patch new file mode 100644 index 00000000..2389d8b9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10235/0.patch @@ -0,0 +1,35 @@ +From 5bb0059243515ecdac138cfdb4cee7259bbd0bbc Mon Sep 17 00:00:00 2001 +From: Subrat Dash +Date: Wed, 3 Aug 2016 16:47:39 +0530 +Subject: qcacld-2.0: Fix VHT-80 IBSS stops beaconing + +A STA entry is created for each peer joining +the network to take care of the peer specific +capabilities. + +The VDEV need not be reconfigured for IBSS peer +with different channel width joining the network. + +Change-Id: Iec6ec5d2b510b84538f4e5300b3f1c5cc63b334d +CRs-Fixed: 1046409 +--- + CORE/MAC/src/pe/sch/schBeaconProcess.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CORE/MAC/src/pe/sch/schBeaconProcess.c b/CORE/MAC/src/pe/sch/schBeaconProcess.c +index a28f2be..4ed8aea 100644 +--- a/CORE/MAC/src/pe/sch/schBeaconProcess.c ++++ b/CORE/MAC/src/pe/sch/schBeaconProcess.c +@@ -465,7 +465,8 @@ static void __schBeaconProcessForSession( tpAniSirGlobal pMac, + sendProbeReq = TRUE; + } + +- if ( psessionEntry->htCapability && pBeacon->HTInfo.present ) ++ if (psessionEntry->htCapability && pBeacon->HTInfo.present && ++ (!LIM_IS_IBSS_ROLE(psessionEntry))) + { + limUpdateStaRunTimeHTSwitchChnlParams( pMac, &pBeacon->HTInfo, bssIdx,psessionEntry); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10235/1.patch b/Patches/Linux_CVEs/CVE-2016-10235/1.patch new file mode 100644 index 00000000..14614ba2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10235/1.patch @@ -0,0 +1,35 @@ +From a8b3b4ff293108a3aef0ea1ec1760f3d406d1e36 Mon Sep 17 00:00:00 2001 +From: Subrat Dash +Date: Wed, 14 Dec 2016 14:35:24 +0530 +Subject: prima: Fix VHT-80 IBSS stops beaconing + +A STA entry is created for each peer joining +the network to take care of the peer specific +capabilities. + +The VDEV need not be reconfigured for IBSS peer +with different channel width joining the network. + +Change-Id: Iec6ec5d2b510b84538f4e5300b3f1c5cc63b334d +CRs-Fixed: 1046409 +--- + CORE/MAC/src/pe/sch/schBeaconProcess.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CORE/MAC/src/pe/sch/schBeaconProcess.c b/CORE/MAC/src/pe/sch/schBeaconProcess.c +index 8d3483b..8d32309 100644 +--- a/CORE/MAC/src/pe/sch/schBeaconProcess.c ++++ b/CORE/MAC/src/pe/sch/schBeaconProcess.c +@@ -469,7 +469,8 @@ static void __schBeaconProcessForSession( tpAniSirGlobal pMac, + sendProbeReq = TRUE; + } + +- if ( psessionEntry->htCapability && pBeacon->HTInfo.present ) ++ if ( psessionEntry->htCapability && pBeacon->HTInfo.present && ++ (!LIM_IS_IBSS_ROLE(psessionEntry))) + { + limUpdateStaRunTimeHTSwitchChnlParams( pMac, &pBeacon->HTInfo, bssIdx,psessionEntry); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10236/0.patch b/Patches/Linux_CVEs/CVE-2016-10236/0.patch new file mode 100644 index 00000000..905e786c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10236/0.patch @@ -0,0 +1,41 @@ +From b8199c2b852f1e23c988e10b8fbb8d34c98b4a1c Mon Sep 17 00:00:00 2001 +From: Arumuga Durai A +Date: Tue, 27 Dec 2016 19:50:06 +0530 +Subject: USB: gadget: mbim: Avoid copying uninitialized data to userspace + +A race condition bug in function 'mbim_bind_config' allows to +change 'mbim->xport' type to invalid value. This allows +mbim_ioctl() to copy the uninitialized data to userspace. Fix +this by avoiding copy_to_user() call when transport type is invalid. + +Change-Id: If8e8b6d4e2c347e1aff529bed0a798128eaea07c +CRs-Fixed: 1102418 +Signed-off-by: Arumuga Durai A +--- + drivers/usb/gadget/function/f_mbim.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/function/f_mbim.c b/drivers/usb/gadget/function/f_mbim.c +index 717ee23..84c0066 100644 +--- a/drivers/usb/gadget/function/f_mbim.c ++++ b/drivers/usb/gadget/function/f_mbim.c +@@ -2030,7 +2030,7 @@ static long mbim_ioctl(struct file *fp, unsigned cmd, unsigned long arg) + default: + ret = -ENODEV; + pr_err("unknown transport\n"); +- break; ++ goto fail; + } + + ret = copy_to_user((void __user *)arg, &info, +@@ -2046,6 +2046,7 @@ static long mbim_ioctl(struct file *fp, unsigned cmd, unsigned long arg) + ret = -EINVAL; + } + ++fail: + mbim_unlock(&mbim->ioctl_excl); + + return ret; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10283/0.patch b/Patches/Linux_CVEs/CVE-2016-10283/0.patch new file mode 100644 index 00000000..83db6b71 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10283/0.patch @@ -0,0 +1,42 @@ +From 93863644b4547324309613361d70ad9dc91f8dfd Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Tue, 14 Feb 2017 16:00:57 +0530 +Subject: qcacld-2.0: Trim operation classes to max supported in change station + +Operation classes supported can be controlled by user, which can +be sent greater than the max supported operations. This results +in stack overflow in change station command. + +Add check to validate operations supported param given by user +and if it exceeds max supported value, set it to max supported +value. + +CRs-Fixed: 2002052 +Change-Id: Idd3a35e38b091546a17d7ec6329f19429e5c289c +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 8fc43a7..f82f258 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -13809,6 +13809,15 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, + "%s: After removing duplcates StaParams.supported_channels_len: %d", + __func__, StaParams.supported_channels_len); + } ++ if (params->supported_oper_classes_len > ++ SIR_MAC_MAX_SUPP_OPER_CLASSES) { ++ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ++ "received oper classes:%d, resetting it to max supported %d", ++ params->supported_oper_classes_len, ++ SIR_MAC_MAX_SUPP_OPER_CLASSES); ++ params->supported_oper_classes_len = ++ SIR_MAC_MAX_SUPP_OPER_CLASSES; ++ } + vos_mem_copy(StaParams.supported_oper_classes, + params->supported_oper_classes, + params->supported_oper_classes_len); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10283/1.patch b/Patches/Linux_CVEs/CVE-2016-10283/1.patch new file mode 100644 index 00000000..82e47015 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10283/1.patch @@ -0,0 +1,44 @@ +From 5842cb5d592b7a4b89f2459ba71f78d860eb6267 Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Wed, 5 Apr 2017 13:18:26 +0530 +Subject: wlan: Trim operation classes to max supported in change station + +qcacld-2.0 to prima propagation. + +Operation classes supported can be controlled by user, which can +be sent greater than the max supported operations. This results +in stack overflow in change station command. + +Add check to validate operations supported param given by user +and if it exceeds max supported value, set it to max supported +value. + +CRs-Fixed: 2002052 +Change-Id: Idd3a35e38b091546a17d7ec6329f19429e5c289c +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 66c732e..5a35945 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -11611,6 +11611,15 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, + } + StaParams.supported_channels_len = j; + } ++ if (params->supported_oper_classes_len > ++ SIR_MAC_MAX_SUPP_OPER_CLASSES) { ++ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ++ "received oper classes:%d, resetting it to max supported %d", ++ params->supported_oper_classes_len, ++ SIR_MAC_MAX_SUPP_OPER_CLASSES); ++ params->supported_oper_classes_len = ++ SIR_MAC_MAX_SUPP_OPER_CLASSES; ++ } + vos_mem_copy(StaParams.supported_oper_classes, + params->supported_oper_classes, + params->supported_oper_classes_len); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10285/0.patch b/Patches/Linux_CVEs/CVE-2016-10285/0.patch new file mode 100644 index 00000000..cc089c19 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10285/0.patch @@ -0,0 +1,143 @@ +From 67dfd3a65336e0b3f55ee83d6312321dc5f2a6f9 Mon Sep 17 00:00:00 2001 +From: Padmanabhan Komanduru +Date: Wed, 25 Jan 2017 16:38:48 +0530 +Subject: msm: mdss: handle synchronization issues during DSI debugfs + read/write + +Handle race condition during read/write operations to DSI debugfs nodes +related to DSI panel ON/OFF commands. + +Change-Id: I29c4ad74bf21d4cb5362565e902a682fe7263147 +Signed-off-by: Padmanabhan Komanduru +--- + drivers/video/msm/mdss/mdss_dsi.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c +index 885d132..e6d9edc 100644 +--- a/drivers/video/msm/mdss/mdss_dsi.c ++++ b/drivers/video/msm/mdss/mdss_dsi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -625,6 +625,7 @@ struct buf_data { + char *string_buf; /* cmd buf as string, 3 bytes per number */ + int sblen; /* string buffer length */ + int sync_flag; ++ struct mutex dbg_mutex; /* mutex to synchronize read/write/flush */ + }; + + struct mdss_dsi_debugfs_info { +@@ -714,6 +715,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, + char *bp; + ssize_t ret = 0; + ++ mutex_lock(&pcmds->dbg_mutex); + if (*ppos == 0) { + kfree(pcmds->string_buf); + pcmds->string_buf = NULL; +@@ -732,6 +734,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, + buffer = kmalloc(bsize, GFP_KERNEL); + if (!buffer) { + pr_err("%s: Failed to allocate memory\n", __func__); ++ mutex_unlock(&pcmds->dbg_mutex); + return -ENOMEM; + } + +@@ -767,10 +770,12 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, + kfree(pcmds->string_buf); + pcmds->string_buf = NULL; + pcmds->sblen = 0; ++ mutex_unlock(&pcmds->dbg_mutex); + return 0; /* the end */ + } + ret = simple_read_from_buffer(buf, count, ppos, pcmds->string_buf, + pcmds->sblen); ++ mutex_unlock(&pcmds->dbg_mutex); + return ret; + } + +@@ -782,6 +787,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, + int blen = 0; + char *string_buf; + ++ mutex_lock(&pcmds->dbg_mutex); + if (*ppos == 0) { + kfree(pcmds->string_buf); + pcmds->string_buf = NULL; +@@ -793,6 +799,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, + string_buf = krealloc(pcmds->string_buf, blen + 1, GFP_KERNEL); + if (!string_buf) { + pr_err("%s: Failed to allocate memory\n", __func__); ++ mutex_unlock(&pcmds->dbg_mutex); + return -ENOMEM; + } + +@@ -802,6 +809,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, + string_buf[blen] = '\0'; + pcmds->string_buf = string_buf; + pcmds->sblen = blen; ++ mutex_unlock(&pcmds->dbg_mutex); + return ret; + } + +@@ -812,8 +820,12 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + char *buf, *bufp, *bp; + struct dsi_ctrl_hdr *dchdr; + +- if (!pcmds->string_buf) ++ mutex_lock(&pcmds->dbg_mutex); ++ ++ if (!pcmds->string_buf) { ++ mutex_unlock(&pcmds->dbg_mutex); + return 0; ++ } + + /* + * Allocate memory for command buffer +@@ -826,6 +838,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + kfree(pcmds->string_buf); + pcmds->string_buf = NULL; + pcmds->sblen = 0; ++ mutex_unlock(&pcmds->dbg_mutex); + return -ENOMEM; + } + +@@ -850,6 +863,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + pr_err("%s: dtsi cmd=%x error, len=%d\n", + __func__, dchdr->dtype, dchdr->dlen); + kfree(buf); ++ mutex_unlock(&pcmds->dbg_mutex); + return -EINVAL; + } + bp += sizeof(*dchdr); +@@ -861,6 +875,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + pr_err("%s: dcs_cmd=%x len=%d error!\n", __func__, + bp[0], len); + kfree(buf); ++ mutex_unlock(&pcmds->dbg_mutex); + return -EINVAL; + } + +@@ -873,6 +888,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + pcmds->buf = buf; + pcmds->blen = blen; + } ++ mutex_unlock(&pcmds->dbg_mutex); + return 0; + } + +@@ -887,6 +903,7 @@ struct dentry *dsi_debugfs_create_dcs_cmd(const char *name, umode_t mode, + struct dentry *parent, struct buf_data *cmd, + struct dsi_panel_cmds ctrl_cmds) + { ++ mutex_init(&cmd->dbg_mutex); + cmd->buf = ctrl_cmds.buf; + cmd->blen = ctrl_cmds.blen; + cmd->string_buf = NULL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10286/0.patch b/Patches/Linux_CVEs/CVE-2016-10286/0.patch new file mode 100644 index 00000000..678c2dec --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10286/0.patch @@ -0,0 +1,50 @@ +From 5d30a3d0dc04916ddfb972bfc52f8e636642f999 Mon Sep 17 00:00:00 2001 +From: Veera Sundaram Sankaran +Date: Fri, 11 Nov 2016 12:01:34 -0800 +Subject: msm: mdss: avoid removing wrong multirect on validate failures + +During atomic commit - validate failures, the newly allocated +pipes and pipes taken from the destroy list are cleaned up. +Currently pipe ndx is checked which can lead to cleaning up +the already in use multirect instead of the rect allocated +in the current validate. Add checks to include checking based +on multirect to avoid such cases. + +Change-Id: I7f8fb6630314cdc523490e28d90dd3776bdfeada +Signed-off-by: Veera Sundaram Sankaran +--- + drivers/video/fbdev/msm/mdss_mdp_layer.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c +index 20fcc26..036e4e3 100644 +--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c ++++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c +@@ -2470,16 +2470,20 @@ validate_exit: + mutex_lock(&mdp5_data->list_lock); + list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) { + if (IS_ERR_VALUE(ret)) { +- if ((pipe->ndx & rec_release_ndx[0]) || +- (pipe->ndx & rec_release_ndx[1])) { ++ if (((pipe->ndx & rec_release_ndx[0]) && ++ (pipe->multirect.num == 0)) || ++ ((pipe->ndx & rec_release_ndx[1]) && ++ (pipe->multirect.num == 1))) { + mdss_mdp_smp_unreserve(pipe); + pipe->params_changed = 0; + pipe->dirty = true; + if (!list_empty(&pipe->list)) + list_del_init(&pipe->list); + mdss_mdp_pipe_destroy(pipe); +- } else if ((pipe->ndx & rec_destroy_ndx[0]) || +- (pipe->ndx & rec_destroy_ndx[1])) { ++ } else if (((pipe->ndx & rec_destroy_ndx[0]) && ++ (pipe->multirect.num == 0)) || ++ ((pipe->ndx & rec_destroy_ndx[1]) && ++ (pipe->multirect.num == 1))) { + /* + * cleanup/destroy list pipes should move back + * to destroy list. Next/current kickoff cycle +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10287/0.patch b/Patches/Linux_CVEs/CVE-2016-10287/0.patch new file mode 100644 index 00000000..5b96ada4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10287/0.patch @@ -0,0 +1,48 @@ +From 937bc9e644180e258c68662095861803f7ba4ded Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Mon, 23 Jan 2017 13:15:58 -0800 +Subject: ASoC: msm: qdsp6v2: completely deallocate on cal block creation + failure + +Completely deallocate the cal block if creation fails to ensure no +memory leaks are present. + +CRs-Fixed: 1112751 +Change-Id: I76916c8b3f7e8e9b864dc39dab96f7d330774473 +Signed-off-by: Siena Richard +--- + sound/soc/msm/qdsp6v2/audio_cal_utils.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c +index 75af648..b54cde4 100644 +--- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c ++++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c +@@ -607,7 +607,6 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, + } + + INIT_LIST_HEAD(&cal_block->list); +- list_add_tail(&cal_block->list, &cal_type->cal_blocks); + + cal_block->map_data.ion_map_handle = basic_cal->cal_data.mem_handle; + if (basic_cal->cal_data.mem_handle > 0) { +@@ -639,6 +638,7 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, + goto err; + } + cal_block->buffer_number = basic_cal->cal_hdr.buffer_number; ++ list_add_tail(&cal_block->list, &cal_type->cal_blocks); + pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pK!\n", + __func__, cal_type->info.reg.cal_type, + cal_block->buffer_number, +@@ -648,6 +648,8 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, + done: + return cal_block; + err: ++ kfree(cal_block->cal_info); ++ kfree(cal_block->client_info); + kfree(cal_block); + cal_block = NULL; + return cal_block; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10288/0.patch b/Patches/Linux_CVEs/CVE-2016-10288/0.patch new file mode 100644 index 00000000..a4294fff --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10288/0.patch @@ -0,0 +1,206 @@ +From db2cdc95204bc404f03613d5dd7002251fb33660 Mon Sep 17 00:00:00 2001 +From: Ankit Sharma +Date: Thu, 9 Feb 2017 16:23:09 +0530 +Subject: leds: qpnp-flash: Fix Use-after-free(UAF) for debugfs + +Fix UAF where two threads can open and close the same file. Second +open will cause the private data for the first file to be overwritten. +When the first file is closed and the private data is freed, this makes +the now-shared private data OOB for the second thread. + +CRs-Fixed: 1109763 +Change-Id: I1c4618d5be99e140abf0f3ea0d7f485897db5ab2 +Signed-off-by: Ankit Sharma +--- + drivers/leds/leds-qpnp-flash.c | 82 +++++++++++++++++++++++++++--------------- + 1 file changed, 54 insertions(+), 28 deletions(-) + +diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c +index 56ba8f5..ec4b4e7 100644 +--- a/drivers/leds/leds-qpnp-flash.c ++++ b/drivers/leds/leds-qpnp-flash.c +@@ -225,11 +225,13 @@ struct flash_led_platform_data { + }; + + struct qpnp_flash_led_buffer { +- struct mutex debugfs_lock; /* Prevent thread concurrency */ +- size_t rpos; +- size_t wpos; +- size_t len; +- char data[0]; ++ struct mutex debugfs_lock; /* Prevent thread concurrency */ ++ size_t rpos; ++ size_t wpos; ++ size_t len; ++ struct qpnp_flash_led *led; ++ u32 buffer_cnt; ++ char data[0]; + }; + + /* +@@ -247,10 +249,8 @@ struct qpnp_flash_led { + struct workqueue_struct *ordered_workq; + struct qpnp_vadc_chip *vadc_dev; + struct mutex flash_led_lock; +- struct qpnp_flash_led_buffer *log; + struct dentry *dbgfs_root; + int num_leds; +- u32 buffer_cnt; + u16 base; + u16 current_addr; + u16 current2_addr; +@@ -282,10 +282,10 @@ static int flash_led_dbgfs_file_open(struct qpnp_flash_led *led, + log->wpos = 0; + log->len = logbufsize - sizeof(*log); + mutex_init(&log->debugfs_lock); +- led->log = log; ++ log->led = led; + +- led->buffer_cnt = 1; +- file->private_data = led; ++ log->buffer_cnt = 1; ++ file->private_data = log; + + return 0; + } +@@ -299,12 +299,12 @@ static int flash_led_dfs_open(struct inode *inode, struct file *file) + + static int flash_led_dfs_close(struct inode *inode, struct file *file) + { +- struct qpnp_flash_led *led = file->private_data; ++ struct qpnp_flash_led_buffer *log = file->private_data; + +- if (led && led->log) { ++ if (log) { + file->private_data = NULL; +- mutex_destroy(&led->log->debugfs_lock); +- kfree(led->log); ++ mutex_destroy(&log->debugfs_lock); ++ kfree(log); + } + + return 0; +@@ -333,15 +333,21 @@ static int print_to_log(struct qpnp_flash_led_buffer *log, + + static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + size_t count, loff_t *ppos) { +- struct qpnp_flash_led *led = fp->private_data; +- struct qpnp_flash_led_buffer *log = led->log; ++ struct qpnp_flash_led_buffer *log = fp->private_data; ++ struct qpnp_flash_led *led; + u8 val; + int rc = 0; + size_t len; + size_t ret; + ++ if (!log) { ++ pr_err("error: file private data is NULL\n"); ++ return -EFAULT; ++ } ++ led = log->led; ++ + mutex_lock(&log->debugfs_lock); +- if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || ++ if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || + ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) + goto unlock_mutex; + +@@ -353,7 +359,7 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + INT_LATCHED_STS(led->base), rc); + goto unlock_mutex; + } +- led->buffer_cnt--; ++ log->buffer_cnt--; + + rc = print_to_log(log, "0x%05X ", INT_LATCHED_STS(led->base)); + if (rc == 0) +@@ -388,18 +394,24 @@ unlock_mutex: + + static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, + size_t count, loff_t *ppos) { +- struct qpnp_flash_led *led = fp->private_data; +- struct qpnp_flash_led_buffer *log = led->log; ++ struct qpnp_flash_led_buffer *log = fp->private_data; ++ struct qpnp_flash_led *led; + int rc = 0; + size_t len; + size_t ret; + ++ if (!log) { ++ pr_err("error: file private data is NULL\n"); ++ return -EFAULT; ++ } ++ led = log->led; ++ + mutex_lock(&log->debugfs_lock); +- if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || ++ if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || + ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) + goto unlock_mutex; + +- led->buffer_cnt--; ++ log->buffer_cnt--; + + rc = print_to_log(log, "0x%05X ", FLASH_LED_FAULT_STATUS(led->base)); + if (rc == 0) +@@ -441,10 +453,17 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, + int data; + size_t ret = 0; + +- struct qpnp_flash_led *led = file->private_data; ++ struct qpnp_flash_led_buffer *log = file->private_data; ++ struct qpnp_flash_led *led; + char *kbuf; + +- mutex_lock(&led->log->debugfs_lock); ++ if (!log) { ++ pr_err("error: file private data is NULL\n"); ++ return -EFAULT; ++ } ++ led = log->led; ++ ++ mutex_lock(&log->debugfs_lock); + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; +@@ -479,7 +498,7 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, + free_buf: + kfree(kbuf); + unlock_mutex: +- mutex_unlock(&led->log->debugfs_lock); ++ mutex_unlock(&log->debugfs_lock); + return ret; + } + +@@ -491,10 +510,17 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, + int cnt = 0; + int data; + size_t ret = 0; +- struct qpnp_flash_led *led = file->private_data; ++ struct qpnp_flash_led_buffer *log = file->private_data; ++ struct qpnp_flash_led *led; + char *kbuf; + +- mutex_lock(&led->log->debugfs_lock); ++ if (!log) { ++ pr_err("error: file private data is NULL\n"); ++ return -EFAULT; ++ } ++ led = log->led; ++ ++ mutex_lock(&log->debugfs_lock); + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; +@@ -528,7 +554,7 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, + free_buf: + kfree(kbuf); + unlock_mutex: +- mutex_unlock(&led->log->debugfs_lock); ++ mutex_unlock(&log->debugfs_lock); + return ret; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10289/0.patch b/Patches/Linux_CVEs/CVE-2016-10289/0.patch new file mode 100644 index 00000000..b8aa3cce --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10289/0.patch @@ -0,0 +1,80 @@ +From a604e6f3889ccc343857532b63dea27603381816 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Tue, 31 Jan 2017 12:07:10 -0800 +Subject: crypto: msm: check length before copying to buf in _debug_stats_read + +Make sure that `len` is not larger than `count` before copying data +to userspace `buf` in _debug_stats_read(). + +Change-Id: Iafb7cfa3828653f8c28183c812797c3d9a183da1 +Signed-off-by: Zhen Kong +--- + drivers/crypto/msm/ota_crypto.c | 6 +++--- + drivers/crypto/msm/qcedev.c | 4 ++-- + drivers/crypto/msm/qcrypto.c | 6 +++--- + 3 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c +index 8aa0d04..416623f 100644 +--- a/drivers/crypto/msm/ota_crypto.c ++++ b/drivers/crypto/msm/ota_crypto.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2017, The 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 +@@ -884,8 +884,8 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, + int len; + + len = _disp_stats(); +- +- rc = simple_read_from_buffer((void __user *) buf, len, ++ if (len <= count) ++ rc = simple_read_from_buffer((void __user *) buf, len, + ppos, (void *) _debug_read_buf, len); + + return rc; +diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c +index a629c62..5ce87a6e 100644 +--- a/drivers/crypto/msm/qcedev.c ++++ b/drivers/crypto/msm/qcedev.c +@@ -1987,9 +1987,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, + + len = _disp_stats(qcedev); + +- rc = simple_read_from_buffer((void __user *) buf, len, ++ if (len <= count) ++ rc = simple_read_from_buffer((void __user *) buf, len, + ppos, (void *) _debug_read_buf, len); +- + return rc; + } + +diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c +index 3324c9d..dd4443f 100644 +--- a/drivers/crypto/msm/qcrypto.c ++++ b/drivers/crypto/msm/qcrypto.c +@@ -1,6 +1,6 @@ + /* Qualcomm Crypto driver + * +- * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2010-2017, The 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 +@@ -5742,9 +5742,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, + + len = _disp_stats(qcrypto); + +- rc = simple_read_from_buffer((void __user *) buf, len, ++ if (len <= count) ++ rc = simple_read_from_buffer((void __user *) buf, len, + ppos, (void *) _debug_read_buf, len); +- + return rc; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10290/0.patch b/Patches/Linux_CVEs/CVE-2016-10290/0.patch new file mode 100644 index 00000000..ac233c61 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10290/0.patch @@ -0,0 +1,88 @@ +From a5e46d8635a2e28463b365aacdeab6750abd0d49 Mon Sep 17 00:00:00 2001 +From: Sahitya Tummala +Date: Fri, 3 Feb 2017 13:24:19 +0530 +Subject: uio: fix potential use after free issue when accessing debug_buffer + +The variable debug_buffer is a global variable which is allocated +and free'd when open/close is called on debugfs file - +"/sys/kernel/debug/rmt_storage/info". The current code doesn't +have locks to handle concurrent accesses to the above file. +This results into use after free issue when debug_buffer is +accessed by two threads at the same time. Fix this by adding +a mutex lock to protect this global variable. + +Change-Id: I6bc3f0ae2d7fca3ca9fe8561612f5863b6c3268a +Signed-off-by: Sahitya Tummala +--- + drivers/uio/msm_sharedmem/sharedmem_qmi.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/uio/msm_sharedmem/sharedmem_qmi.c b/drivers/uio/msm_sharedmem/sharedmem_qmi.c +index 48fb17e..fd95dee 100644 +--- a/drivers/uio/msm_sharedmem/sharedmem_qmi.c ++++ b/drivers/uio/msm_sharedmem/sharedmem_qmi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2015, 2017, The 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 +@@ -223,6 +223,7 @@ static int sharedmem_qmi_req_cb(struct qmi_handle *handle, void *conn_h, + #define DEBUG_BUF_SIZE (2048) + static char *debug_buffer; + static u32 debug_data_size; ++static struct mutex dbg_buf_lock; /* mutex for debug_buffer */ + + static ssize_t debug_read(struct file *file, char __user *buf, + size_t count, loff_t *file_pos) +@@ -279,21 +280,29 @@ static int debug_open(struct inode *inode, struct file *file) + { + u32 buffer_size; + +- if (debug_buffer != NULL) ++ mutex_lock(&dbg_buf_lock); ++ if (debug_buffer != NULL) { ++ mutex_unlock(&dbg_buf_lock); + return -EBUSY; ++ } + buffer_size = DEBUG_BUF_SIZE; + debug_buffer = kzalloc(buffer_size, GFP_KERNEL); +- if (debug_buffer == NULL) ++ if (debug_buffer == NULL) { ++ mutex_unlock(&dbg_buf_lock); + return -ENOMEM; ++ } + debug_data_size = fill_debug_info(debug_buffer, buffer_size); ++ mutex_unlock(&dbg_buf_lock); + return 0; + } + + static int debug_close(struct inode *inode, struct file *file) + { ++ mutex_lock(&dbg_buf_lock); + kfree(debug_buffer); + debug_buffer = NULL; + debug_data_size = 0; ++ mutex_unlock(&dbg_buf_lock); + return 0; + } + +@@ -324,6 +333,7 @@ static void debugfs_init(void) + { + struct dentry *f_ent; + ++ mutex_init(&dbg_buf_lock); + dir_ent = debugfs_create_dir("rmt_storage", NULL); + if (IS_ERR(dir_ent)) { + pr_err("Failed to create debug_fs directory\n"); +@@ -352,6 +362,7 @@ static void debugfs_init(void) + static void debugfs_exit(void) + { + debugfs_remove_recursive(dir_ent); ++ mutex_destroy(&dbg_buf_lock); + } + + static void sharedmem_qmi_svc_recv_msg(struct work_struct *work) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10291/0.patch b/Patches/Linux_CVEs/CVE-2016-10291/0.patch new file mode 100644 index 00000000..aaa8a0ff --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10291/0.patch @@ -0,0 +1,74 @@ +From a225074c0494ca8125ca0ac2f9ebc8a2bd3612de Mon Sep 17 00:00:00 2001 +From: Dilip Kota +Date: Mon, 21 Mar 2016 11:28:51 +0530 +Subject: slim-msm: Synchronize SSR callbacks + +Subsystem will restart within short timeframe. +Synchronise subsytem up/down callback notifications +to avoid functionality failures. +Use mutex locks to achieve synchronization. + +Change-Id: I5881c7d468507bb8402a2e9f8178b9c31e57e8a5 +Signed-off-by: Dilip Kota +--- + drivers/slimbus/slim-msm-ngd.c | 5 +++++ + drivers/slimbus/slim-msm.h | 3 ++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c +index 3684984..1328e76 100644 +--- a/drivers/slimbus/slim-msm-ngd.c ++++ b/drivers/slimbus/slim-msm-ngd.c +@@ -1449,11 +1449,13 @@ static void ngd_adsp_down(struct msm_slim_ctrl *dev) + struct slim_controller *ctrl = &dev->ctrl; + struct slim_device *sbdev; + ++ mutex_lock(&dev->ssr_lock); + ngd_slim_enable(dev, false); + /* device up should be called again after SSR */ + list_for_each_entry(sbdev, &ctrl->devs, dev_list) + slim_report_absent(sbdev); + SLIM_INFO(dev, "SLIM ADSP SSR (DOWN) done\n"); ++ mutex_unlock(&dev->ssr_lock); + } + + static void ngd_adsp_up(struct work_struct *work) +@@ -1462,7 +1464,9 @@ static void ngd_adsp_up(struct work_struct *work) + container_of(work, struct msm_slim_qmi, ssr_up); + struct msm_slim_ctrl *dev = + container_of(qmi, struct msm_slim_ctrl, qmi); ++ mutex_lock(&dev->ssr_lock); + ngd_slim_enable(dev, true); ++ mutex_unlock(&dev->ssr_lock); + } + + static ssize_t show_mask(struct device *device, struct device_attribute *attr, +@@ -1626,6 +1630,7 @@ static int ngd_slim_probe(struct platform_device *pdev) + init_completion(&dev->reconf); + init_completion(&dev->ctrl_up); + mutex_init(&dev->tx_lock); ++ mutex_init(&dev->ssr_lock); + spin_lock_init(&dev->tx_buf_lock); + spin_lock_init(&dev->rx_lock); + dev->ee = 1; +diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h +index 86d2606..7859d1e 100644 +--- a/drivers/slimbus/slim-msm.h ++++ b/drivers/slimbus/slim-msm.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2016, The 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 +@@ -284,6 +284,7 @@ struct msm_slim_ctrl { + struct clk *rclk; + struct clk *hclk; + struct mutex tx_lock; ++ struct mutex ssr_lock; + spinlock_t tx_buf_lock; + u8 pgdla; + enum msm_slim_msgq use_rx_msgqs; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10293/0.patch b/Patches/Linux_CVEs/CVE-2016-10293/0.patch new file mode 100644 index 00000000..04ca3e4c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10293/0.patch @@ -0,0 +1,184 @@ +From 2469d5374745a2228f774adbca6fb95a79b9047f Mon Sep 17 00:00:00 2001 +From: Yang Xu +Date: Thu, 29 Oct 2015 17:46:15 +0800 +Subject: msm: mdss: Add debugfs support for panel command data type + +Register debugfs node to read from and write to the panel command +data type. The default data type is DCS_LONG_WRITE 0x39. + +Give following command in adb shell to read panel register: + cat /sys/kernel/debug/mdp/panel_cmd_data_type +To write panel command data type: + echo "command_data_type" > + /sys/kernel/debug/mdp/panel_cmd_data_type + +Change-Id: I6dbe5bccb3142e93400825eddf7f05180acfc710 +Signed-off-by: Yang Xu +--- + drivers/video/msm/mdss/mdss_debug.c | 73 ++++++++++++++++++++++--------------- + drivers/video/msm/mdss/mdss_debug.h | 3 +- + 2 files changed, 46 insertions(+), 30 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c +index eaeccac..13d2b16 100644 +--- a/drivers/video/msm/mdss/mdss_debug.c ++++ b/drivers/video/msm/mdss/mdss_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2009-2017, The 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 +@@ -124,32 +124,22 @@ static ssize_t panel_debug_base_reg_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) + { + struct mdss_debug_base *dbg = file->private_data; +- +- u32 cnt, tmp, i; +- u32 len = 0; + char buf[PANEL_TX_MAX_BUF] = {0x0}; +- char *p = NULL; + char reg[PANEL_TX_MAX_BUF] = {0x0}; ++ u32 len = 0, step = 0, value = 0; ++ char *bufp; + + struct mdss_data_type *mdata = mdss_res; +- struct mdss_mdp_ctl *ctl = mdata->ctl_off + 0; +- struct mdss_panel_data *panel_data = ctl->panel_data; +- struct mdss_dsi_ctrl_pdata *ctrl_pdata = container_of(panel_data, +- struct mdss_dsi_ctrl_pdata, panel_data); +- ++ struct mdss_mdp_ctl *ctl; ++ struct mdss_dsi_ctrl_pdata *ctrl_pdata; + struct dsi_cmd_desc dsi_write_cmd = { +- {DTYPE_GEN_LWRITE, 1, 0, 0, 0, 0/*len*/}, reg}; ++ {0/*data type*/, 1, 0, 0, 0, 0/* len */}, reg}; + struct dcs_cmd_req cmdreq; + +- cmdreq.cmds = &dsi_write_cmd; +- cmdreq.cmds_cnt = 1; +- cmdreq.flags = CMD_REQ_COMMIT; +- cmdreq.rlen = 0; +- cmdreq.cb = NULL; +- + if (!dbg || !mdata) + return -ENODEV; + ++ /* get command string from user */ + if (count >= sizeof(buf)) + return -EFAULT; + +@@ -158,26 +148,38 @@ static ssize_t panel_debug_base_reg_write(struct file *file, + + buf[count] = 0; /* end of string */ + +- len = count / 3; +- ++ bufp = buf; ++ while (sscanf(bufp, "%x%n", &value, &step) > 0) { ++ reg[len++] = value; ++ if (len >= PANEL_TX_MAX_BUF) { ++ pr_err("wrong input reg len\n"); ++ return -EFAULT; ++ } ++ bufp += step; ++ } + if (len < PANEL_CMD_MIN_TX_COUNT) { + pr_err("wrong input reg len\n"); + return -EFAULT; + } + +- for (i = 0; i < len; i++) { +- p = buf + i * 3; +- p[2] = 0; +- pr_debug("p[%d] = %p:%s\n", i, p, p); +- cnt = sscanf(p, "%x", &tmp); +- reg[i] = tmp; +- pr_debug("reg[%d] = %x\n", i, (int)reg[i]); +- } ++ /* put command to cmdlist */ ++ dsi_write_cmd.dchdr.dtype = dbg->cmd_data_type; ++ dsi_write_cmd.dchdr.dlen = len; ++ dsi_write_cmd.payload = reg; ++ ++ cmdreq.cmds = &dsi_write_cmd; ++ cmdreq.cmds_cnt = 1; ++ cmdreq.flags = CMD_REQ_COMMIT; ++ cmdreq.rlen = 0; ++ cmdreq.cb = NULL; ++ ++ ctl = mdata->ctl_off + 0; ++ ctrl_pdata = container_of(ctl->panel_data, ++ struct mdss_dsi_ctrl_pdata, panel_data); + + if (mdata->debug_inf.debug_enable_clock) + mdata->debug_inf.debug_enable_clock(1); + +- dsi_write_cmd.dchdr.dlen = len; + mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); + + if (mdata->debug_inf.debug_enable_clock) +@@ -262,7 +264,7 @@ int panel_debug_register_base(const char *name, void __iomem *base, + struct mdss_data_type *mdata = mdss_res; + struct mdss_debug_data *mdd; + struct mdss_debug_base *dbg; +- struct dentry *ent_off, *ent_reg; ++ struct dentry *ent_off, *ent_reg, *ent_type; + char dn[PANEL_DATA_NODE_LEN] = ""; + int prefix_len = 0; + +@@ -279,10 +281,20 @@ int panel_debug_register_base(const char *name, void __iomem *base, + dbg->max_offset = max_offset; + dbg->off = 0x0a; + dbg->cnt = 0x01; ++ dbg->cmd_data_type = DTYPE_DCS_LWRITE; + + if (name) + prefix_len = snprintf(dn, sizeof(dn), "%s_", name); + ++ strlcpy(dn + prefix_len, "cmd_data_type", sizeof(dn) - prefix_len); ++ ent_type = debugfs_create_x8(dn, 0644, mdd->root, ++ (u8 *)&dbg->cmd_data_type); ++ ++ if (IS_ERR_OR_NULL(ent_type)) { ++ pr_err("debugfs_create_file: data_type fail\n"); ++ goto type_fail; ++ } ++ + strlcpy(dn + prefix_len, "off", sizeof(dn) - prefix_len); + ent_off = debugfs_create_file(dn, 0644, mdd->root, + dbg, &panel_off_fops); +@@ -303,9 +315,12 @@ int panel_debug_register_base(const char *name, void __iomem *base, + list_add(&dbg->head, &mdd->base_list); + + return 0; ++ + reg_fail: + debugfs_remove(ent_off); + off_fail: ++ debugfs_remove(ent_type); ++type_fail: + kfree(dbg); + return -ENODEV; + } +diff --git a/drivers/video/msm/mdss/mdss_debug.h b/drivers/video/msm/mdss/mdss_debug.h +index ef665e7..1bb54d2 100644 +--- a/drivers/video/msm/mdss/mdss_debug.h ++++ b/drivers/video/msm/mdss/mdss_debug.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014, 2017 The 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 +@@ -49,6 +49,7 @@ struct mdss_debug_base { + void __iomem *base; + size_t off; + size_t cnt; ++ u8 cmd_data_type; + size_t max_offset; + char *buf; + size_t buf_len; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10294/0.patch b/Patches/Linux_CVEs/CVE-2016-10294/0.patch new file mode 100644 index 00000000..efdca413 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10294/0.patch @@ -0,0 +1,122 @@ +From 9e9bc51ffb8a298f0be5befe346762cdb6e1d49c Mon Sep 17 00:00:00 2001 +From: ansharma +Date: Wed, 18 Jan 2017 16:46:38 +0530 +Subject: power: qpnp-fg: Fix possible race condition in FG debugfs + +There is a possible race condition when FG debugfs files are concurrently +accessed by multiple threads. Fix this. + +CRs-Fixed: 1105481 +Change-Id: I154e7f3cdd8d51cf67ef1dfd9d78f423f183cb64 +Signed-off-by: ansharma +--- + drivers/power/qpnp-fg.c | 34 ++++++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c +index 182b562..1e2fefc 100644 +--- a/drivers/power/qpnp-fg.c ++++ b/drivers/power/qpnp-fg.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The 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 +@@ -669,6 +669,7 @@ struct fg_trans { + struct fg_chip *chip; + struct fg_log_buffer *log; /* log buffer */ + u8 *data; /* fg data that is read */ ++ struct mutex memif_dfs_lock; /* Prevent thread concurrency */ + }; + + struct fg_dbgfs { +@@ -7514,6 +7515,7 @@ static int fg_memif_data_open(struct inode *inode, struct file *file) + trans->addr = dbgfs_data.addr; + trans->chip = dbgfs_data.chip; + trans->offset = trans->addr; ++ mutex_init(&trans->memif_dfs_lock); + + file->private_data = trans; + return 0; +@@ -7525,6 +7527,7 @@ static int fg_memif_dfs_close(struct inode *inode, struct file *file) + + if (trans && trans->log && trans->data) { + file->private_data = NULL; ++ mutex_destroy(&trans->memif_dfs_lock); + kfree(trans->log); + kfree(trans->data); + kfree(trans); +@@ -7682,10 +7685,13 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, + size_t ret; + size_t len; + ++ mutex_lock(&trans->memif_dfs_lock); + /* Is the the log buffer empty */ + if (log->rpos >= log->wpos) { +- if (get_log_data(trans) <= 0) +- return 0; ++ if (get_log_data(trans) <= 0) { ++ len = 0; ++ goto unlock_mutex; ++ } + } + + len = min(count, log->wpos - log->rpos); +@@ -7693,7 +7699,8 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, + ret = copy_to_user(buf, &log->data[log->rpos], len); + if (ret == len) { + pr_err("error copy sram register values to user\n"); +- return -EFAULT; ++ len = -EFAULT; ++ goto unlock_mutex; + } + + /* 'ret' is the number of bytes not copied */ +@@ -7701,6 +7708,9 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, + + *ppos += len; + log->rpos += len; ++ ++unlock_mutex: ++ mutex_unlock(&trans->memif_dfs_lock); + return len; + } + +@@ -7721,14 +7731,20 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, + int cnt = 0; + u8 *values; + size_t ret = 0; ++ char *kbuf; ++ u32 offset; + + struct fg_trans *trans = file->private_data; +- u32 offset = trans->offset; ++ ++ mutex_lock(&trans->memif_dfs_lock); ++ offset = trans->offset; + + /* Make a copy of the user data */ +- char *kbuf = kmalloc(count + 1, GFP_KERNEL); +- if (!kbuf) +- return -ENOMEM; ++ kbuf = kmalloc(count + 1, GFP_KERNEL); ++ if (!kbuf) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } + + ret = copy_from_user(kbuf, buf, count); + if (ret == count) { +@@ -7767,6 +7783,8 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, + + free_buf: + kfree(kbuf); ++unlock_mutex: ++ mutex_unlock(&trans->memif_dfs_lock); + return ret; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10295/0.patch b/Patches/Linux_CVEs/CVE-2016-10295/0.patch new file mode 100644 index 00000000..08b35d6f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10295/0.patch @@ -0,0 +1,238 @@ +From f11ae3df500bc2a093ddffee6ea40da859de0fa9 Mon Sep 17 00:00:00 2001 +From: ansharma +Date: Thu, 19 Jan 2017 20:22:14 +0530 +Subject: leds: qpnp-flash: Fix possible race condition in debugfs + +There is a possible race condition when debugfs files are concurrently +accessed by multiple threads. Fix this. + +CRs-Fixed: 1109420, 1109326 +Change-Id: I19e9107079ac8d039b12a37ae612727f824552d4 +Signed-off-by: ansharma +--- + drivers/leds/leds-qpnp-flash.c | 80 ++++++++++++++++++++++++++++++------------ + 1 file changed, 57 insertions(+), 23 deletions(-) + +diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c +index 43298a7..56ba8f5 100644 +--- a/drivers/leds/leds-qpnp-flash.c ++++ b/drivers/leds/leds-qpnp-flash.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The 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 +@@ -225,6 +225,7 @@ struct flash_led_platform_data { + }; + + struct qpnp_flash_led_buffer { ++ struct mutex debugfs_lock; /* Prevent thread concurrency */ + size_t rpos; + size_t wpos; + size_t len; +@@ -280,6 +281,7 @@ static int flash_led_dbgfs_file_open(struct qpnp_flash_led *led, + log->rpos = 0; + log->wpos = 0; + log->len = logbufsize - sizeof(*log); ++ mutex_init(&log->debugfs_lock); + led->log = log; + + led->buffer_cnt = 1; +@@ -301,20 +303,26 @@ static int flash_led_dfs_close(struct inode *inode, struct file *file) + + if (led && led->log) { + file->private_data = NULL; ++ mutex_destroy(&led->log->debugfs_lock); + kfree(led->log); + } + + return 0; + } + ++#define MIN_BUFFER_WRITE_LEN 20 + static int print_to_log(struct qpnp_flash_led_buffer *log, + const char *fmt, ...) + { + va_list args; + int cnt; +- char *log_buf = &log->data[log->wpos]; ++ char *log_buf; + size_t size = log->len - log->wpos; + ++ if (size < MIN_BUFFER_WRITE_LEN) ++ return 0; /* not enough buffer left */ ++ ++ log_buf = &log->data[log->wpos]; + va_start(args, fmt); + cnt = vscnprintf(log_buf, size, fmt, args); + va_end(args); +@@ -328,12 +336,14 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + struct qpnp_flash_led *led = fp->private_data; + struct qpnp_flash_led_buffer *log = led->log; + u8 val; +- int rc; ++ int rc = 0; + size_t len; + size_t ret; + +- if (log->rpos >= log->wpos && led->buffer_cnt == 0) +- return 0; ++ mutex_lock(&log->debugfs_lock); ++ if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || ++ ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) ++ goto unlock_mutex; + + rc = spmi_ext_register_readl(led->spmi_dev->ctrl, + led->spmi_dev->sid, INT_LATCHED_STS(led->base), &val, 1); +@@ -341,17 +351,17 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + dev_err(&led->spmi_dev->dev, + "Unable to read from address %x, rc(%d)\n", + INT_LATCHED_STS(led->base), rc); +- return -EINVAL; ++ goto unlock_mutex; + } + led->buffer_cnt--; + + rc = print_to_log(log, "0x%05X ", INT_LATCHED_STS(led->base)); + if (rc == 0) +- return rc; ++ goto unlock_mutex; + + rc = print_to_log(log, "0x%02X ", val); + if (rc == 0) +- return rc; ++ goto unlock_mutex; + + if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') + log->data[log->wpos - 1] = '\n'; +@@ -361,36 +371,43 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + ret = copy_to_user(buf, &log->data[log->rpos], len); + if (ret) { + pr_err("error copy register value to user\n"); +- return -EFAULT; ++ rc = -EFAULT; ++ goto unlock_mutex; + } + + len -= ret; + *ppos += len; + log->rpos += len; + +- return len; ++ rc = len; ++ ++unlock_mutex: ++ mutex_unlock(&log->debugfs_lock); ++ return rc; + } + + static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, + size_t count, loff_t *ppos) { + struct qpnp_flash_led *led = fp->private_data; + struct qpnp_flash_led_buffer *log = led->log; +- int rc; ++ int rc = 0; + size_t len; + size_t ret; + +- if (log->rpos >= log->wpos && led->buffer_cnt == 0) +- return 0; ++ mutex_lock(&log->debugfs_lock); ++ if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || ++ ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) ++ goto unlock_mutex; + + led->buffer_cnt--; + + rc = print_to_log(log, "0x%05X ", FLASH_LED_FAULT_STATUS(led->base)); + if (rc == 0) +- return rc; ++ goto unlock_mutex; + + rc = print_to_log(log, "0x%02X ", led->fault_reg); + if (rc == 0) +- return rc; ++ goto unlock_mutex; + + if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') + log->data[log->wpos - 1] = '\n'; +@@ -400,14 +417,19 @@ static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, + ret = copy_to_user(buf, &log->data[log->rpos], len); + if (ret) { + pr_err("error copy register value to user\n"); +- return -EFAULT; ++ rc = -EFAULT; ++ goto unlock_mutex; + } + + len -= ret; + *ppos += len; + log->rpos += len; + +- return len; ++ rc = len; ++ ++unlock_mutex: ++ mutex_unlock(&log->debugfs_lock); ++ return rc; + } + + static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, +@@ -420,10 +442,14 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, + size_t ret = 0; + + struct qpnp_flash_led *led = file->private_data; +- char *kbuf = kmalloc(count + 1, GFP_KERNEL); ++ char *kbuf; + +- if (!kbuf) +- return -ENOMEM; ++ mutex_lock(&led->log->debugfs_lock); ++ kbuf = kmalloc(count + 1, GFP_KERNEL); ++ if (!kbuf) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } + + ret = copy_from_user(kbuf, buf, count); + if (!ret) { +@@ -452,6 +478,8 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, + + free_buf: + kfree(kbuf); ++unlock_mutex: ++ mutex_unlock(&led->log->debugfs_lock); + return ret; + } + +@@ -464,10 +492,14 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, + int data; + size_t ret = 0; + struct qpnp_flash_led *led = file->private_data; +- char *kbuf = kmalloc(count + 1, GFP_KERNEL); ++ char *kbuf; + +- if (!kbuf) +- return -ENOMEM; ++ mutex_lock(&led->log->debugfs_lock); ++ kbuf = kmalloc(count + 1, GFP_KERNEL); ++ if (!kbuf) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } + + ret = copy_from_user(kbuf, buf, count); + if (ret == count) { +@@ -495,6 +527,8 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, + + free_buf: + kfree(kbuf); ++unlock_mutex: ++ mutex_unlock(&led->log->debugfs_lock); + return ret; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-10296/0.patch b/Patches/Linux_CVEs/CVE-2016-10296/0.patch new file mode 100644 index 00000000..ac233c61 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-10296/0.patch @@ -0,0 +1,88 @@ +From a5e46d8635a2e28463b365aacdeab6750abd0d49 Mon Sep 17 00:00:00 2001 +From: Sahitya Tummala +Date: Fri, 3 Feb 2017 13:24:19 +0530 +Subject: uio: fix potential use after free issue when accessing debug_buffer + +The variable debug_buffer is a global variable which is allocated +and free'd when open/close is called on debugfs file - +"/sys/kernel/debug/rmt_storage/info". The current code doesn't +have locks to handle concurrent accesses to the above file. +This results into use after free issue when debug_buffer is +accessed by two threads at the same time. Fix this by adding +a mutex lock to protect this global variable. + +Change-Id: I6bc3f0ae2d7fca3ca9fe8561612f5863b6c3268a +Signed-off-by: Sahitya Tummala +--- + drivers/uio/msm_sharedmem/sharedmem_qmi.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/uio/msm_sharedmem/sharedmem_qmi.c b/drivers/uio/msm_sharedmem/sharedmem_qmi.c +index 48fb17e..fd95dee 100644 +--- a/drivers/uio/msm_sharedmem/sharedmem_qmi.c ++++ b/drivers/uio/msm_sharedmem/sharedmem_qmi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2015, 2017, The 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 +@@ -223,6 +223,7 @@ static int sharedmem_qmi_req_cb(struct qmi_handle *handle, void *conn_h, + #define DEBUG_BUF_SIZE (2048) + static char *debug_buffer; + static u32 debug_data_size; ++static struct mutex dbg_buf_lock; /* mutex for debug_buffer */ + + static ssize_t debug_read(struct file *file, char __user *buf, + size_t count, loff_t *file_pos) +@@ -279,21 +280,29 @@ static int debug_open(struct inode *inode, struct file *file) + { + u32 buffer_size; + +- if (debug_buffer != NULL) ++ mutex_lock(&dbg_buf_lock); ++ if (debug_buffer != NULL) { ++ mutex_unlock(&dbg_buf_lock); + return -EBUSY; ++ } + buffer_size = DEBUG_BUF_SIZE; + debug_buffer = kzalloc(buffer_size, GFP_KERNEL); +- if (debug_buffer == NULL) ++ if (debug_buffer == NULL) { ++ mutex_unlock(&dbg_buf_lock); + return -ENOMEM; ++ } + debug_data_size = fill_debug_info(debug_buffer, buffer_size); ++ mutex_unlock(&dbg_buf_lock); + return 0; + } + + static int debug_close(struct inode *inode, struct file *file) + { ++ mutex_lock(&dbg_buf_lock); + kfree(debug_buffer); + debug_buffer = NULL; + debug_data_size = 0; ++ mutex_unlock(&dbg_buf_lock); + return 0; + } + +@@ -324,6 +333,7 @@ static void debugfs_init(void) + { + struct dentry *f_ent; + ++ mutex_init(&dbg_buf_lock); + dir_ent = debugfs_create_dir("rmt_storage", NULL); + if (IS_ERR(dir_ent)) { + pr_err("Failed to create debug_fs directory\n"); +@@ -352,6 +362,7 @@ static void debugfs_init(void) + static void debugfs_exit(void) + { + debugfs_remove_recursive(dir_ent); ++ mutex_destroy(&dbg_buf_lock); + } + + static void sharedmem_qmi_svc_recv_msg(struct work_struct *work) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-1583/0.patch b/Patches/Linux_CVEs/CVE-2016-1583/0.patch new file mode 100644 index 00000000..9d7b23e6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-1583/0.patch @@ -0,0 +1,57 @@ +From f0fe970df3838c202ef6c07a4c2b36838ef0a88b Mon Sep 17 00:00:00 2001 +From: Jeff Mahoney +Date: Tue, 5 Jul 2016 17:32:30 -0400 +Subject: ecryptfs: don't allow mmap when the lower fs doesn't support it + +There are legitimate reasons to disallow mmap on certain files, notably +in sysfs or procfs. We shouldn't emulate mmap support on file systems +that don't offer support natively. + +CVE-2016-1583 + +Signed-off-by: Jeff Mahoney +Cc: stable@vger.kernel.org +[tyhicks: clean up f_op check by using ecryptfs_file_to_lower()] +Signed-off-by: Tyler Hicks +--- + fs/ecryptfs/file.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +(limited to 'fs/ecryptfs/file.c') + +diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c +index 53d0141..ca4e837 100644 +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -169,6 +169,19 @@ out: + return rc; + } + ++static int ecryptfs_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct file *lower_file = ecryptfs_file_to_lower(file); ++ /* ++ * Don't allow mmap on top of file systems that don't support it ++ * natively. If FILESYSTEM_MAX_STACK_DEPTH > 2 or ecryptfs ++ * allows recursive mounting, this will need to be extended. ++ */ ++ if (!lower_file->f_op->mmap) ++ return -ENODEV; ++ return generic_file_mmap(file, vma); ++} ++ + /** + * ecryptfs_open + * @inode: inode specifying file to open +@@ -403,7 +416,7 @@ const struct file_operations ecryptfs_main_fops = { + #ifdef CONFIG_COMPAT + .compat_ioctl = ecryptfs_compat_ioctl, + #endif +- .mmap = generic_file_mmap, ++ .mmap = ecryptfs_mmap, + .open = ecryptfs_open, + .flush = ecryptfs_flush, + .release = ecryptfs_release, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2053/0.patch b/Patches/Linux_CVEs/CVE-2016-2053/0.patch new file mode 100644 index 00000000..53718a7b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2053/0.patch @@ -0,0 +1,125 @@ +From 0d62e9dd6da45bbf0f33a8617afc5fe774c8f45f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 5 Aug 2015 12:54:46 +0100 +Subject: ASN.1: Fix non-match detection failure on data overrun + +If the ASN.1 decoder is asked to parse a sequence of objects, non-optional +matches get skipped if there's no more data to be had rather than a +data-overrun error being reported. + +This is due to the code segment that decides whether to skip optional +matches (ie. matches that could get ignored because an element is marked +OPTIONAL in the grammar) due to a lack of data also skips non-optional +elements if the data pointer has reached the end of the buffer. + +This can be tested with the data decoder for the new RSA akcipher algorithm +that takes three non-optional integers. Currently, it skips the last +integer if there is insufficient data. + +Without the fix, #defining DEBUG in asn1_decoder.c will show something +like: + + next_op: pc=0/13 dp=0/270 C=0 J=0 + - match? 30 30 00 + - TAG: 30 266 CONS + next_op: pc=2/13 dp=4/270 C=1 J=0 + - match? 02 02 00 + - TAG: 02 257 + - LEAF: 257 + next_op: pc=5/13 dp=265/270 C=1 J=0 + - match? 02 02 00 + - TAG: 02 3 + - LEAF: 3 + next_op: pc=8/13 dp=270/270 C=1 J=0 + next_op: pc=11/13 dp=270/270 C=1 J=0 + - end cons t=4 dp=270 l=270/270 + +The next_op line for pc=8/13 should be followed by a match line. + +This is not exploitable for X.509 certificates by means of shortening the +message and fixing up the ASN.1 CONS tags because: + + (1) The relevant records being built up are cleared before use. + + (2) If the message is shortened sufficiently to remove the public key, the + ASN.1 parse of the RSA key will fail quickly due to a lack of data. + + (3) Extracted signature data is either turned into MPIs (which cope with a + 0 length) or is simpler integers specifying algoritms and suchlike + (which can validly be 0); and + + (4) The AKID and SKID extensions are optional and their removal is handled + without risking passing a NULL to asymmetric_key_generate_id(). + + (5) If the certificate is truncated sufficiently to remove the subject, + issuer or serialNumber then the ASN.1 decoder will fail with a 'Cons + stack underflow' return. + +This is not exploitable for PKCS#7 messages by means of removal of elements +from such a message from the tail end of a sequence: + + (1) Any shortened X.509 certs embedded in the PKCS#7 message are survivable + as detailed above. + + (2) The message digest content isn't used if it shows a NULL pointer, + similarly, the authattrs aren't used if that shows a NULL pointer. + + (3) A missing signature results in a NULL MPI - which the MPI routines deal + with. + + (4) If data is NULL, it is expected that the message has detached content and + that is handled appropriately. + + (5) If the serialNumber is excised, the unconditional action associated + with it will pick up the containing SEQUENCE instead, so no NULL + pointer will be seen here. + + If both the issuer and the serialNumber are excised, the ASN.1 decode + will fail with an 'Unexpected tag' return. + + In either case, there's no way to get to asymmetric_key_generate_id() + with a NULL pointer. + + (6) Other fields are decoded to simple integers. Shortening the message + to omit an algorithm ID field will cause checks on this to fail early + in the verification process. + + +This can also be tested by snipping objects off of the end of the ASN.1 stream +such that mandatory tags are removed - or even from the end of internal +SEQUENCEs. If any mandatory tag is missing, the error EBADMSG *should* be +produced. Without this patch ERANGE or ENOPKG might be produced or the parse +may apparently succeed, perhaps with ENOKEY or EKEYREJECTED being produced +later, depending on what gets snipped. + +Just snipping off the final BIT_STRING or OCTET_STRING from either sample +should be a start since both are mandatory and neither will cause an EBADMSG +without the patches + +Reported-by: Marcel Holtmann +Signed-off-by: David Howells +Tested-by: Marcel Holtmann +Reviewed-by: David Woodhouse +--- + lib/asn1_decoder.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c +index 55980d7..3f74dd3 100644 +--- a/lib/asn1_decoder.c ++++ b/lib/asn1_decoder.c +@@ -210,9 +210,8 @@ next_op: + unsigned char tmp; + + /* Skip conditional matches if possible */ +- if ((op & ASN1_OP_MATCH__COND && +- flags & FLAG_MATCHED) || +- dp == datalen) { ++ if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || ++ (op & ASN1_OP_MATCH__SKIP && dp == datalen)) { + flags &= ~FLAG_LAST_MATCHED; + pc += asn1_op_lengths[op]; + goto next_op; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2059/0.patch b/Patches/Linux_CVEs/CVE-2016-2059/0.patch new file mode 100644 index 00000000..0394e128 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2059/0.patch @@ -0,0 +1,41 @@ +From 9e8bdd63f7011dff5523ea435433834b3702398d Mon Sep 17 00:00:00 2001 +From: Karthikeyan Ramasubramanian +Date: Mon, 22 Feb 2016 16:30:40 -0700 +Subject: net: ipc_router: Bind only a client port as control port + +IPC Router binds any port as a control port and moves it from the client +port list to control port list. Misbehaving clients can exploit this +incorrect behavior. + +IPC Router to check if the port is a client port before binding it as a +control port. + +CRs-Fixed: 974577 +Change-Id: I9f189b76967d5f85750218a7cb6537d187a69663 +Signed-off-by: Karthikeyan Ramasubramanian +--- + net/ipc_router/ipc_router_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c +index 99486e9..3100ebd 100644 +--- a/net/ipc_router/ipc_router_core.c ++++ b/net/ipc_router/ipc_router_core.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2016, The 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 +@@ -3532,7 +3532,7 @@ int msm_ipc_router_get_curr_pkt_size(struct msm_ipc_port *port_ptr) + + int msm_ipc_router_bind_control_port(struct msm_ipc_port *port_ptr) + { +- if (!port_ptr) ++ if (unlikely(!port_ptr || port_ptr->type != CLIENT_PORT)) + return -EINVAL; + + down_write(&local_ports_lock_lhc2); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2061/0.patch b/Patches/Linux_CVEs/CVE-2016-2061/0.patch new file mode 100644 index 00000000..f6306c84 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2061/0.patch @@ -0,0 +1,239 @@ +From 79db14ca9f791a14be9376a0340ad3b9b9a4d603 Mon Sep 17 00:00:00 2001 +From: Jing Zhou +Date: Fri, 11 Mar 2016 17:30:50 -0800 +Subject: msm: camera: isp: Fix warning and errors based on static analysis + +This change fixes the warning/errors from static analysis + +CRs-fixed: 992942 +Change-Id: Iaf90ab4c1d17f903d03458d76cab1b4c0a5c8836 +Signed-off-by: Jing Zhou +--- + drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c | 3 +-- + .../media/platform/msm/camera_v2/isp/msm_isp_axi_util.c | 13 ++++++++----- + .../platform/msm/camera_v2/isp/msm_isp_stats_util.c | 5 ++--- + drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 16 +++++++++------- + drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c | 14 +++++++------- + 5 files changed, 27 insertions(+), 24 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +index b196934..3331f0d 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +@@ -85,6 +85,7 @@ struct msm_isp_bufq *msm_isp_get_bufq( + + /* bufq_handle cannot be 0 */ + if ((bufq_handle == 0) || ++ bufq_index >= BUF_MGR_NUM_BUF_Q || + (bufq_index > buf_mgr->num_buf_q)) + return NULL; + +@@ -1329,8 +1330,6 @@ static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr, + + for (i = 0; i < BUF_MGR_NUM_BUF_Q; i++) { + bufq = &buf_mgr->bufq[i]; +- if (!bufq) +- continue; + + spin_lock_irqsave(&bufq->bufq_lock, flags); + if (!bufq->bufq_handle) { +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 61cc9b9..c98b8ad 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 +@@ -60,7 +60,7 @@ int msm_isp_axi_create_stream(struct vfe_device *vfe_dev, + struct msm_vfe_axi_shared_data *axi_data, + struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd) + { +- int i = stream_cfg_cmd->stream_src; ++ uint32_t i = stream_cfg_cmd->stream_src; + + if (i >= VFE_AXI_SRC_MAX) { + pr_err("%s:%d invalid stream_src %d\n", __func__, __LINE__, +@@ -1686,6 +1686,7 @@ static void msm_isp_handle_done_buf_frame_id_mismatch( + struct msm_isp_event_data error_event; + int ret = 0; + ++ memset(&error_event, 0, sizeof(error_event)); + error_event.frame_id = + vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id; + error_event.u.error_info.err_type = +@@ -1709,7 +1710,7 @@ static int msm_isp_process_done_buf(struct vfe_device *vfe_dev, + struct msm_vfe_axi_stream *stream_info, struct msm_isp_buffer *buf, + struct timeval *time_stamp, uint32_t frame_id) + { +- int rc = 0, ret = 0; ++ int rc; + unsigned long flags; + struct msm_isp_event_data buf_event; + uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle); +@@ -1771,7 +1772,7 @@ static int msm_isp_process_done_buf(struct vfe_device *vfe_dev, + if (rc == -EFAULT) { + msm_isp_halt_send_error(vfe_dev, + ISP_EVENT_BUF_FATAL_ERROR); +- return ret; ++ return rc; + } + if (!rc) { + ISP_DBG("%s:%d vfe_id %d Buffer dropped %d\n", +@@ -1827,7 +1828,7 @@ static int msm_isp_process_done_buf(struct vfe_device *vfe_dev, + if (rc == -EFAULT) { + msm_isp_halt_send_error(vfe_dev, + ISP_EVENT_BUF_FATAL_ERROR); +- return ret; ++ return rc; + } + } + +@@ -2406,7 +2407,8 @@ static int msm_isp_update_dual_HW_ms_info_at_stop( + static int msm_isp_update_dual_HW_axi(struct vfe_device *vfe_dev, + struct msm_vfe_axi_stream *stream_info) + { +- int rc = 0, vfe_id; ++ int rc = 0; ++ int vfe_id; + uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle); + struct dual_vfe_resource *dual_vfe_res = NULL; + +@@ -2871,6 +2873,7 @@ static int msm_isp_return_empty_buffer(struct vfe_device *vfe_dev, + return rc; + } + ++ memset(&error_event, 0, sizeof(error_event)); + error_event.frame_id = frame_id; + error_event.u.error_info.err_type = ISP_ERROR_RETURN_EMPTY_BUFFER; + error_event.u.error_info.session_id = stream_info->session_id; +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 fe97f13..7eaffad 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 +@@ -117,7 +117,7 @@ static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev, + = buf; + } + } +- } else if (!vfe_dev->is_split) { ++ } else { + if (buf) + vfe_dev->hw_info->vfe_ops.stats_ops. + update_ping_pong_addr( +@@ -285,8 +285,7 @@ static int32_t msm_isp_stats_configure(struct vfe_device *vfe_dev, + if (rc < 0) { + pr_err("%s:%d failed: stats buf divert rc %d\n", + __func__, __LINE__, rc); +- if (0 == result) +- result = rc; ++ result = rc; + } + } + if (is_composite && comp_stats_type_mask) { +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 4535d20..8a6c395e 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 +@@ -944,6 +944,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) + { + long rc = 0; ++ long rc2 = 0; + struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd); + + if (!vfe_dev || !vfe_dev->vfe_base) { +@@ -1023,7 +1024,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, + if (atomic_read(&vfe_dev->error_info.overflow_state) + != HALT_ENFORCED) { + rc = msm_isp_stats_reset(vfe_dev); +- rc |= msm_isp_axi_reset(vfe_dev, arg); ++ rc2 = msm_isp_axi_reset(vfe_dev, arg); ++ if (!rc && rc2) ++ rc = rc2; + } else { + pr_err_ratelimited("%s: no HW reset, halt enforced.\n", + __func__); +@@ -1035,7 +1038,9 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, + if (atomic_read(&vfe_dev->error_info.overflow_state) + != HALT_ENFORCED) { + rc = msm_isp_stats_restart(vfe_dev); +- rc |= msm_isp_axi_restart(vfe_dev, arg); ++ rc2 = msm_isp_axi_restart(vfe_dev, arg); ++ if (!rc && rc2) ++ rc = rc2; + } else { + pr_err_ratelimited("%s: no AXI restart, halt enforced.\n", + __func__); +@@ -1822,8 +1827,6 @@ void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev) + { + struct msm_vfe_error_info *error_info = &vfe_dev->error_info; + error_info->info_dump_frame_count++; +- if (error_info->info_dump_frame_count == 0) +- error_info->info_dump_frame_count++; + } + + +@@ -1922,6 +1925,7 @@ static void msm_isp_process_overflow_irq( + + if (atomic_read(&vfe_dev->error_info.overflow_state) + != HALT_ENFORCED) { ++ memset(&error_event, 0, sizeof(error_event)); + error_event.frame_id = + vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id; + error_event.u.error_info.err_type = +@@ -1939,10 +1943,8 @@ void msm_isp_reset_burst_count_and_frame_drop( + stream_info->stream_type != BURST_STREAM) { + return; + } +- if (stream_info->stream_type == BURST_STREAM && +- stream_info->num_burst_capture != 0) { ++ if (stream_info->num_burst_capture != 0) + msm_isp_reset_framedrop(vfe_dev, stream_info); +- } + } + + static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev, +diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +index dc6af17..640379d 100644 +--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c ++++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +@@ -467,23 +467,23 @@ static void msm_ispif_sel_csid_core(struct ispif_device *ispif, + switch (intftype) { + case PIX0: + data &= ~(BIT(1) | BIT(0)); +- data |= csid; ++ data |= (uint32_t) csid; + break; + case RDI0: + data &= ~(BIT(5) | BIT(4)); +- data |= (csid << 4); ++ data |= ((uint32_t) csid) << 4; + break; + case PIX1: + data &= ~(BIT(9) | BIT(8)); +- data |= (csid << 8); ++ data |= ((uint32_t) csid) << 8; + break; + case RDI1: + data &= ~(BIT(13) | BIT(12)); +- data |= (csid << 12); ++ data |= ((uint32_t) csid) << 12; + break; + case RDI2: + data &= ~(BIT(21) | BIT(20)); +- data |= (csid << 20); ++ data |= ((uint32_t) csid) << 20; + break; + } + +@@ -559,9 +559,9 @@ static void msm_ispif_enable_intf_cids(struct ispif_device *ispif, + + data = msm_camera_io_r(ispif->base + intf_addr); + if (enable) +- data |= cid_mask; ++ data |= (uint32_t) cid_mask; + else +- data &= ~cid_mask; ++ data &= ~((uint32_t) cid_mask); + msm_camera_io_w_mb(data, ispif->base + intf_addr); + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2063/0.patch b/Patches/Linux_CVEs/CVE-2016-2063/0.patch new file mode 100644 index 00000000..24f90187 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2063/0.patch @@ -0,0 +1,41 @@ +From ab3f46119ca10de87a11fe966b0723c48f27acd4 Mon Sep 17 00:00:00 2001 +From: Manaf Meethalavalappu Pallikunhi +Date: Wed, 30 Mar 2016 17:12:16 +0530 +Subject: msm: limits: Check user buffer size before copying to local buffer + +User input data is passed in from userspace through debugfs interface +of supply lm core to validate supply lm core functionality. Ensure +user buffer size is not greater than expected stack buffer size +to avoid out of bounds array accesses. + +Change-Id: I5a93774855241b50895c5e2b3ff939e4c33a0185 +Signed-off-by: Manaf Meethalavalappu Pallikunhi +--- + drivers/thermal/supply_lm_core.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/thermal/supply_lm_core.c b/drivers/thermal/supply_lm_core.c +index fc8e807..a4d137f 100644 +--- a/drivers/thermal/supply_lm_core.c ++++ b/drivers/thermal/supply_lm_core.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2016, The 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 +@@ -303,6 +303,11 @@ static ssize_t supply_lm_input_write(struct file *fp, + enum corner_state gpu; + enum corner_state modem; + ++ if (count > (MODE_MAX - 1)) { ++ pr_err("Invalid user input\n"); ++ return -EINVAL; ++ } ++ + if (copy_from_user(&buf, user_buffer, count)) + return -EFAULT; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2068/0.patch b/Patches/Linux_CVEs/CVE-2016-2068/0.patch new file mode 100644 index 00000000..b724c522 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2068/0.patch @@ -0,0 +1,69 @@ +From 2c04c0dab66013b7dfbe4d5a523c2c1d6b5b11d6 Mon Sep 17 00:00:00 2001 +From: Weiyin Jiang +Date: Tue, 26 Apr 2016 14:35:38 +0800 +Subject: ASoC: msm: audio-effects: misc fixes in h/w accelerated effect + +Adding memory copy size check and integer overflow check in h/w +accelerated effect driver. + +Change-Id: I17d4cc0a38770f0c5067fa8047cd63e7bf085e48 +CRs-Fixed: 1006609 +Signed-off-by: Weiyin Jiang +--- + drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 8 +++++--- + sound/soc/msm/qdsp6v2/q6asm.c | 6 ++++++ + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +index 3ba20ca..3a88344 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +@@ -163,7 +163,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + + pr_debug("%s: dec buf size: %d, num_buf: %d, enc buf size: %d, num_buf: %d\n", + __func__, effects->config.output.buf_size, +- effects->config.output.buf_size, ++ effects->config.output.num_buf, + effects->config.input.buf_size, + effects->config.input.num_buf); + rc = q6asm_audio_client_buf_alloc_contiguous(IN, effects->ac, +@@ -251,7 +251,8 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + + bufptr = q6asm_is_cpu_buf_avail(IN, effects->ac, &size, &idx); + if (bufptr) { +- if (copy_from_user(bufptr, (void *)arg, ++ if ((effects->config.buf_cfg.output_len > size) || ++ copy_from_user(bufptr, (void *)arg, + effects->config.buf_cfg.output_len)) { + rc = -EFAULT; + goto ioctl_fail; +@@ -307,7 +308,8 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + rc = -EFAULT; + goto ioctl_fail; + } +- if (copy_to_user((void *)arg, bufptr, ++ if ((effects->config.buf_cfg.input_len > size) || ++ copy_to_user((void *)arg, bufptr, + effects->config.buf_cfg.input_len)) { + rc = -EFAULT; + goto ioctl_fail; +diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c +index df310b8..d143eb0 100644 +--- a/sound/soc/msm/qdsp6v2/q6asm.c ++++ b/sound/soc/msm/qdsp6v2/q6asm.c +@@ -1300,6 +1300,12 @@ int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir, + + ac->port[dir].buf = buf; + ++ /* check for integer overflow */ ++ if ((bufcnt > 0) && ((INT_MAX / bufcnt) < bufsz)) { ++ pr_err("%s: integer overflow\n", __func__); ++ mutex_unlock(&ac->cmd_lock); ++ goto fail; ++ } + bytes_to_alloc = bufsz * bufcnt; + + /* The size to allocate should be multiple of 4K bytes */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2185/0.patch b/Patches/Linux_CVEs/CVE-2016-2185/0.patch new file mode 100644 index 00000000..5731daee --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2185/0.patch @@ -0,0 +1,109 @@ +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/Linux_CVEs/CVE-2016-2185/1.patch b/Patches/Linux_CVEs/CVE-2016-2185/1.patch new file mode 100644 index 00000000..9cf00e3d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2185/1.patch @@ -0,0 +1,109 @@ +From 37735ed2c8c12e9671a3742d6b9028bad43852df Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Wed, 23 Mar 2016 11:53:46 -0700 +Subject: [PATCH] Input: ati_remote2 - fix crashes on detecting device with + invalid descriptor + +[ Upstream commit 950336ba3e4a1ffd2ca60d29f6ef386dd2c7351d ] + +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 +Signed-off-by: Sasha Levin +--- + 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 f63341f20b91a..e8c6a4842e91c 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); diff --git a/Patches/Linux_CVEs/CVE-2016-2186/0.patch b/Patches/Linux_CVEs/CVE-2016-2186/0.patch new file mode 100644 index 00000000..bfc78434 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2186/0.patch @@ -0,0 +1,38 @@ +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/Linux_CVEs/CVE-2016-2186/1.patch b/Patches/Linux_CVEs/CVE-2016-2186/1.patch new file mode 100644 index 00000000..e0bca0ae --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2186/1.patch @@ -0,0 +1,38 @@ +From b684cb33d6867e10ba45375a12ef9f3ceb6f0aa7 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Mon, 14 Mar 2016 09:33:40 -0700 +Subject: [PATCH] Input: powermate - fix oops with malicious USB descriptors + +[ Upstream commit 9c6ba456711687b794dcf285856fc14e2c76074f ] + +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 +Signed-off-by: Sasha Levin +--- + 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 63b539d3dabae..84909a12ff36c 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; diff --git a/Patches/Linux_CVEs/CVE-2016-2187/0.patch b/Patches/Linux_CVEs/CVE-2016-2187/0.patch new file mode 100644 index 00000000..d6b97d0d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2187/0.patch @@ -0,0 +1,56 @@ +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/Linux_CVEs/CVE-2016-2187/1.patch b/Patches/Linux_CVEs/CVE-2016-2187/1.patch new file mode 100644 index 00000000..72d5fe93 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2187/1.patch @@ -0,0 +1,59 @@ +From adaad9d866105bcb8f87293a0a675f573a39129d 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 + +commit 162f98dea487206d9ab79fc12ed64700667a894d upstream. + +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 +Signed-off-by: Willy Tarreau +--- + 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 29e01ab..a9f8f92 100644 +--- a/drivers/input/tablet/gtco.c ++++ b/drivers/input/tablet/gtco.c +@@ -869,6 +869,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 +@@ -890,7 +898,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/Linux_CVEs/CVE-2016-2188/0.patch b/Patches/Linux_CVEs/CVE-2016-2188/0.patch new file mode 100644 index 00000000..1f95444c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2188/0.patch @@ -0,0 +1,41 @@ +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/Linux_CVEs/CVE-2016-2188/1.patch b/Patches/Linux_CVEs/CVE-2016-2188/1.patch new file mode 100644 index 00000000..12c35b6b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2188/1.patch @@ -0,0 +1,46 @@ +From 2fac1c275bbea560d607f2e52d23c4f92dccc12f Mon Sep 17 00:00:00 2001 +From: Badhri Jagan Sridharan +Date: Tue, 30 Aug 2016 13:37:07 -0700 +Subject: UPSTREAM: USB: iowarrior: fix oops with malicious USB descriptors + +commit 4ec0ef3a82125efc36173062a50624550a900ae0 upstream. + +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 + +BUG: 28242610 + +Reported-by: Ralf Spenneberg +Signed-off-by: Josh Boyer +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Badhri Jagan Sridharan +Change-Id: If5161c23928e9ef77cb3359cba9b36622b1908df +--- + 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 d36f34e..4c24ba0 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -792,6 +792,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/Linux_CVEs/CVE-2016-2188/2.patch b/Patches/Linux_CVEs/CVE-2016-2188/2.patch new file mode 100644 index 00000000..7e944dee --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2188/2.patch @@ -0,0 +1,56 @@ +From b7321e81fc369abe353cf094d4f0dc2fe11ab95f Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 7 Mar 2017 16:11:03 +0100 +Subject: USB: iowarrior: fix NULL-deref at probe + +Make sure to check for the required interrupt-in endpoint to avoid +dereferencing a NULL-pointer should a malicious device lack such an +endpoint. + +Note that a fairly recent change purported to fix this issue, but added +an insufficient test on the number of endpoints only, a test which can +now be removed. + +Fixes: 4ec0ef3a8212 ("USB: iowarrior: fix oops with malicious USB descriptors") +Fixes: 946b960d13c1 ("USB: add driver for iowarrior devices.") +Cc: stable # 2.6.21 +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/iowarrior.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index 095778f..3ad058c 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -781,12 +781,6 @@ 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; +@@ -797,6 +791,13 @@ static int iowarrior_probe(struct usb_interface *interface, + /* this one will match for the IOWarrior56 only */ + dev->int_out_endpoint = endpoint; + } ++ ++ if (!dev->int_in_endpoint) { ++ dev_err(&interface->dev, "no interrupt-in endpoint found\n"); ++ retval = -ENODEV; ++ goto error; ++ } ++ + /* we have to check the report_size often, so remember it in the endianness suitable for our machine */ + dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint); + if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2384/0.patch b/Patches/Linux_CVEs/CVE-2016-2384/0.patch new file mode 100644 index 00000000..3a2f4799 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2384/0.patch @@ -0,0 +1,34 @@ +From 07d86ca93db7e5cdf4743564d98292042ec21af7 Mon Sep 17 00:00:00 2001 +From: Andrey Konovalov +Date: Sat, 13 Feb 2016 11:08:06 +0300 +Subject: ALSA: usb-audio: avoid freeing umidi object twice + +The 'umidi' object will be free'd on the error path by snd_usbmidi_free() +when tearing down the rawmidi interface. So we shouldn't try to free it +in snd_usbmidi_create() after having registered the rawmidi interface. + +Found by KASAN. + +Signed-off-by: Andrey Konovalov +Acked-by: Clemens Ladisch +Cc: +Signed-off-by: Takashi Iwai +--- + sound/usb/midi.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index cc39f63..007cf58 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -2455,7 +2455,6 @@ int snd_usbmidi_create(struct snd_card *card, + else + err = snd_usbmidi_create_endpoints(umidi, endpoints); + if (err < 0) { +- snd_usbmidi_free(umidi); + return err; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2465/0.patch b/Patches/Linux_CVEs/CVE-2016-2465/0.patch new file mode 100644 index 00000000..8c7ea9e4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2465/0.patch @@ -0,0 +1,173 @@ +From 09dc4abecb0da388aedb37a57889c1ce2b267807 Mon Sep 17 00:00:00 2001 +From: Veera Sundaram Sankaran +Date: Tue, 15 Mar 2016 18:42:27 -0700 +Subject: msm: mdss: fix possible out-of-bounds and overflow issue in mdp + debugfs + +There are few cases where the count argument passed by the user +space is not validated, which can potentially lead to out of bounds +or overflow issues. In some cases, kernel might copy more data than +what is requested. Add necessary checks to avoid such cases. + +Change-Id: Ifa42fbd475665a0ca581c907ce5432584ea0e7ed +Signed-off-by: Veera Sundaram Sankaran +--- + drivers/video/msm/mdss/mdss_debug.c | 44 +++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 19 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c +index 12415c2..1d214ca 100644 +--- a/drivers/video/msm/mdss/mdss_debug.c ++++ b/drivers/video/msm/mdss/mdss_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2009-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2009-2016, The 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 +@@ -109,10 +109,10 @@ static ssize_t panel_debug_base_offset_read(struct file *file, + return 0; /* the end */ + + len = snprintf(buf, sizeof(buf), "0x%02zx %zx\n", dbg->off, dbg->cnt); +- if (len < 0) ++ if (len < 0 || len >= sizeof(buf)) + return 0; + +- if (copy_to_user(buff, buf, len)) ++ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + return -EFAULT; + + *ppos += len; /* increase offset */ +@@ -231,10 +231,11 @@ static ssize_t panel_debug_base_reg_read(struct file *file, + if (mdata->debug_inf.debug_enable_clock) + mdata->debug_inf.debug_enable_clock(0); + +- if (len < 0) ++ if (len < 0 || len >= sizeof(to_user_buf)) + return 0; + +- if (copy_to_user(user_buf, to_user_buf, len)) ++ if ((count < sizeof(to_user_buf)) ++ || copy_to_user(user_buf, to_user_buf, len)) + return -EFAULT; + + *ppos += len; /* increase offset */ +@@ -368,7 +369,7 @@ static ssize_t mdss_debug_base_offset_read(struct file *file, + { + struct mdss_debug_base *dbg = file->private_data; + int len = 0; +- char buf[24]; ++ char buf[24] = {'\0'}; + + if (!dbg) + return -ENODEV; +@@ -377,10 +378,10 @@ static ssize_t mdss_debug_base_offset_read(struct file *file, + return 0; /* the end */ + + len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt); +- if (len < 0) ++ if (len < 0 || len >= sizeof(buf)) + return 0; + +- if (copy_to_user(buff, buf, len)) ++ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + return -EFAULT; + + *ppos += len; /* increase offset */ +@@ -702,7 +703,7 @@ static ssize_t mdss_debug_factor_read(struct file *file, + { + struct mdss_fudge_factor *factor = file->private_data; + int len = 0; +- char buf[32]; ++ char buf[32] = {'\0'}; + + if (!factor) + return -ENODEV; +@@ -712,10 +713,10 @@ static ssize_t mdss_debug_factor_read(struct file *file, + + len = snprintf(buf, sizeof(buf), "%d/%d\n", + factor->numer, factor->denom); +- if (len < 0) ++ if (len < 0 || len >= sizeof(buf)) + return 0; + +- if (copy_to_user(buff, buf, len)) ++ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + return -EFAULT; + + *ppos += len; /* increase offset */ +@@ -746,6 +747,8 @@ static ssize_t mdss_debug_perf_mode_write(struct file *file, + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + ++ buf[count] = 0; /* end of string */ ++ + if (sscanf(buf, "%d", &perf_mode) != 1) + return -EFAULT; + +@@ -766,7 +769,7 @@ static ssize_t mdss_debug_perf_mode_read(struct file *file, + { + struct mdss_perf_tune *perf_tune = file->private_data; + int len = 0; +- char buf[40]; ++ char buf[40] = {'\0'}; + + if (!perf_tune) + return -ENODEV; +@@ -774,14 +777,12 @@ static ssize_t mdss_debug_perf_mode_read(struct file *file, + if (*ppos) + return 0; /* the end */ + +- buf[count] = 0; +- + len = snprintf(buf, sizeof(buf), "min_mdp_clk %lu min_bus_vote %llu\n", + perf_tune->min_mdp_clk, perf_tune->min_bus_vote); +- if (len < 0) ++ if (len < 0 || len >= sizeof(buf)) + return 0; + +- if (copy_to_user(buff, buf, len)) ++ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + return -EFAULT; + + *ppos += len; /* increase offset */ +@@ -801,7 +802,7 @@ static ssize_t mdss_debug_perf_panic_read(struct file *file, + { + struct mdss_data_type *mdata = file->private_data; + int len = 0; +- char buf[40]; ++ char buf[40] = {'\0'}; + + if (!mdata) + return -ENODEV; +@@ -811,10 +812,10 @@ static ssize_t mdss_debug_perf_panic_read(struct file *file, + + len = snprintf(buf, sizeof(buf), "%d\n", + !mdata->has_panic_ctrl); +- if (len < 0) ++ if (len < 0 || len >= sizeof(buf)) + return 0; + +- if (copy_to_user(buff, buf, len)) ++ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) + return -EFAULT; + + *ppos += len; /* increase offset */ +@@ -877,9 +878,14 @@ static ssize_t mdss_debug_perf_panic_write(struct file *file, + if (!mdata) + return -EFAULT; + ++ if (count >= sizeof(buf)) ++ return -EFAULT; ++ + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + ++ buf[count] = 0; /* end of string */ ++ + if (sscanf(buf, "%d", &disable_panic) != 1) + return -EFAULT; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2467/0.patch b/Patches/Linux_CVEs/CVE-2016-2467/0.patch new file mode 100644 index 00000000..cb3ed542 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2467/0.patch @@ -0,0 +1,91 @@ +From 38b6131d78cecec5d970230aeee3cef485103d82 Mon Sep 17 00:00:00 2001 +From: Fred Oh +Date: Thu, 3 Oct 2013 20:03:38 -0700 +Subject: ASoC: msm: q6: check upper bounds when copy ac3 params + +Although AC3 maximum param size is fixed, better check upper bounds +when copy user data. It might cause overflow, possibly cause memory +corruption. + +Change-Id: Iaded762f774c608e48e685d92204fc7516aa3063 +Signed-off-by: Fred Oh +--- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c | 30 ++++++++++++++++++++++-------- + 1 file changed, 22 insertions(+), 8 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +index b630e4b..dcac1a0 100644 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +@@ -51,6 +51,8 @@ + #define COMPRE_OUTPUT_METADATA_SIZE (sizeof(struct output_meta_data_st)) + #define COMPRESSED_LR_VOL_MAX_STEPS 0x20002000 + ++#define MAX_AC3_PARAM_SIZE (18*2*sizeof(int)) ++ + const DECLARE_TLV_DB_LINEAR(compr_rx_vol_gain, 0, + COMPRESSED_LR_VOL_MAX_STEPS); + struct snd_msm { +@@ -973,19 +975,25 @@ static int msm_compr_ioctl(struct snd_pcm_substream *substream, + compr->codec = FORMAT_MPEG4_AAC; + break; + case SND_AUDIOCODEC_AC3: { +- char params_value[18*2*sizeof(int)]; ++ char params_value[MAX_AC3_PARAM_SIZE]; + int *params_value_data = (int *)params_value; + /* 36 is the max param length for ddp */ + int i; + struct snd_dec_ddp *ddp = + &compr->info.codec_param.codec.options.ddp; +- int params_length = ddp->params_length*sizeof(int); ++ uint32_t params_length = ddp->params_length*sizeof(int); ++ if (params_length > MAX_AC3_PARAM_SIZE) { ++ /*MAX is 36*sizeof(int) this should not happen*/ ++ pr_err("params_length(%d) is greater than %d", ++ params_length, MAX_AC3_PARAM_SIZE); ++ params_length = MAX_AC3_PARAM_SIZE; ++ } + pr_debug("SND_AUDIOCODEC_AC3\n"); + compr->codec = FORMAT_AC3; + if (copy_from_user(params_value, (void *)ddp->params, + params_length)) +- pr_err("%s: ERROR: copy ddp params value\n", +- __func__); ++ pr_err("%s: copy ddp params value, size=%d\n", ++ __func__, params_length); + pr_debug("params_length: %d\n", ddp->params_length); + for (i = 0; i < params_length; i++) + pr_debug("params_value[%d]: %x\n", i, +@@ -1004,19 +1012,25 @@ static int msm_compr_ioctl(struct snd_pcm_substream *substream, + break; + } + case SND_AUDIOCODEC_EAC3: { +- char params_value[18*2*sizeof(int)]; ++ char params_value[MAX_AC3_PARAM_SIZE]; + int *params_value_data = (int *)params_value; + /* 36 is the max param length for ddp */ + int i; + struct snd_dec_ddp *ddp = + &compr->info.codec_param.codec.options.ddp; +- int params_length = ddp->params_length*sizeof(int); ++ uint32_t params_length = ddp->params_length*sizeof(int); ++ if (params_length > MAX_AC3_PARAM_SIZE) { ++ /*MAX is 36*sizeof(int) this should not happen*/ ++ pr_err("params_length(%d) is greater than %d", ++ params_length, MAX_AC3_PARAM_SIZE); ++ params_length = MAX_AC3_PARAM_SIZE; ++ } + pr_debug("SND_AUDIOCODEC_EAC3\n"); + compr->codec = FORMAT_EAC3; + if (copy_from_user(params_value, (void *)ddp->params, + params_length)) +- pr_err("%s: ERROR: copy ddp params value\n", +- __func__); ++ pr_err("%s: copy ddp params value, size=%d\n", ++ __func__, params_length); + pr_debug("params_length: %d\n", ddp->params_length); + for (i = 0; i < ddp->params_length; i++) + pr_debug("params_value[%d]: %x\n", i, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2468/0.patch b/Patches/Linux_CVEs/CVE-2016-2468/0.patch new file mode 100644 index 00000000..71ec1f27 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2468/0.patch @@ -0,0 +1,44 @@ +From b5eb67744215b3434a36b9251e28da3dc2a638a6 Mon Sep 17 00:00:00 2001 +From: Rajesh Kemisetti +Date: Mon, 9 May 2016 22:12:20 +0530 +Subject: msm: kgsl: Add missing checks for alloc size and sglen + +In _kgsl_sharedmem_page_alloc(), check for boundary limits +of requested alloc size before honoring and make sure sglen +is greater than zero before marking it as end of sg list. + +Change-Id: I8b9e225e515a0f31593df6f4cad253236475d0ae +Signed-off-by: Rajesh Kemisetti +--- + drivers/gpu/msm/kgsl_sharedmem.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c +index 079b9ff..98f634d 100644 +--- a/drivers/gpu/msm/kgsl_sharedmem.c ++++ b/drivers/gpu/msm/kgsl_sharedmem.c +@@ -609,6 +609,10 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, + unsigned int align; + int step = ((VMALLOC_END - VMALLOC_START)/8) >> PAGE_SHIFT; + ++ size = PAGE_ALIGN(size); ++ if (size == 0 || size > UINT_MAX) ++ return -EINVAL; ++ + align = (memdesc->flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT; + + page_size = get_page_size(size, align); +@@ -712,7 +716,9 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, + + memdesc->sglen = sglen; + memdesc->size = size; +- sg_mark_end(&memdesc->sg[sglen - 1]); ++ ++ if (sglen > 0) ++ sg_mark_end(&memdesc->sg[sglen - 1]); + + /* + * All memory that goes to the user has to be zeroed out before it gets +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2488/0.patch b/Patches/Linux_CVEs/CVE-2016-2488/0.patch new file mode 100644 index 00000000..b8f17f35 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2488/0.patch @@ -0,0 +1,40 @@ +From 91ea960b91250eca57d8fbdb8aafa11d80695d46 Mon Sep 17 00:00:00 2001 +From: VijayaKumar T M +Date: Wed, 8 Jun 2016 16:32:11 +0530 +Subject: msm: camera: ispif: Validate VFE num input during reset + +Userspace supplies the actual number of used VFEs in session to ISPIF. +Validate the userspace input value and if found to be invalid, return +error. + +CRs-Fixed: 898074 +Signed-off-by: Venu Yeshala +Signed-off-by: VijayaKumar T M +Change-Id: I3288ddb6404e817a705a92281b4c54666f372c56 +--- + drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +index 7fb1ac1..94735fd 100644 +--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c ++++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +@@ -1133,9 +1133,13 @@ static irqreturn_t msm_io_ispif_irq(int irq_num, void *data) + static int msm_ispif_set_vfe_info(struct ispif_device *ispif, + struct msm_ispif_vfe_info *vfe_info) + { +- memcpy(&ispif->vfe_info, vfe_info, sizeof(struct msm_ispif_vfe_info)); +- if (ispif->vfe_info.num_vfe > ispif->hw_num_isps) ++ if (!vfe_info || (vfe_info->num_vfe <= 0) || ++ ((uint32_t)(vfe_info->num_vfe) > ispif->hw_num_isps)) { ++ pr_err("Invalid VFE info: %p %d\n", vfe_info, ++ (vfe_info ? vfe_info->num_vfe:0)); + return -EINVAL; ++ } ++ memcpy(&ispif->vfe_info, vfe_info, sizeof(struct msm_ispif_vfe_info)); + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2503/0.patch b/Patches/Linux_CVEs/CVE-2016-2503/0.patch new file mode 100644 index 00000000..ddefe228 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2503/0.patch @@ -0,0 +1,102 @@ +From 0c46fc0f8fb7ffd26557b51b235d463a01ee75f5 Mon Sep 17 00:00:00 2001 +From: Divya Ponnusamy +Date: Fri, 6 May 2016 13:24:37 -0600 +Subject: msm: kgsl: Avoid race condition in ioctl_syncsource_destroy + +If the ioctl syncsource_destroy is accessed by parallel +threads, where the spinlock is acquired by threads after +getting syncsource, then the simultaneous processes try +to remove the already destroyed syncsource->refcount by +the first thread that acquires this spinlock. This leads +to race condition while removing syncsource->idr. + +Avoid separate lock inside getting syncsource, instead +acquire spinlock before we get the syncsource in +destroy ioctl so that the threads access the spinlock +and operate on syncsource without use-after-free issue. + +Change-Id: I6add3800c40cd09f6e6e0cf2720e69059bd83cbc +Signed-off-by: Divya Ponnusamy +--- + drivers/gpu/msm/kgsl_sync.c | 36 +++++++++++++++++------------------- + 1 file changed, 17 insertions(+), 19 deletions(-) + +diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c +index 44a0f11..df181ad 100644 +--- a/drivers/gpu/msm/kgsl_sync.c ++++ b/drivers/gpu/msm/kgsl_sync.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -473,23 +473,23 @@ long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, + goto out; + } + ++ kref_init(&syncsource->refcount); ++ syncsource->private = private; ++ + idr_preload(GFP_KERNEL); + spin_lock(&private->syncsource_lock); + id = idr_alloc(&private->syncsource_idr, syncsource, 1, 0, GFP_NOWAIT); +- spin_unlock(&private->syncsource_lock); +- idr_preload_end(); +- + if (id > 0) { +- kref_init(&syncsource->refcount); + syncsource->id = id; +- syncsource->private = private; +- + param->id = id; + ret = 0; + } else { + ret = id; + } + ++ spin_unlock(&private->syncsource_lock); ++ idr_preload_end(); ++ + out: + if (ret) { + if (syncsource && syncsource->oneshot) +@@ -547,25 +547,23 @@ long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, + { + struct kgsl_syncsource_destroy *param = data; + struct kgsl_syncsource *syncsource = NULL; +- struct kgsl_process_private *private; +- +- syncsource = kgsl_syncsource_get(dev_priv->process_priv, +- param->id); ++ struct kgsl_process_private *private = dev_priv->process_priv; + +- if (syncsource == NULL) +- return -EINVAL; ++ spin_lock(&private->syncsource_lock); ++ syncsource = idr_find(&private->syncsource_idr, param->id); + +- private = syncsource->private; ++ if (syncsource) { ++ idr_remove(&private->syncsource_idr, param->id); ++ syncsource->id = 0; ++ } + +- spin_lock(&private->syncsource_lock); +- idr_remove(&private->syncsource_idr, param->id); +- syncsource->id = 0; + spin_unlock(&private->syncsource_lock); + ++ if (syncsource == NULL) ++ return -EINVAL; ++ + /* put reference from syncsource creation */ + kgsl_syncsource_put(syncsource); +- /* put reference from getting the syncsource above */ +- kgsl_syncsource_put(syncsource); + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2504/0.patch b/Patches/Linux_CVEs/CVE-2016-2504/0.patch new file mode 100644 index 00000000..0afa3534 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2504/0.patch @@ -0,0 +1,180 @@ +From ec5feea777b07c0e1f9ce45b7f3179a3f6facf75 Mon Sep 17 00:00:00 2001 +From: Sunil Khatri +Date: Wed, 25 May 2016 15:36:30 +0530 +Subject: msm: kgsl: Defer adding the mem entry to a process + +If we add the mem entry pointer in the process idr and rb tree +too early, other threads can do operations on the entry by +guessing the ID or GPU address before the object gets returned +by the creating operation. + +Allocate an ID for the object but don't assign the pointer until +right before the creating function returns ensuring that another +operation can't access it until it is ready. + +CRs-Fixed: 1002974 +Change-Id: Ic0dedbadc0dd2125bd2a7bcc152972c0555e07f8 +Signed-off-by: Jordan Crouse +Signed-off-by: Sunil Khatri +--- + drivers/gpu/msm/kgsl.c | 84 ++++++++++++++++++++++++++++++++------------------ + 1 file changed, 54 insertions(+), 30 deletions(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index 94b09f0..dab99c5 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -313,18 +313,13 @@ kgsl_mem_entry_destroy(struct kref *kref) + EXPORT_SYMBOL(kgsl_mem_entry_destroy); + + /** +- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and +- * assign it with a gpu address space before insertion ++ * kgsl_mem_entry_track_gpuaddr - Get the entry gpu address space before ++ * insertion to the process + * @process: the process that owns the memory + * @entry: the memory entry + * +- * @returns - 0 on succcess else error code ++ * @returns - 0 on success else error code + * +- * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address. +- * The assignment of gpu address and insertion into list needs to +- * happen with the memory lock held to avoid race conditions between +- * gpu address being selected and some other thread looking through the +- * rb list in search of memory based on gpuaddr + * This function should be called with processes memory spinlock held + */ + static int +@@ -332,8 +327,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, + struct kgsl_mem_entry *entry) + { + int ret = 0; +- struct rb_node **node; +- struct rb_node *parent = NULL; + struct kgsl_pagetable *pagetable = process->pagetable; + + assert_spin_locked(&process->mem_lock); +@@ -354,25 +347,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, + pagetable = pagetable->mmu->securepagetable; + + ret = kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc); +- if (ret) +- goto done; +- +- node = &process->mem_rb.rb_node; +- +- while (*node) { +- struct kgsl_mem_entry *cur; +- +- parent = *node; +- cur = rb_entry(parent, struct kgsl_mem_entry, node); +- +- if (entry->memdesc.gpuaddr < cur->memdesc.gpuaddr) +- node = &parent->rb_left; +- else +- node = &parent->rb_right; +- } +- +- rb_link_node(&entry->node, parent, node); +- rb_insert_color(&entry->node, &process->mem_rb); + + done: + return ret; +@@ -398,6 +372,47 @@ kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, + } + } + ++static void kgsl_mem_entry_commit_mem_list(struct kgsl_process_private *process, ++ struct kgsl_mem_entry *entry) ++{ ++ struct rb_node **node; ++ struct rb_node *parent = NULL; ++ ++ if (!entry->memdesc.gpuaddr) ++ return; ++ ++ /* Insert mem entry in mem_rb tree */ ++ node = &process->mem_rb.rb_node; ++ while (*node) { ++ struct kgsl_mem_entry *cur; ++ ++ parent = *node; ++ cur = rb_entry(parent, struct kgsl_mem_entry, node); ++ ++ if (entry->memdesc.gpuaddr < cur->memdesc.gpuaddr) ++ node = &parent->rb_left; ++ else ++ node = &parent->rb_right; ++ } ++ ++ rb_link_node(&entry->node, parent, node); ++ rb_insert_color(&entry->node, &process->mem_rb); ++} ++ ++static void kgsl_mem_entry_commit_process(struct kgsl_process_private *process, ++ struct kgsl_mem_entry *entry) ++{ ++ if (!entry) ++ return; ++ ++ spin_lock(&entry->priv->mem_lock); ++ /* Insert mem entry in mem_rb tree */ ++ kgsl_mem_entry_commit_mem_list(process, entry); ++ /* Replace mem entry in mem_idr using id */ ++ idr_replace(&entry->priv->mem_idr, entry, entry->id); ++ spin_unlock(&entry->priv->mem_lock); ++} ++ + /** + * kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process + * @entry: the memory entry +@@ -424,7 +439,8 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, + return -EBADF; + idr_preload(GFP_KERNEL); + spin_lock(&process->mem_lock); +- id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT); ++ /* Allocate the ID but don't attach the pointer just yet */ ++ id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT); + spin_unlock(&process->mem_lock); + idr_preload_end(); + +@@ -2400,6 +2416,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, + + trace_kgsl_mem_map(entry, fd); + ++ kgsl_mem_entry_commit_process(private, entry); + return 0; + + unmap: +@@ -2671,6 +2688,7 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, + + trace_kgsl_mem_map(entry, param->fd); + ++ kgsl_mem_entry_commit_process(private, entry); + return result; + + error_attach: +@@ -3084,6 +3102,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( + entry->memdesc.size); + trace_kgsl_mem_alloc(entry); + ++ kgsl_mem_entry_commit_process(private, entry); + return entry; + err: + kfree(entry); +@@ -3579,6 +3598,11 @@ static int kgsl_check_gpu_addr_collision( + spin_lock(&private->mem_lock); + kgsl_mem_entry_untrack_gpuaddr(private, entry); + spin_unlock(&private->mem_lock); ++ } else { ++ /* Insert mem entry in mem_rb tree */ ++ spin_lock(&private->mem_lock); ++ kgsl_mem_entry_commit_mem_list(private, entry); ++ spin_unlock(&private->mem_lock); + } + } else { + trace_kgsl_mem_unmapped_area_collision(entry, addr, len, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2544/0.patch b/Patches/Linux_CVEs/CVE-2016-2544/0.patch new file mode 100644 index 00000000..09cb3cc1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2544/0.patch @@ -0,0 +1,38 @@ +From 3567eb6af614dac436c4b16a8d426f9faed639b3 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 12 Jan 2016 15:36:27 +0100 +Subject: ALSA: seq: Fix race at timer setup and close + +ALSA sequencer code has an open race between the timer setup ioctl and +the close of the client. This was triggered by syzkaller fuzzer, and +a use-after-free was caught there as a result. + +This patch papers over it by adding a proper queue->timer_mutex lock +around the timer-related calls in the relevant code path. + +Reported-by: Dmitry Vyukov +Tested-by: Dmitry Vyukov +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/seq/seq_queue.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c +index 7dfd0f4..0bec02e 100644 +--- a/sound/core/seq/seq_queue.c ++++ b/sound/core/seq/seq_queue.c +@@ -142,8 +142,10 @@ static struct snd_seq_queue *queue_new(int owner, int locked) + static void queue_delete(struct snd_seq_queue *q) + { + /* stop and release the timer */ ++ mutex_lock(&q->timer_mutex); + snd_seq_timer_stop(q->timer); + snd_seq_timer_close(q); ++ mutex_unlock(&q->timer_mutex); + /* wait until access free */ + snd_use_lock_sync(&q->use_lock); + /* release resources... */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2545/0.patch b/Patches/Linux_CVEs/CVE-2016-2545/0.patch new file mode 100644 index 00000000..0c88b965 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2545/0.patch @@ -0,0 +1,37 @@ +From ee8413b01045c74340aa13ad5bdf905de32be736 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 13 Jan 2016 21:35:06 +0100 +Subject: ALSA: timer: Fix double unlink of active_list + +ALSA timer instance object has a couple of linked lists and they are +unlinked unconditionally at snd_timer_stop(). Meanwhile +snd_timer_interrupt() unlinks it, but it calls list_del() which leaves +the element list itself unchanged. This ends up with unlinking twice, +and it was caught by syzkaller fuzzer. + +The fix is to use list_del_init() variant properly there, too. + +Reported-by: Dmitry Vyukov +Tested-by: Dmitry Vyukov +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/timer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 31f40f0..9241784df 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -694,7 +694,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) + } else { + ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING; + if (--timer->running) +- list_del(&ti->active_list); ++ list_del_init(&ti->active_list); + } + if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || + (ti->flags & SNDRV_TIMER_IFLG_FAST)) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2546/0.patch b/Patches/Linux_CVEs/CVE-2016-2546/0.patch new file mode 100644 index 00000000..0c11987f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2546/0.patch @@ -0,0 +1,122 @@ +From af368027a49a751d6ff4ee9e3f9961f35bb4fede Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 13 Jan 2016 17:48:01 +0100 +Subject: ALSA: timer: Fix race among timer ioctls + +ALSA timer ioctls have an open race and this may lead to a +use-after-free of timer instance object. A simplistic fix is to make +each ioctl exclusive. We have already tread_sem for controlling the +tread, and extend this as a global mutex to be applied to each ioctl. + +The downside is, of course, the worse concurrency. But these ioctls +aren't to be parallel accessible, in anyway, so it should be fine to +serialize there. + +Reported-by: Dmitry Vyukov +Tested-by: Dmitry Vyukov +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/timer.c | 32 +++++++++++++++++++------------- + 1 file changed, 19 insertions(+), 13 deletions(-) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 9241784df..3810ee8 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -73,7 +73,7 @@ struct snd_timer_user { + struct timespec tstamp; /* trigger tstamp */ + wait_queue_head_t qchange_sleep; + struct fasync_struct *fasync; +- struct mutex tread_sem; ++ struct mutex ioctl_lock; + }; + + /* list of timers */ +@@ -1253,7 +1253,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) + return -ENOMEM; + spin_lock_init(&tu->qlock); + init_waitqueue_head(&tu->qchange_sleep); +- mutex_init(&tu->tread_sem); ++ mutex_init(&tu->ioctl_lock); + tu->ticks = 1; + tu->queue_size = 128; + tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), +@@ -1273,8 +1273,10 @@ static int snd_timer_user_release(struct inode *inode, struct file *file) + if (file->private_data) { + tu = file->private_data; + file->private_data = NULL; ++ mutex_lock(&tu->ioctl_lock); + if (tu->timeri) + snd_timer_close(tu->timeri); ++ mutex_unlock(&tu->ioctl_lock); + kfree(tu->queue); + kfree(tu->tqueue); + kfree(tu); +@@ -1512,7 +1514,6 @@ static int snd_timer_user_tselect(struct file *file, + int err = 0; + + tu = file->private_data; +- mutex_lock(&tu->tread_sem); + if (tu->timeri) { + snd_timer_close(tu->timeri); + tu->timeri = NULL; +@@ -1556,7 +1557,6 @@ static int snd_timer_user_tselect(struct file *file, + } + + __err: +- mutex_unlock(&tu->tread_sem); + return err; + } + +@@ -1769,7 +1769,7 @@ enum { + SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), + }; + +-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, ++static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) + { + struct snd_timer_user *tu; +@@ -1786,17 +1786,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, + { + int xarg; + +- mutex_lock(&tu->tread_sem); +- if (tu->timeri) { /* too late */ +- mutex_unlock(&tu->tread_sem); ++ if (tu->timeri) /* too late */ + return -EBUSY; +- } +- if (get_user(xarg, p)) { +- mutex_unlock(&tu->tread_sem); ++ if (get_user(xarg, p)) + return -EFAULT; +- } + tu->tread = xarg ? 1 : 0; +- mutex_unlock(&tu->tread_sem); + return 0; + } + case SNDRV_TIMER_IOCTL_GINFO: +@@ -1829,6 +1823,18 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, + return -ENOTTY; + } + ++static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct snd_timer_user *tu = file->private_data; ++ long ret; ++ ++ mutex_lock(&tu->ioctl_lock); ++ ret = __snd_timer_user_ioctl(file, cmd, arg); ++ mutex_unlock(&tu->ioctl_lock); ++ return ret; ++} ++ + static int snd_timer_user_fasync(int fd, struct file * file, int on) + { + struct snd_timer_user *tu; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2547/0.patch b/Patches/Linux_CVEs/CVE-2016-2547/0.patch new file mode 100644 index 00000000..7df556be --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2547/0.patch @@ -0,0 +1,101 @@ +From b5a663aa426f4884c71cd8580adae73f33570f0d Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 14 Jan 2016 16:30:58 +0100 +Subject: ALSA: timer: Harden slave timer list handling + +A slave timer instance might be still accessible in a racy way while +operating the master instance as it lacks of locking. Since the +master operation is mostly protected with timer->lock, we should cope +with it while changing the slave instance, too. Also, some linked +lists (active_list and ack_list) of slave instances aren't unlinked +immediately at stopping or closing, and this may lead to unexpected +accesses. + +This patch tries to address these issues. It adds spin lock of +timer->lock (either from master or slave, which is equivalent) in a +few places. For avoiding a deadlock, we ensure that the global +slave_active_lock is always locked at first before each timer lock. + +Also, ack and active_list of slave instances are properly unlinked at +snd_timer_stop() and snd_timer_close(). + +Last but not least, remove the superfluous call of _snd_timer_stop() +at removing slave links. This is a noop, and calling it may confuse +readers wrt locking. Further cleanup will follow in a later patch. + +Actually we've got reports of use-after-free by syzkaller fuzzer, and +this hopefully fixes these issues. + +Reported-by: Dmitry Vyukov +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/timer.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 3810ee8..4e8d7bf 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -215,11 +215,13 @@ static void snd_timer_check_master(struct snd_timer_instance *master) + slave->slave_id == master->slave_id) { + list_move_tail(&slave->open_list, &master->slave_list_head); + spin_lock_irq(&slave_active_lock); ++ spin_lock(&master->timer->lock); + slave->master = master; + slave->timer = master->timer; + if (slave->flags & SNDRV_TIMER_IFLG_RUNNING) + list_add_tail(&slave->active_list, + &master->slave_active_head); ++ spin_unlock(&master->timer->lock); + spin_unlock_irq(&slave_active_lock); + } + } +@@ -346,15 +348,18 @@ int snd_timer_close(struct snd_timer_instance *timeri) + timer->hw.close) + timer->hw.close(timer); + /* remove slave links */ ++ spin_lock_irq(&slave_active_lock); ++ spin_lock(&timer->lock); + list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, + open_list) { +- spin_lock_irq(&slave_active_lock); +- _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION); + list_move_tail(&slave->open_list, &snd_timer_slave_list); + slave->master = NULL; + slave->timer = NULL; +- spin_unlock_irq(&slave_active_lock); ++ list_del_init(&slave->ack_list); ++ list_del_init(&slave->active_list); + } ++ spin_unlock(&timer->lock); ++ spin_unlock_irq(&slave_active_lock); + mutex_unlock(®ister_mutex); + } + out: +@@ -441,9 +446,12 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri) + + spin_lock_irqsave(&slave_active_lock, flags); + timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; +- if (timeri->master) ++ if (timeri->master && timeri->timer) { ++ spin_lock(&timeri->timer->lock); + list_add_tail(&timeri->active_list, + &timeri->master->slave_active_head); ++ spin_unlock(&timeri->timer->lock); ++ } + spin_unlock_irqrestore(&slave_active_lock, flags); + return 1; /* delayed start */ + } +@@ -489,6 +497,8 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, + if (!keep_flag) { + spin_lock_irqsave(&slave_active_lock, flags); + timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; ++ list_del_init(&timeri->ack_list); ++ list_del_init(&timeri->active_list); + spin_unlock_irqrestore(&slave_active_lock, flags); + } + goto __end; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2549/0.patch b/Patches/Linux_CVEs/CVE-2016-2549/0.patch new file mode 100644 index 00000000..cede879f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2549/0.patch @@ -0,0 +1,54 @@ +From 2ba1fe7a06d3624f9a7586d672b55f08f7c670f3 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 18 Jan 2016 13:52:47 +0100 +Subject: ALSA: hrtimer: Fix stall by hrtimer_cancel() + +hrtimer_cancel() waits for the completion from the callback, thus it +must not be called inside the callback itself. This was already a +problem in the past with ALSA hrtimer driver, and the early commit +[fcfdebe70759: ALSA: hrtimer - Fix lock-up] tried to address it. + +However, the previous fix is still insufficient: it may still cause a +lockup when the ALSA timer instance reprograms itself in its callback. +Then it invokes the start function even in snd_timer_interrupt() that +is called in hrtimer callback itself, results in a CPU stall. This is +no hypothetical problem but actually triggered by syzkaller fuzzer. + +This patch tries to fix the issue again. Now we call +hrtimer_try_to_cancel() at both start and stop functions so that it +won't fall into a deadlock, yet giving some chance to cancel the queue +if the functions have been called outside the callback. The proper +hrtimer_cancel() is called in anyway at closing, so this should be +enough. + +Reported-and-tested-by: Dmitry Vyukov +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/hrtimer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c +index f845ecf..656d9a9 100644 +--- a/sound/core/hrtimer.c ++++ b/sound/core/hrtimer.c +@@ -90,7 +90,7 @@ static int snd_hrtimer_start(struct snd_timer *t) + struct snd_hrtimer *stime = t->private_data; + + atomic_set(&stime->running, 0); +- hrtimer_cancel(&stime->hrt); ++ hrtimer_try_to_cancel(&stime->hrt); + hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), + HRTIMER_MODE_REL); + atomic_set(&stime->running, 1); +@@ -101,6 +101,7 @@ static int snd_hrtimer_stop(struct snd_timer *t) + { + struct snd_hrtimer *stime = t->private_data; + atomic_set(&stime->running, 0); ++ hrtimer_try_to_cancel(&stime->hrt); + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-2847/0.patch b/Patches/Linux_CVEs/CVE-2016-2847/0.patch new file mode 100644 index 00000000..843bdd83 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-2847/0.patch @@ -0,0 +1,250 @@ +From 759c01142a5d0f364a462346168a56de28a80f52 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Mon, 18 Jan 2016 16:36:09 +0100 +Subject: pipe: limit the per-user amount of pages allocated in pipes + +On no-so-small systems, it is possible for a single process to cause an +OOM condition by filling large pipes with data that are never read. A +typical process filling 4000 pipes with 1 MB of data will use 4 GB of +memory. On small systems it may be tricky to set the pipe max size to +prevent this from happening. + +This patch makes it possible to enforce a per-user soft limit above +which new pipes will be limited to a single page, effectively limiting +them to 4 kB each, as well as a hard limit above which no new pipes may +be created for this user. This has the effect of protecting the system +against memory abuse without hurting other users, and still allowing +pipes to work correctly though with less data at once. + +The limit are controlled by two new sysctls : pipe-user-pages-soft, and +pipe-user-pages-hard. Both may be disabled by setting them to zero. The +default soft limit allows the default number of FDs per process (1024) +to create pipes of the default size (64kB), thus reaching a limit of 64MB +before starting to create only smaller pipes. With 256 processes limited +to 1024 FDs each, this results in 1024*64kB + (256*1024 - 1024) * 4kB = +1084 MB of memory allocated for a user. The hard limit is disabled by +default to avoid breaking existing applications that make intensive use +of pipes (eg: for splicing). + +Reported-by: socketpair@gmail.com +Reported-by: Tetsuo Handa +Mitigates: CVE-2013-4312 (Linux 2.0+) +Suggested-by: Linus Torvalds +Signed-off-by: Willy Tarreau +Signed-off-by: Al Viro +--- + Documentation/sysctl/fs.txt | 23 ++++++++++++++++++++++ + fs/pipe.c | 47 +++++++++++++++++++++++++++++++++++++++++++-- + include/linux/pipe_fs_i.h | 4 ++++ + include/linux/sched.h | 1 + + kernel/sysctl.c | 14 ++++++++++++++ + 5 files changed, 87 insertions(+), 2 deletions(-) + +diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt +index 88152f2..302b5ed 100644 +--- a/Documentation/sysctl/fs.txt ++++ b/Documentation/sysctl/fs.txt +@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs: + - nr_open + - overflowuid + - overflowgid ++- pipe-user-pages-hard ++- pipe-user-pages-soft + - protected_hardlinks + - protected_symlinks + - suid_dumpable +@@ -159,6 +161,27 @@ The default is 65534. + + ============================================================== + ++pipe-user-pages-hard: ++ ++Maximum total number of pages a non-privileged user may allocate for pipes. ++Once this limit is reached, no new pipes may be allocated until usage goes ++below the limit again. When set to 0, no limit is applied, which is the default ++setting. ++ ++============================================================== ++ ++pipe-user-pages-soft: ++ ++Maximum total number of pages a non-privileged user may allocate for pipes ++before the pipe size gets limited to a single page. Once this limit is reached, ++new pipes will be limited to a single page in size for this user in order to ++limit total memory usage, and trying to increase them using fcntl() will be ++denied until usage goes below the limit again. The default value allows to ++allocate up to 1024 pipes at their default size. When set to 0, no limit is ++applied. ++ ++============================================================== ++ + protected_hardlinks: + + A long-standing class of security issues is the hardlink-based +diff --git a/fs/pipe.c b/fs/pipe.c +index 42cf8dd..ab8dad3 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -38,6 +38,12 @@ unsigned int pipe_max_size = 1048576; + */ + unsigned int pipe_min_size = PAGE_SIZE; + ++/* Maximum allocatable pages per user. Hard limit is unset by default, soft ++ * matches default values. ++ */ ++unsigned long pipe_user_pages_hard; ++unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR; ++ + /* + * We use a start+len construction, which provides full use of the + * allocated memory. +@@ -583,20 +589,49 @@ pipe_fasync(int fd, struct file *filp, int on) + return retval; + } + ++static void account_pipe_buffers(struct pipe_inode_info *pipe, ++ unsigned long old, unsigned long new) ++{ ++ atomic_long_add(new - old, &pipe->user->pipe_bufs); ++} ++ ++static bool too_many_pipe_buffers_soft(struct user_struct *user) ++{ ++ return pipe_user_pages_soft && ++ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft; ++} ++ ++static bool too_many_pipe_buffers_hard(struct user_struct *user) ++{ ++ return pipe_user_pages_hard && ++ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard; ++} ++ + struct pipe_inode_info *alloc_pipe_info(void) + { + struct pipe_inode_info *pipe; + + pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); + if (pipe) { +- pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL); ++ unsigned long pipe_bufs = PIPE_DEF_BUFFERS; ++ struct user_struct *user = get_current_user(); ++ ++ if (!too_many_pipe_buffers_hard(user)) { ++ if (too_many_pipe_buffers_soft(user)) ++ pipe_bufs = 1; ++ pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL); ++ } ++ + if (pipe->bufs) { + init_waitqueue_head(&pipe->wait); + pipe->r_counter = pipe->w_counter = 1; +- pipe->buffers = PIPE_DEF_BUFFERS; ++ pipe->buffers = pipe_bufs; ++ pipe->user = user; ++ account_pipe_buffers(pipe, 0, pipe_bufs); + mutex_init(&pipe->mutex); + return pipe; + } ++ free_uid(user); + kfree(pipe); + } + +@@ -607,6 +642,8 @@ void free_pipe_info(struct pipe_inode_info *pipe) + { + int i; + ++ account_pipe_buffers(pipe, pipe->buffers, 0); ++ free_uid(pipe->user); + for (i = 0; i < pipe->buffers; i++) { + struct pipe_buffer *buf = pipe->bufs + i; + if (buf->ops) +@@ -998,6 +1035,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages) + memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer)); + } + ++ account_pipe_buffers(pipe, pipe->buffers, nr_pages); + pipe->curbuf = 0; + kfree(pipe->bufs); + pipe->bufs = bufs; +@@ -1069,6 +1107,11 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) + if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) { + ret = -EPERM; + goto out; ++ } else if ((too_many_pipe_buffers_hard(pipe->user) || ++ too_many_pipe_buffers_soft(pipe->user)) && ++ !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { ++ ret = -EPERM; ++ goto out; + } + ret = pipe_set_size(pipe, nr_pages); + break; +diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h +index eb8b8ac..24f5470 100644 +--- a/include/linux/pipe_fs_i.h ++++ b/include/linux/pipe_fs_i.h +@@ -42,6 +42,7 @@ struct pipe_buffer { + * @fasync_readers: reader side fasync + * @fasync_writers: writer side fasync + * @bufs: the circular array of pipe buffers ++ * @user: the user who created this pipe + **/ + struct pipe_inode_info { + struct mutex mutex; +@@ -57,6 +58,7 @@ struct pipe_inode_info { + struct fasync_struct *fasync_readers; + struct fasync_struct *fasync_writers; + struct pipe_buffer *bufs; ++ struct user_struct *user; + }; + + /* +@@ -123,6 +125,8 @@ void pipe_unlock(struct pipe_inode_info *); + void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); + + extern unsigned int pipe_max_size, pipe_min_size; ++extern unsigned long pipe_user_pages_hard; ++extern unsigned long pipe_user_pages_soft; + int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *); + + +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 61aa9bb..1589ddc8 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -835,6 +835,7 @@ struct user_struct { + #endif + unsigned long locked_shm; /* How many pages of mlocked shm ? */ + unsigned long unix_inflight; /* How many files in flight in unix sockets */ ++ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */ + + #ifdef CONFIG_KEYS + struct key *uid_keyring; /* UID specific keyring */ +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index c810f8a..f6fd236 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -1757,6 +1757,20 @@ static struct ctl_table fs_table[] = { + .proc_handler = &pipe_proc_fn, + .extra1 = &pipe_min_size, + }, ++ { ++ .procname = "pipe-user-pages-hard", ++ .data = &pipe_user_pages_hard, ++ .maxlen = sizeof(pipe_user_pages_hard), ++ .mode = 0644, ++ .proc_handler = proc_doulongvec_minmax, ++ }, ++ { ++ .procname = "pipe-user-pages-soft", ++ .data = &pipe_user_pages_soft, ++ .maxlen = sizeof(pipe_user_pages_soft), ++ .mode = 0644, ++ .proc_handler = proc_doulongvec_minmax, ++ }, + { } + }; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3070/0.patch b/Patches/Linux_CVEs/CVE-2016-3070/0.patch new file mode 100644 index 00000000..0c801170 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3070/0.patch @@ -0,0 +1,163 @@ +From af110cc4b24250faafd4f3b9879cf51e350d7799 Mon Sep 17 00:00:00 2001 +From: Hugh Dickins +Date: Fri, 15 Jul 2016 15:08:19 -0400 +Subject: mm: migrate dirty page without clear_page_dirty_for_io etc + +commit 42cb14b110a5698ccf26ce59c4441722605a3743 upstream. + +clear_page_dirty_for_io() has accumulated writeback and memcg subtleties +since v2.6.16 first introduced page migration; and the set_page_dirty() +which completed its migration of PageDirty, later had to be moderated to +__set_page_dirty_nobuffers(); then PageSwapBacked had to skip that too. + +No actual problems seen with this procedure recently, but if you look into +what the clear_page_dirty_for_io(page)+set_page_dirty(newpage) is actually +achieving, it turns out to be nothing more than moving the PageDirty flag, +and its NR_FILE_DIRTY stat from one zone to another. + +It would be good to avoid a pile of irrelevant decrementations and +incrementations, and improper event counting, and unnecessary descent of +the radix_tree under tree_lock (to set the PAGECACHE_TAG_DIRTY which +radix_tree_replace_slot() left in place anyway). + +Do the NR_FILE_DIRTY movement, like the other stats movements, while +interrupts still disabled in migrate_page_move_mapping(); and don't even +bother if the zone is the same. Do the PageDirty movement there under +tree_lock too, where old page is frozen and newpage not yet visible: +bearing in mind that as soon as newpage becomes visible in radix_tree, an +un-page-locked set_page_dirty() might interfere (or perhaps that's just +not possible: anything doing so should already hold an additional +reference to the old page, preventing its migration; but play safe). + +But we do still need to transfer PageDirty in migrate_page_copy(), for +those who don't go the mapping route through migrate_page_move_mapping(). + +CVE-2016-3070 + +Signed-off-by: Hugh Dickins +Cc: Christoph Lameter +Cc: "Kirill A. Shutemov" +Cc: Rik van Riel +Cc: Vlastimil Babka +Cc: Davidlohr Bueso +Cc: Oleg Nesterov +Cc: Sasha Levin +Cc: Dmitry Vyukov +Cc: KOSAKI Motohiro +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +[ciwillia@brocade.com: backported to 3.10: adjusted context] +Signed-off-by: Charles (Chas) Williams +Signed-off-by: Willy Tarreau +--- + mm/migrate.c | 51 +++++++++++++++++++++++++++++++-------------------- + 1 file changed, 31 insertions(+), 20 deletions(-) + +diff --git a/mm/migrate.c b/mm/migrate.c +index a88c12f..a61500f 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -311,6 +312,8 @@ static int migrate_page_move_mapping(struct address_space *mapping, + struct page *newpage, struct page *page, + struct buffer_head *head, enum migrate_mode mode) + { ++ struct zone *oldzone, *newzone; ++ int dirty; + int expected_count = 0; + void **pslot; + +@@ -321,6 +324,9 @@ static int migrate_page_move_mapping(struct address_space *mapping, + return MIGRATEPAGE_SUCCESS; + } + ++ oldzone = page_zone(page); ++ newzone = page_zone(newpage); ++ + spin_lock_irq(&mapping->tree_lock); + + pslot = radix_tree_lookup_slot(&mapping->page_tree, +@@ -361,6 +367,13 @@ static int migrate_page_move_mapping(struct address_space *mapping, + set_page_private(newpage, page_private(page)); + } + ++ /* Move dirty while page refs frozen and newpage not yet exposed */ ++ dirty = PageDirty(page); ++ if (dirty) { ++ ClearPageDirty(page); ++ SetPageDirty(newpage); ++ } ++ + radix_tree_replace_slot(pslot, newpage); + + /* +@@ -370,6 +383,9 @@ static int migrate_page_move_mapping(struct address_space *mapping, + */ + page_unfreeze_refs(page, expected_count - 1); + ++ spin_unlock(&mapping->tree_lock); ++ /* Leave irq disabled to prevent preemption while updating stats */ ++ + /* + * If moved to a different zone then also account + * the page for that zone. Other VM counters will be +@@ -380,13 +396,19 @@ static int migrate_page_move_mapping(struct address_space *mapping, + * via NR_FILE_PAGES and NR_ANON_PAGES if they + * are mapped to swap space. + */ +- __dec_zone_page_state(page, NR_FILE_PAGES); +- __inc_zone_page_state(newpage, NR_FILE_PAGES); +- if (!PageSwapCache(page) && PageSwapBacked(page)) { +- __dec_zone_page_state(page, NR_SHMEM); +- __inc_zone_page_state(newpage, NR_SHMEM); ++ if (newzone != oldzone) { ++ __dec_zone_state(oldzone, NR_FILE_PAGES); ++ __inc_zone_state(newzone, NR_FILE_PAGES); ++ if (PageSwapBacked(page) && !PageSwapCache(page)) { ++ __dec_zone_state(oldzone, NR_SHMEM); ++ __inc_zone_state(newzone, NR_SHMEM); ++ } ++ if (dirty && mapping_cap_account_dirty(mapping)) { ++ __dec_zone_state(oldzone, NR_FILE_DIRTY); ++ __inc_zone_state(newzone, NR_FILE_DIRTY); ++ } + } +- spin_unlock_irq(&mapping->tree_lock); ++ local_irq_enable(); + + return MIGRATEPAGE_SUCCESS; + } +@@ -460,20 +482,9 @@ void migrate_page_copy(struct page *newpage, struct page *page) + if (PageMappedToDisk(page)) + SetPageMappedToDisk(newpage); + +- if (PageDirty(page)) { +- clear_page_dirty_for_io(page); +- /* +- * Want to mark the page and the radix tree as dirty, and +- * redo the accounting that clear_page_dirty_for_io undid, +- * but we can't use set_page_dirty because that function +- * is actually a signal that all of the page has become dirty. +- * Whereas only part of our page may be dirty. +- */ +- if (PageSwapBacked(page)) +- SetPageDirty(newpage); +- else +- __set_page_dirty_nobuffers(newpage); +- } ++ /* Move dirty on pages not done by migrate_page_move_mapping() */ ++ if (PageDirty(page)) ++ SetPageDirty(newpage); + + mlock_migrate_page(newpage, page); + ksm_migrate_page(newpage, page); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3134/0.patch b/Patches/Linux_CVEs/CVE-2016-3134/0.patch new file mode 100644 index 00000000..42416182 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3134/0.patch @@ -0,0 +1,115 @@ +From 82e2616ad251a3f72991036d6e8acebbd0aceb80 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Fri, 15 Jul 2016 15:08:15 -0400 +Subject: netfilter: x_tables: don't move to non-existent next rule + +commit f24e230d257af1ad7476c6e81a8dc3127a74204e upstream. + +Ben Hawkes says: + + In the mark_source_chains function (net/ipv4/netfilter/ip_tables.c) it + is possible for a user-supplied ipt_entry structure to have a large + next_offset field. This field is not bounds checked prior to writing a + counter value at the supplied offset. + +Base chains enforce absolute verdict. + +User defined chains are supposed to end with an unconditional return, +xtables userspace adds them automatically. + +But if such return is missing we will move to non-existent next rule. + +CVE-2016-3134 + +Reported-by: Ben Hawkes +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Chas Williams <3chas3@gmail.com> +Signed-off-by: Willy Tarreau +--- + net/ipv4/netfilter/arp_tables.c | 8 +++++--- + net/ipv4/netfilter/ip_tables.c | 4 ++++ + net/ipv6/netfilter/ip6_tables.c | 4 ++++ + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c +index 456fc6e..7460b7b 100644 +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -430,6 +430,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct arpt_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -452,6 +454,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct arpt_entry *) + (entry0 + newpos); +@@ -675,10 +679,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, + } + } + +- if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) { +- duprintf("Looping hook\n"); ++ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) + return -ELOOP; +- } + + /* Finally, each sanity check must pass */ + i = 0; +diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c +index a5bd3c8..8fc22ee 100644 +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -511,6 +511,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct ipt_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -532,6 +534,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct ipt_entry *) + (entry0 + newpos); +diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c +index fb8a146..63f7876 100644 +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -521,6 +521,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct ip6t_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -542,6 +544,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct ip6t_entry *) + (entry0 + newpos); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3135/0.patch b/Patches/Linux_CVEs/CVE-2016-3135/0.patch new file mode 100644 index 00000000..97ba8166 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3135/0.patch @@ -0,0 +1,34 @@ +From d157bd761585605b7882935ffb86286919f62ea1 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Thu, 10 Mar 2016 01:56:23 +0100 +Subject: netfilter: x_tables: check for size overflow + +Ben Hawkes says: + integer overflow in xt_alloc_table_info, which on 32-bit systems can + lead to small structure allocation and a copy_from_user based heap + corruption. + +Reported-by: Ben Hawkes +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +--- + net/netfilter/x_tables.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c +index d0cd2b9..582c9cf 100644 +--- a/net/netfilter/x_tables.c ++++ b/net/netfilter/x_tables.c +@@ -659,6 +659,9 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size) + struct xt_table_info *info = NULL; + size_t sz = sizeof(*info) + size; + ++ if (sz < sizeof(*info)) ++ return NULL; ++ + /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ + if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages) + return NULL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3136/0.patch b/Patches/Linux_CVEs/CVE-2016-3136/0.patch new file mode 100644 index 00000000..2809018d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3136/0.patch @@ -0,0 +1,49 @@ +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/Linux_CVEs/CVE-2016-3136/1.patch b/Patches/Linux_CVEs/CVE-2016-3136/1.patch new file mode 100644 index 00000000..52e03439 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3136/1.patch @@ -0,0 +1,53 @@ +From 2633b8df3dff0377066fb32feb8ef06ae834d7ff Mon Sep 17 00:00:00 2001 +From: Badhri Jagan Sridharan +Date: Tue, 30 Aug 2016 13:33:55 -0700 +Subject: UPSTREAM: USB: mct_u232: add sanity checking in probe + +commit 4e9a0b05257f29cf4b75f3209243ed71614d062e upstream. + +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 +BUG: 28242610 +Signed-off-by: Oliver Neukum +[johan: add error message ] +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +Signed-off-by: Badhri Jagan Sridharan +Change-Id: I284ad648c2087c34a098d67e0cc6d948a568413c +--- + 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 6a15adf..c14c29f 100644 +--- a/drivers/usb/serial/mct_u232.c ++++ b/drivers/usb/serial/mct_u232.c +@@ -377,14 +377,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/Linux_CVEs/CVE-2016-3137/0.patch b/Patches/Linux_CVEs/CVE-2016-3137/0.patch new file mode 100644 index 00000000..c54514e3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3137/0.patch @@ -0,0 +1,49 @@ +From c55aee1bf0e6b6feec8b2927b43f7a09a6d5f754 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 31 Mar 2016 12:04:25 -0400 +Subject: USB: cypress_m8: add endpoint sanity check + +An attack using missing endpoints exists. + +CVE-2016-3137 + +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/cypress_m8.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c +index b283eb8..bbeeb2b 100644 +--- a/drivers/usb/serial/cypress_m8.c ++++ b/drivers/usb/serial/cypress_m8.c +@@ -447,6 +447,11 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) + struct usb_serial *serial = port->serial; + struct cypress_private *priv; + ++ if (!port->interrupt_out_urb || !port->interrupt_in_urb) { ++ dev_err(&port->dev, "required endpoint is missing\n"); ++ return -ENODEV; ++ } ++ + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +@@ -606,12 +611,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) + cypress_set_termios(tty, port, &priv->tmp_termios); + + /* setup the port and start reading from the device */ +- if (!port->interrupt_in_urb) { +- dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n", +- __func__); +- return -1; +- } +- + usb_fill_int_urb(port->interrupt_in_urb, serial->dev, + usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), + port->interrupt_in_urb->transfer_buffer, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3137/1.patch b/Patches/Linux_CVEs/CVE-2016-3137/1.patch new file mode 100644 index 00000000..9e9f9b88 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3137/1.patch @@ -0,0 +1,53 @@ +From 7a17891b0194ba11f7ee15a18e545808b0d27495 Mon Sep 17 00:00:00 2001 +From: Badhri Jagan Sridharan +Date: Mon, 29 Aug 2016 17:33:52 -0700 +Subject: UPSTREAM: USB: cypress_m8: add endpoint sanity check + +commit c55aee1bf0e6b6feec8b2927b43f7a09a6d5f754 upstream. + +An attack using missing endpoints exists. + +CVE-2016-3137 + +BUG: 28242610 +Signed-off-by: Oliver Neukum +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Badhri Jagan Sridharan +Change-Id: I1cc7957a5924175d24f12fdc41162ece67c907e5 +--- + drivers/usb/serial/cypress_m8.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c +index 08212019..09f0f63 100644 +--- a/drivers/usb/serial/cypress_m8.c ++++ b/drivers/usb/serial/cypress_m8.c +@@ -449,6 +449,11 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) + struct usb_serial *serial = port->serial; + struct cypress_private *priv; + ++ if (!port->interrupt_out_urb || !port->interrupt_in_urb) { ++ dev_err(&port->dev, "required endpoint is missing\n"); ++ return -ENODEV; ++ } ++ + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +@@ -606,12 +611,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) + cypress_set_termios(tty, port, &priv->tmp_termios); + + /* setup the port and start reading from the device */ +- if (!port->interrupt_in_urb) { +- dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n", +- __func__); +- return -1; +- } +- + usb_fill_int_urb(port->interrupt_in_urb, serial->dev, + usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), + port->interrupt_in_urb->transfer_buffer, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3138/0.patch b/Patches/Linux_CVEs/CVE-2016-3138/0.patch new file mode 100644 index 00000000..0abd439f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3138/0.patch @@ -0,0 +1,34 @@ +From 8835ba4a39cf53f705417b3b3a94eb067673f2c9 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Tue, 15 Mar 2016 10:14:04 +0100 +Subject: USB: cdc-acm: more sanity checking + +An attack has become available which pretends to be a quirky +device circumventing normal sanity checks and crashes the kernel +by an insufficient number of interfaces. This patch adds a check +to the code path for quirky devices. + +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/class/cdc-acm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 1d2c99a..83fd30b 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1179,6 +1179,9 @@ static int acm_probe(struct usb_interface *intf, + if (quirks == NO_UNION_NORMAL) { + data_interface = usb_ifnum_to_if(usb_dev, 1); + control_interface = usb_ifnum_to_if(usb_dev, 0); ++ /* we would crash */ ++ if (!data_interface || !control_interface) ++ return -ENODEV; + goto skip_normal_probe; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3138/1.patch b/Patches/Linux_CVEs/CVE-2016-3138/1.patch new file mode 100644 index 00000000..eee71747 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3138/1.patch @@ -0,0 +1,39 @@ +From 801c5f937ef7edb23e411bc00d3695496b89dca2 Mon Sep 17 00:00:00 2001 +From: Badhri Jagan Sridharan +Date: Tue, 30 Aug 2016 13:39:02 -0700 +Subject: UPSTREAM: USB: cdc-acm: more sanity checking + +commit 8835ba4a39cf53f705417b3b3a94eb067673f2c9 upstream. + +An attack has become available which pretends to be a quirky +device circumventing normal sanity checks and crashes the kernel +by an insufficient number of interfaces. This patch adds a check +to the code path for quirky devices. + +BUG: 28242610 + +Signed-off-by: Oliver Neukum +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Badhri Jagan Sridharan +Change-Id: I9a5f7f3c704b65e866335054f470451fcfae9d1c +--- + drivers/usb/class/cdc-acm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 9b1cbcf..f519d28 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -972,6 +972,9 @@ static int acm_probe(struct usb_interface *intf, + if (quirks == NO_UNION_NORMAL) { + data_interface = usb_ifnum_to_if(usb_dev, 1); + control_interface = usb_ifnum_to_if(usb_dev, 0); ++ /* we would crash */ ++ if (!data_interface || !control_interface) ++ return -ENODEV; + goto skip_normal_probe; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3140/0.patch b/Patches/Linux_CVEs/CVE-2016-3140/0.patch new file mode 100644 index 00000000..21067f69 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3140/0.patch @@ -0,0 +1,54 @@ +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/Linux_CVEs/CVE-2016-3140/1.patch b/Patches/Linux_CVEs/CVE-2016-3140/1.patch new file mode 100644 index 00000000..bd2011bc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3140/1.patch @@ -0,0 +1,57 @@ +From 129e6372f40a423bcded0a6dae547205edf652fb 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 + +commit 5a07975ad0a36708c6b0a5b9fea1ff811d0b0c1f upstream. + +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 +Signed-off-by: Willy Tarreau +--- + 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 7b807d3..8c34d9c 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -1253,8 +1253,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/Linux_CVEs/CVE-2016-3156/0.patch b/Patches/Linux_CVEs/CVE-2016-3156/0.patch new file mode 100644 index 00000000..176b4f71 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3156/0.patch @@ -0,0 +1,97 @@ +From fbd40ea0180a2d328c5adc61414dc8bab9335ce2 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Sun, 13 Mar 2016 23:28:00 -0400 +Subject: ipv4: Don't do expensive useless work during inetdev destroy. + +When an inetdev is destroyed, every address assigned to the interface +is removed. And in this scenerio we do two pointless things which can +be very expensive if the number of assigned interfaces is large: + +1) Address promotion. We are deleting all addresses, so there is no + point in doing this. + +2) A full nf conntrack table purge for every address. We only need to + do this once, as is already caught by the existing + masq_dev_notifier so masq_inet_event() can skip this. + +Reported-by: Solar Designer +Signed-off-by: David S. Miller +Tested-by: Cyrill Gorcunov +--- + net/ipv4/devinet.c | 4 ++++ + net/ipv4/fib_frontend.c | 4 ++++ + net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 12 ++++++++++-- + 3 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c +index 65e76a4..e333bc8 100644 +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -334,6 +334,9 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, + + ASSERT_RTNL(); + ++ if (in_dev->dead) ++ goto no_promotions; ++ + /* 1. Deleting primary ifaddr forces deletion all secondaries + * unless alias promotion is set + **/ +@@ -380,6 +383,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, + fib_del_ifaddr(ifa, ifa1); + } + ++no_promotions: + /* 2. Unlink it */ + + *ifap = ifa1->ifa_next; +diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 4734475..21add55 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -922,6 +922,9 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim) + subnet = 1; + } + ++ if (in_dev->dead) ++ goto no_promotions; ++ + /* Deletion is more complicated than add. + * We should take care of not to delete too much :-) + * +@@ -997,6 +1000,7 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim) + } + } + ++no_promotions: + if (!(ok & BRD_OK)) + fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); + if (subnet && ifa->ifa_prefixlen < 31) { +diff --git a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +index c6eb421..ea91058 100644 +--- a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c ++++ b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +@@ -108,10 +108,18 @@ static int masq_inet_event(struct notifier_block *this, + unsigned long event, + void *ptr) + { +- struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; ++ struct in_device *idev = ((struct in_ifaddr *)ptr)->ifa_dev; + struct netdev_notifier_info info; + +- netdev_notifier_info_init(&info, dev); ++ /* The masq_dev_notifier will catch the case of the device going ++ * down. So if the inetdev is dead and being destroyed we have ++ * no work to do. Otherwise this is an individual address removal ++ * and we have to perform the flush. ++ */ ++ if (idev->dead) ++ return NOTIFY_DONE; ++ ++ netdev_notifier_info_init(&info, idev->dev); + return masq_device_event(this, event, &info); + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3672/0.patch b/Patches/Linux_CVEs/CVE-2016-3672/0.patch new file mode 100644 index 00000000..483f87d7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3672/0.patch @@ -0,0 +1,95 @@ +From d6dee0ccda11e6d9f8b47acd112b399d8afd34bc Mon Sep 17 00:00:00 2001 +From: Hector Marco-Gisbert +Date: Thu, 10 Mar 2016 20:51:00 +0100 +Subject: [PATCH] UPSTREAM: x86/mm/32: Enable full randomization on i386 and + X86_32 + +Currently on i386 and on X86_64 when emulating X86_32 in legacy mode, only +the stack and the executable are randomized but not other mmapped files + +libraries, vDSO and mmap requests on i386 and in X86_32 in legacy mode. + +By default on i386 there are 8 bits for the randomization of the libraries, +vDSO and mmaps which only uses 1MB of VA. + +This patch preserves the original randomness, using 1MB of VA out of 3GB or +4GB. We think that 1MB out of 3GB is not a big cost for having the ASLR. + +The first obvious security benefit is that all objects are randomized (not +only the stack and the executable) in legacy mode which highly increases +the ASLR effectiveness, otherwise the attackers may use these +non-randomized areas. But also sensitive setuid/setgid applications are +more secure because currently, attackers can disable the randomization of +these applications by setting the ulimit stack to "unlimited". This is a +very old and widely known trick to disable the ASLR in i386 which has been +allowed for too long. + +Another trick used to disable the ASLR was to set the ADDR_NO_RANDOMIZE +personality flag, but fortunately this doesn't work on setuid/setgid +applications because there is security checks which clear Security-relevant +flags. + +This patch always randomizes the mmap_legacy_base address, removing the +possibility to disable the ASLR by setting the stack to "unlimited". + +Signed-off-by: Hector Marco-Gisbert +Acked-by: Ismael Ripoll Ripoll +Acked-by: Kees Cook +Acked-by: Arjan van de Ven +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: akpm@linux-foundation.org +Cc: kees Cook +Link: http://lkml.kernel.org/r/1457639460-5242-1-git-send-email-hecmargi@upv.es +Signed-off-by: Ingo Molnar + +Bug: 28763575 +Change-Id: Icd128489c3c196ade64f79d4ea898d29f8471baf +(cherry picked from commit 8b8addf891de8a00e4d39fc32f93f7c5eb8feceb) +--- + arch/x86/mm/mmap.c | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index 084c36f6b4e3..47287ea3f080 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -95,30 +95,23 @@ static unsigned long mmap_base(void) + } + + /* +- * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 +- * does, but not when emulating X86_32 +- */ +-static unsigned long mmap_legacy_base(void) +-{ +- if (mmap_is_ia32()) +- return TASK_UNMAPPED_BASE; +- else +- return TASK_UNMAPPED_BASE + mmap_rnd(); +-} +- +-/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ + void arch_pick_mmap_layout(struct mm_struct *mm) + { +- mm->mmap_legacy_base = mmap_legacy_base(); +- mm->mmap_base = mmap_base(); ++ unsigned long random_factor = 0UL; ++ ++ if (current->flags & PF_RANDOMIZE) ++ random_factor = mmap_rnd(); ++ ++ mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor; + + if (mmap_is_legacy()) { + mm->mmap_base = mm->mmap_legacy_base; + mm->get_unmapped_area = arch_get_unmapped_area; + } else { ++ mm->mmap_base = mmap_base(); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + } + } diff --git a/Patches/Linux_CVEs/CVE-2016-3689/0.patch b/Patches/Linux_CVEs/CVE-2016-3689/0.patch new file mode 100644 index 00000000..5c5c1bce --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3689/0.patch @@ -0,0 +1,40 @@ +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/Linux_CVEs/CVE-2016-3689/1.patch b/Patches/Linux_CVEs/CVE-2016-3689/1.patch new file mode 100644 index 00000000..abc036f7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3689/1.patch @@ -0,0 +1,40 @@ +From 7ca573e32c0a6634d679540314a80d235f224bfb Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 17 Mar 2016 14:00:17 -0700 +Subject: [PATCH] Input: ims-pcu - sanity check against missing interfaces + +[ Upstream commit a0ad220c96692eda76b2e3fd7279f3dcd1d8a8ff ] + +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 +Signed-off-by: Sasha Levin +--- + 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 afed8e2b2f944..41ef29b516f35 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) { diff --git a/Patches/Linux_CVEs/CVE-2016-3768/0.patch b/Patches/Linux_CVEs/CVE-2016-3768/0.patch new file mode 100644 index 00000000..10ad536a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3768/0.patch @@ -0,0 +1,52 @@ +From 84d8c81420aaa7c6cd6f57cb52daccf07b1f7a50 Mon Sep 17 00:00:00 2001 +From: Veena Sambasivan +Date: Thu, 19 May 2016 18:47:15 -0700 +Subject: [PATCH] msm: perf: Do not allocate new hw_event if event is + duplicate. + +During a perf_event_enable, kernel/events/core.c calls pmu->add() which +is platform implementation(arch/arm/kernel/perf_event.c). Due to the +duplicate constraints, arch/arm/mach-msm/perf_event_msm_krait_l2.c +drivers marks the event as OFF but returns TRUE to perf_event.c which +goes ahead and allocates the hw_event and enables it. +Since event is marked OFF, kernel events core will try to enable this event +again during next perf_event_enable. Which results in same event enabled +on multiple hw_events. But during the perf_release, event struct is freed +and only one hw_event is released. This results in dereferencing the +invalid pointer and hence the crash. +Fix this by returning error in case of constraint event duplicate. Hence +avoiding the same event programmed on multiple hw event counters. + +bug: 28172137 +Change-Id: Ia3360be027dfe87ac753191ffe7e0bc947e72455 +Signed-off-by: Arun KS +Signed-off-by: Veena Sambasivan +--- + arch/arm/kernel/perf_event.c | 1 + + arch/arm/mach-msm/perf_event_msm_krait_l2.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c +index 0f288a7c035f9..a0c1e318a7905 100644 +--- a/arch/arm/kernel/perf_event.c ++++ b/arch/arm/kernel/perf_event.c +@@ -240,6 +240,7 @@ armpmu_add(struct perf_event *event, int flags) + pr_err("Event: %llx failed constraint check.\n", + event->attr.config); + event->state = PERF_EVENT_STATE_OFF; ++ err = -EPERM; + goto out; + } + +diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c +index 65a5d2f8e1bcd..cc39b719b33fb 100644 +--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c ++++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c +@@ -468,6 +468,7 @@ static int msm_l2_test_set_ev_constraint(struct perf_event *event) + if (!(event->cpu < 0)) { + event->state = PERF_EVENT_STATE_OFF; + event->attr.constraint_duplicate = 1; ++ err = -EPERM; + } + } + out: diff --git a/Patches/Linux_CVEs/CVE-2016-3775/0.patch b/Patches/Linux_CVEs/CVE-2016-3775/0.patch new file mode 100644 index 00000000..e72588b7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3775/0.patch @@ -0,0 +1,53 @@ +From 8096090858689395a75bbf696ff8276c3c236b98 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Thu, 25 Feb 2016 12:15:48 -0800 +Subject: [PATCH] AIO: properly check iovec sizes + +commit ff19ac8fb71e8a2bf07d61b959062998139c1104 upstream + +In Linus's tree, the iovec code has been reworked massively, but in +older kernels the AIO layer should be checking this before passing the +request on to other layers. + +Many thanks to Ben Hawkes of Google Project Zero for pointing out the +issue. + +Bug: 28588279 + +Reported-by: Ben Hawkes +Acked-by: Benjamin LaHaise +Tested-by: Willy Tarreau +[backported to 3.10 - willy] +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +Change-Id: If539a08b42dd51a473b3f3743f9497e637266a05 +--- + fs/aio.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/fs/aio.c b/fs/aio.c +index ded94c4fa30d3..9798d4edfd8f2 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -977,12 +977,17 @@ static ssize_t aio_setup_vectored_rw(int rw, struct kiocb *kiocb, bool compat) + + static ssize_t aio_setup_single_vector(int rw, struct kiocb *kiocb) + { +- if (unlikely(!access_ok(!rw, kiocb->ki_buf, kiocb->ki_nbytes))) +- return -EFAULT; ++ size_t len = kiocb->ki_nbytes; ++ ++ if (len > MAX_RW_COUNT) ++ len = MAX_RW_COUNT; ++ ++ if (unlikely(!access_ok(!rw, kiocb->ki_buf, len))) ++ return -EFAULT; + + kiocb->ki_iovec = &kiocb->ki_inline_vec; + kiocb->ki_iovec->iov_base = kiocb->ki_buf; +- kiocb->ki_iovec->iov_len = kiocb->ki_nbytes; ++ kiocb->ki_iovec->iov_len = len; + kiocb->ki_nr_segs = 1; + return 0; + } diff --git a/Patches/Linux_CVEs/CVE-2016-3775/1.patch b/Patches/Linux_CVEs/CVE-2016-3775/1.patch new file mode 100644 index 00000000..28901d3d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3775/1.patch @@ -0,0 +1,48 @@ +From b1568c363c54fa3aa98b1cfa7c535115950bec0c Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Fri, 19 Feb 2016 17:36:21 -0800 +Subject: [PATCH] BACKPORT: AIO: properly check iovec sizes + +In Linus's tree, the iovec code has been reworked massively, but in +older kernels the AIO layer should be checking this before passing the +request on to other layers. + +Many thanks to Ben Hawkes of Google Project Zero for pointing out the +issue. + +Reported-by: Ben Hawkes +Acked-by: Benjamin LaHaise +Tested-by: Willy Tarreau +[backported to 3.10 - willy] +Signed-off-by: Greg Kroah-Hartman + +(cherry picked from commit ff19ac8fb71e8a2bf07d61b959062998139c1104) +Change-Id: I3150b93cf125b03add473dfded89757531b4eb13 +Signed-off-by: Thierry Strudel +--- + fs/aio.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/aio.c b/fs/aio.c +index 58caa7e5d81c6..d9912555aacc8 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -1354,11 +1354,16 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb, + unsigned long *nr_segs, + struct iovec *iovec) + { +- if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes))) ++ size_t len = kiocb->ki_nbytes; ++ ++ if (len > MAX_RW_COUNT) ++ len = MAX_RW_COUNT; ++ ++ if (unlikely(!access_ok(!rw, buf, len))) + return -EFAULT; + + iovec->iov_base = buf; +- iovec->iov_len = kiocb->ki_nbytes; ++ iovec->iov_len = len; + *nr_segs = 1; + return 0; + } diff --git a/Patches/Linux_CVEs/CVE-2016-3775/2.patch b/Patches/Linux_CVEs/CVE-2016-3775/2.patch new file mode 100644 index 00000000..d707f1d2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3775/2.patch @@ -0,0 +1,108 @@ +From dc18eac80caaa12ff7072df9fe857b921e8c26c7 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Mon, 21 May 2012 16:06:20 -0700 +Subject: [PATCH] UPSTREAM: 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. + +Bug: 28939037 +Reported-by: Manish Honap +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +(cherry picked from commit a70b52ec1aaeaf60f4739edb1b422827cb6f3893) + +Change-Id: I2e182e973b44ba97c45c80d52d8a0b7c32a72750 +--- + fs/aio.c | 30 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 16 deletions(-) + +diff --git a/fs/aio.c b/fs/aio.c +index 67a6db3e1b6f8..e7f2fad7b4ce7 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 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat) + 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; diff --git a/Patches/Linux_CVEs/CVE-2016-3813/0.patch b/Patches/Linux_CVEs/CVE-2016-3813/0.patch new file mode 100644 index 00000000..7c2f848a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3813/0.patch @@ -0,0 +1,51 @@ +From 3c0add95808fdada98ba0ab465c0b4ba49e71d26 Mon Sep 17 00:00:00 2001 +From: Vijayavardhan Vennapusa +Date: Thu, 5 May 2016 14:37:08 +0530 +Subject: USB: dwc3: debugfs: Add boundary check in dwc3_store_ep_num() + +User can pass arguments as part of write to requests and endpoint number +will be calculated based on the arguments. There is a chance that driver +can access ep structue that is not allocated due to invalid arguments +passed by user. Hence fix the issue by having check and return error in +case of invalid arguments. + +Change-Id: I060ea878b55ce0f9983b91c50e58718c8a2c2fa1 +Signed-off-by: Vijayavardhan Vennapusa +--- + drivers/usb/dwc3/debugfs.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c +index 857b413..fc3f959 100644 +--- a/drivers/usb/dwc3/debugfs.c ++++ b/drivers/usb/dwc3/debugfs.c +@@ -650,7 +650,7 @@ static ssize_t dwc3_store_ep_num(struct file *file, const char __user *ubuf, + struct seq_file *s = file->private_data; + struct dwc3 *dwc = s->private; + char kbuf[10]; +- unsigned int num, dir; ++ unsigned int num, dir, temp; + unsigned long flags; + + memset(kbuf, 0, 10); +@@ -661,8 +661,16 @@ static ssize_t dwc3_store_ep_num(struct file *file, const char __user *ubuf, + if (sscanf(kbuf, "%u %u", &num, &dir) != 2) + return -EINVAL; + ++ if (dir != 0 && dir != 1) ++ return -EINVAL; ++ ++ temp = (num << 1) + dir; ++ if (temp >= (dwc->num_in_eps + dwc->num_out_eps) || ++ temp >= DWC3_ENDPOINTS_NUM) ++ return -EINVAL; ++ + spin_lock_irqsave(&dwc->lock, flags); +- ep_num = (num << 1) + dir; ++ ep_num = temp; + spin_unlock_irqrestore(&dwc->lock, flags); + + return count; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3841/0.patch b/Patches/Linux_CVEs/CVE-2016-3841/0.patch new file mode 100644 index 00000000..24a2041c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3841/0.patch @@ -0,0 +1,557 @@ +From a6a295a31168eafb4049a81f2db7bedc339da75e Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 29 Nov 2015 19:37:57 -0800 +Subject: [PATCH] ipv6: add complete rcu protection around np->opt + +[ Upstream commit 45f6fad84cc305103b28d73482b344d7f5b76f39 ] + +This patch addresses multiple problems : + +UDP/RAW sendmsg() need to get a stable struct ipv6_txoptions +while socket is not locked : Other threads can change np->opt +concurrently. Dmitry posted a syzkaller +(http://github.com/google/syzkaller) program desmonstrating +use-after-free. + +Starting with TCP/DCCP lockless listeners, tcp_v6_syn_recv_sock() +and dccp_v6_request_recv_sock() also need to use RCU protection +to dereference np->opt once (before calling ipv6_dup_options()) + +This patch adds full RCU protection to np->opt + +BUG: 28746669 + +Change-Id: I207da29ac48bb6dd7c40d65f9e27c4e3ff508da0 +Reported-by: Dmitry Vyukov +Signed-off-by: Eric Dumazet +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +Signed-off-by: Pierre Imai +--- + include/linux/ipv6.h | 2 +- + include/net/ipv6.h | 21 ++++++++++++++++++++- + net/dccp/ipv6.c | 39 +++++++++++++++++++++------------------ + net/ipv6/af_inet6.c | 12 +++++++++--- + net/ipv6/datagram.c | 4 +++- + net/ipv6/exthdrs.c | 3 ++- + net/ipv6/inet6_connection_sock.c | 11 ++++++++--- + net/ipv6/ipv6_sockglue.c | 36 ++++++++++++++++++++++++------------ + net/ipv6/raw.c | 8 ++++++-- + net/ipv6/syncookies.c | 2 +- + net/ipv6/tcp_ipv6.c | 28 +++++++++++++++------------- + net/ipv6/udp.c | 8 ++++++-- + 12 files changed, 116 insertions(+), 58 deletions(-) + +diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h +index d5041862ed6cc..8e3f2cb7d7cf1 100644 +--- a/include/linux/ipv6.h ++++ b/include/linux/ipv6.h +@@ -382,7 +382,7 @@ struct ipv6_pinfo { + struct ipv6_ac_socklist *ipv6_ac_list; + struct ipv6_fl_socklist *ipv6_fl_list; + +- struct ipv6_txoptions *opt; ++ struct ipv6_txoptions __rcu *opt; + struct sk_buff *pktoptions; + struct sk_buff *rxpmtu; + struct { +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index f3d9b54e81d4d..1f455db905900 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -203,6 +203,7 @@ extern rwlock_t ip6_ra_lock; + */ + + struct ipv6_txoptions { ++ atomic_t refcnt; + /* Length of this structure */ + int tot_len; + +@@ -215,7 +216,7 @@ struct ipv6_txoptions { + struct ipv6_opt_hdr *dst0opt; + struct ipv6_rt_hdr *srcrt; /* Routing Header */ + struct ipv6_opt_hdr *dst1opt; +- ++ struct rcu_head rcu; + /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */ + }; + +@@ -241,6 +242,24 @@ struct ipv6_fl_socklist { + struct ip6_flowlabel *fl; + }; + ++static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np) ++{ ++ struct ipv6_txoptions *opt; ++ ++ rcu_read_lock(); ++ opt = rcu_dereference(np->opt); ++ if (opt && !atomic_inc_not_zero(&opt->refcnt)) ++ opt = NULL; ++ rcu_read_unlock(); ++ return opt; ++} ++ ++static inline void txopt_put(struct ipv6_txoptions *opt) ++{ ++ if (opt && atomic_dec_and_test(&opt->refcnt)) ++ kfree_rcu(opt, rcu); ++} ++ + extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label); + extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, + struct ip6_flowlabel * fl, +diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c +index 4dc588f520e04..95fd5ec945f03 100644 +--- a/net/dccp/ipv6.c ++++ b/net/dccp/ipv6.c +@@ -253,9 +253,9 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, + fl6.fl6_sport = inet_rsk(req)->loc_port; + security_req_classify_flow(req, flowi6_to_flowi(&fl6)); + +- opt = np->opt; +- +- final_p = fl6_update_dst(&fl6, opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); + if (IS_ERR(dst)) { +@@ -272,13 +272,14 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, + &ireq6->loc_addr, + &ireq6->rmt_addr); + fl6.daddr = ireq6->rmt_addr; +- err = ip6_xmit(sk, skb, &fl6, opt, np->tclass); ++ rcu_read_lock(); ++ err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), ++ np->tclass); ++ rcu_read_unlock(); + err = net_xmit_eval(err); + } + + done: +- if (opt != NULL && opt != np->opt) +- sock_kfree_s(sk, opt, opt->tot_len); + dst_release(dst); + return err; + } +@@ -469,6 +470,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, + { + struct inet6_request_sock *ireq6 = inet6_rsk(req); + struct ipv6_pinfo *newnp, *np = inet6_sk(sk); ++ struct ipv6_txoptions *opt; + struct inet_sock *newinet; + struct dccp6_sock *newdp6; + struct sock *newsk; +@@ -594,16 +596,16 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, + * Yes, keeping reference count would be much more clever, but we make + * one more one thing there: reattach optmem to newsk. + */ +- if (opt != NULL) { +- newnp->opt = ipv6_dup_options(newsk, opt); +- if (opt != np->opt) +- sock_kfree_s(sk, opt, opt->tot_len); +- } + ++ opt = rcu_dereference(np->opt); ++ if (opt) { ++ opt = ipv6_dup_options(newsk, opt); ++ RCU_INIT_POINTER(newnp->opt, opt); ++ } + inet_csk(newsk)->icsk_ext_hdr_len = 0; +- if (newnp->opt != NULL) +- inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + +- newnp->opt->opt_flen); ++ if (opt) ++ inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + ++ opt->opt_flen; + + dccp_sync_mss(newsk, dst_mtu(dst)); + +@@ -856,6 +858,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + struct ipv6_pinfo *np = inet6_sk(sk); + struct dccp_sock *dp = dccp_sk(sk); + struct in6_addr *saddr = NULL, *final_p, final; ++ struct ipv6_txoptions *opt; + struct flowi6 fl6; + struct dst_entry *dst; + int addr_type; +@@ -958,7 +961,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + fl6.fl6_sport = inet->inet_sport; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ final_p = fl6_update_dst(&fl6, opt, &final); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); + if (IS_ERR(dst)) { +@@ -978,9 +982,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + __ip6_dst_store(sk, dst, NULL, NULL); + + icsk->icsk_ext_hdr_len = 0; +- if (np->opt != NULL) +- icsk->icsk_ext_hdr_len = (np->opt->opt_flen + +- np->opt->opt_nflen); ++ if (opt) ++ icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; + + inet->inet_dport = usin->sin6_port; + +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index 296886bff7348..69b587e3a5cbb 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -448,8 +448,11 @@ void inet6_destroy_sock(struct sock *sk) + + /* Free tx options */ + +- if ((opt = xchg(&np->opt, NULL)) != NULL) +- sock_kfree_s(sk, opt, opt->tot_len); ++ opt = xchg((__force struct ipv6_txoptions **)&np->opt, NULL); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + } + + EXPORT_SYMBOL_GPL(inet6_destroy_sock); +@@ -705,7 +708,10 @@ int inet6_sk_rebuild_header(struct sock *sk) + fl6.flowi6_uid = sock_i_uid(sk); + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), ++ &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); + if (IS_ERR(dst)) { +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index ae4d713ac88d8..2659d0028bb12 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -167,8 +167,10 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- opt = flowlabel ? flowlabel->opt : np->opt; ++ rcu_read_lock(); ++ opt = flowlabel ? flowlabel->opt : rcu_dereference(np->opt); + final_p = fl6_update_dst(&fl6, opt, &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); + err = 0; +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index 3d641b6e9b092..e66773850e50d 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -748,6 +748,7 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt) + *((char**)&opt2->dst1opt) += dif; + if (opt2->srcrt) + *((char**)&opt2->srcrt) += dif; ++ atomic_set(&opt2->refcnt, 1); + } + return opt2; + } +@@ -812,7 +813,7 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, + return ERR_PTR(-ENOBUFS); + + memset(opt2, 0, tot_len); +- ++ atomic_set(&opt2->refcnt, 1); + opt2->tot_len = tot_len; + p = (char *)(opt2 + 1); + +diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c +index aefc8b7180951..67aa2c2b502c9 100644 +--- a/net/ipv6/inet6_connection_sock.c ++++ b/net/ipv6/inet6_connection_sock.c +@@ -66,7 +66,9 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_TCP; + fl6.daddr = treq->rmt_addr; +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + fl6.saddr = treq->loc_addr; + fl6.flowi6_oif = sk->sk_bound_dev_if; + fl6.flowi6_mark = inet_rsk(req)->ir_mark; +@@ -227,7 +229,9 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) + fl6.flowi6_uid = sock_i_uid(sk); + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + + dst = __inet6_csk_dst_check(sk, np->dst_cookie); + +@@ -250,7 +254,8 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) + /* Restore final destination back after routing done */ + fl6.daddr = np->daddr; + +- res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); ++ res = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), ++ np->tclass); + rcu_read_unlock(); + return res; + } +diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c +index 63dd1f89ed7de..601360e6bb839 100644 +--- a/net/ipv6/ipv6_sockglue.c ++++ b/net/ipv6/ipv6_sockglue.c +@@ -110,10 +110,12 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk, + icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; + icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); + } +- opt = xchg(&inet6_sk(sk)->opt, opt); ++ opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt, ++ opt); + } else { + spin_lock(&sk->sk_dst_lock); +- opt = xchg(&inet6_sk(sk)->opt, opt); ++ opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt, ++ opt); + spin_unlock(&sk->sk_dst_lock); + } + sk_dst_reset(sk); +@@ -213,9 +215,12 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + sk->sk_socket->ops = &inet_dgram_ops; + sk->sk_family = PF_INET; + } +- opt = xchg(&np->opt, NULL); +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ opt = xchg((__force struct ipv6_txoptions **)&np->opt, ++ NULL); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + pktopt = xchg(&np->pktoptions, NULL); + kfree_skb(pktopt); + +@@ -384,7 +389,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) + break; + +- opt = ipv6_renew_options(sk, np->opt, optname, ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ opt = ipv6_renew_options(sk, opt, optname, + (struct ipv6_opt_hdr __user *)optval, + optlen); + if (IS_ERR(opt)) { +@@ -413,8 +419,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + retv = 0; + opt = ipv6_update_options(sk, opt); + sticky_done: +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + break; + } + +@@ -467,6 +475,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + break; + + memset(opt, 0, sizeof(*opt)); ++ atomic_set(&opt->refcnt, 1); + opt->tot_len = sizeof(*opt) + optlen; + retv = -EFAULT; + if (copy_from_user(opt+1, optval, optlen)) +@@ -483,8 +492,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + retv = 0; + opt = ipv6_update_options(sk, opt); + done: +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + break; + } + case IPV6_UNICAST_HOPS: +@@ -1084,10 +1095,11 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, + case IPV6_RTHDR: + case IPV6_DSTOPTS: + { ++ struct ipv6_txoptions *opt; + + lock_sock(sk); +- len = ipv6_getsockopt_sticky(sk, np->opt, +- optname, optval, len); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len); + release_sock(sk); + /* check if ipv6_getsockopt_sticky() returns err code */ + if (len < 0) +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 49ec3f8e7ceaa..dbe4e09ee7c5f 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -728,6 +728,7 @@ static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg) + static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len) + { ++ struct ipv6_txoptions *opt_to_free = NULL; + struct ipv6_txoptions opt_space; + struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; + struct in6_addr *daddr, *final_p, final; +@@ -835,8 +836,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + if (!(opt->opt_nflen|opt->opt_flen)) + opt = NULL; + } +- if (opt == NULL) +- opt = np->opt; ++ if (!opt) { ++ opt = txopt_get(np); ++ opt_to_free = opt; ++ } + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); +@@ -903,6 +906,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + dst_release(dst); + out: + fl6_sock_release(flowlabel); ++ txopt_put(opt_to_free); + return err<0?err:len; + do_confirm: + dst_confirm(dst); +diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c +index af939afeae226..b57996a4fd66d 100644 +--- a/net/ipv6/syncookies.c ++++ b/net/ipv6/syncookies.c +@@ -240,7 +240,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_TCP; + fl6.daddr = ireq6->rmt_addr; +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); + fl6.saddr = ireq6->loc_addr; + fl6.flowi6_oif = sk->sk_bound_dev_if; + fl6.flowi6_mark = inet_rsk(req)->ir_mark; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index c4de212ad12c2..c39a2f47dd8c7 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -132,6 +132,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + struct ipv6_pinfo *np = inet6_sk(sk); + struct tcp_sock *tp = tcp_sk(sk); + struct in6_addr *saddr = NULL, *final_p, final; ++ struct ipv6_txoptions *opt; + struct rt6_info *rt; + struct flowi6 fl6; + struct dst_entry *dst; +@@ -253,7 +254,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + fl6.fl6_sport = inet->inet_sport; + fl6.flowi6_uid = sock_i_uid(sk); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ final_p = fl6_update_dst(&fl6, opt, &final); + + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +@@ -296,9 +298,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + } + + icsk->icsk_ext_hdr_len = 0; +- if (np->opt) +- icsk->icsk_ext_hdr_len = (np->opt->opt_flen + +- np->opt->opt_nflen); ++ if (opt) ++ icsk->icsk_ext_hdr_len = opt->opt_flen + ++ opt->opt_nflen; + + tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); + +@@ -516,7 +518,8 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, + __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); + + fl6.daddr = treq->rmt_addr; +- err = ip6_xmit(sk, skb, &fl6, opt, np->tclass); ++ err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), ++ np->tclass); + err = net_xmit_eval(err); + } + +@@ -1243,10 +1246,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, + struct inet6_request_sock *treq; + struct ipv6_pinfo *newnp, *np = inet6_sk(sk); + struct tcp6_sock *newtcp6sk; ++ struct ipv6_txoptions *opt; + struct inet_sock *newinet; + struct tcp_sock *newtp; + struct sock *newsk; +- struct ipv6_txoptions *opt; + #ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; + #endif +@@ -1375,16 +1378,15 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, + but we make one more one thing there: reattach optmem + to newsk. + */ ++ opt = rcu_dereference(np->opt); + if (opt) { +- newnp->opt = ipv6_dup_options(newsk, opt); +- if (opt != np->opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ opt = ipv6_dup_options(newsk, opt); ++ RCU_INIT_POINTER(newnp->opt, opt); + } +- + inet_csk(newsk)->icsk_ext_hdr_len = 0; +- if (newnp->opt) +- inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + +- newnp->opt->opt_flen); ++ if (opt) ++ inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + ++ opt->opt_flen; + + tcp_mtup_init(newsk); + tcp_sync_mss(newsk, dst_mtu(dst)); +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index a20d55dc9c2aa..101d2ba8df281 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -955,6 +955,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; + struct in6_addr *daddr, *final_p, final; + struct ipv6_txoptions *opt = NULL; ++ struct ipv6_txoptions *opt_to_free = NULL; + struct ip6_flowlabel *flowlabel = NULL; + struct flowi6 fl6; + struct dst_entry *dst; +@@ -1109,8 +1110,10 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + opt = NULL; + connected = 0; + } +- if (opt == NULL) +- opt = np->opt; ++ if (!opt) { ++ opt = txopt_get(np); ++ opt_to_free = opt; ++ } + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); +@@ -1211,6 +1214,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + out: + dst_release(dst); + fl6_sock_release(flowlabel); ++ txopt_put(opt_to_free); + if (!err) + return len; + /* diff --git a/Patches/Linux_CVEs/CVE-2016-3841/1.patch b/Patches/Linux_CVEs/CVE-2016-3841/1.patch new file mode 100644 index 00000000..22b6dfb3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3841/1.patch @@ -0,0 +1,574 @@ +From 07bd7f369c24d534163ed0f1cffdd461af648732 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 29 Nov 2015 19:37:57 -0800 +Subject: [PATCH] ipv6: add complete rcu protection around np->opt + +[ Upstream commit 45f6fad84cc305103b28d73482b344d7f5b76f39 ] + +This patch addresses multiple problems : + +UDP/RAW sendmsg() need to get a stable struct ipv6_txoptions +while socket is not locked : Other threads can change np->opt +concurrently. Dmitry posted a syzkaller +(http://github.com/google/syzkaller) program desmonstrating +use-after-free. + +Starting with TCP/DCCP lockless listeners, tcp_v6_syn_recv_sock() +and dccp_v6_request_recv_sock() also need to use RCU protection +to dereference np->opt once (before calling ipv6_dup_options()) + +This patch adds full RCU protection to np->opt + +BUG: 28746669 + +Reported-by: Dmitry Vyukov +Signed-off-by: Eric Dumazet +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Jiri Slaby +--- + include/linux/ipv6.h | 2 +- + include/net/ipv6.h | 21 ++++++++++++++++++++- + net/dccp/ipv6.c | 33 +++++++++++++++++++++------------ + net/ipv6/af_inet6.c | 13 +++++++++---- + net/ipv6/datagram.c | 4 +++- + net/ipv6/exthdrs.c | 3 ++- + net/ipv6/inet6_connection_sock.c | 11 ++++++++--- + net/ipv6/ipv6_sockglue.c | 36 ++++++++++++++++++++++++------------ + net/ipv6/raw.c | 8 ++++++-- + net/ipv6/syncookies.c | 2 +- + net/ipv6/tcp_ipv6.c | 28 +++++++++++++++++----------- + net/ipv6/udp.c | 8 ++++++-- + net/l2tp/l2tp_ip6.c | 8 ++++++-- + 13 files changed, 124 insertions(+), 53 deletions(-) + +diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h +index 9f3792c1dcde3..f6f0c3cfd6771 100644 +--- a/include/linux/ipv6.h ++++ b/include/linux/ipv6.h +@@ -222,7 +222,7 @@ struct ipv6_pinfo { + struct ipv6_ac_socklist *ipv6_ac_list; + struct ipv6_fl_socklist __rcu *ipv6_fl_list; + +- struct ipv6_txoptions *opt; ++ struct ipv6_txoptions __rcu *opt; + struct sk_buff *pktoptions; + struct sk_buff *rxpmtu; + struct { +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index 27e9ba47b3040..48c799736152e 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -203,6 +203,7 @@ extern rwlock_t ip6_ra_lock; + */ + + struct ipv6_txoptions { ++ atomic_t refcnt; + /* Length of this structure */ + int tot_len; + +@@ -215,7 +216,7 @@ struct ipv6_txoptions { + struct ipv6_opt_hdr *dst0opt; + struct ipv6_rt_hdr *srcrt; /* Routing Header */ + struct ipv6_opt_hdr *dst1opt; +- ++ struct rcu_head rcu; + /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */ + }; + +@@ -246,6 +247,24 @@ struct ipv6_fl_socklist { + struct rcu_head rcu; + }; + ++static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np) ++{ ++ struct ipv6_txoptions *opt; ++ ++ rcu_read_lock(); ++ opt = rcu_dereference(np->opt); ++ if (opt && !atomic_inc_not_zero(&opt->refcnt)) ++ opt = NULL; ++ rcu_read_unlock(); ++ return opt; ++} ++ ++static inline void txopt_put(struct ipv6_txoptions *opt) ++{ ++ if (opt && atomic_dec_and_test(&opt->refcnt)) ++ kfree_rcu(opt, rcu); ++} ++ + extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label); + extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, + struct ip6_flowlabel * fl, +diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c +index 6cf9f7782ad42..86eedbaf037ff 100644 +--- a/net/dccp/ipv6.c ++++ b/net/dccp/ipv6.c +@@ -235,7 +235,9 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req) + security_req_classify_flow(req, flowi6_to_flowi(&fl6)); + + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); + if (IS_ERR(dst)) { +@@ -252,7 +254,10 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req) + &ireq6->loc_addr, + &ireq6->rmt_addr); + fl6.daddr = ireq6->rmt_addr; +- err = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); ++ rcu_read_lock(); ++ err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), ++ np->tclass); ++ rcu_read_unlock(); + err = net_xmit_eval(err); + } + +@@ -448,6 +453,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, + { + struct inet6_request_sock *ireq6 = inet6_rsk(req); + struct ipv6_pinfo *newnp, *np = inet6_sk(sk); ++ struct ipv6_txoptions *opt; + struct inet_sock *newinet; + struct dccp6_sock *newdp6; + struct sock *newsk; +@@ -571,13 +577,15 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, + * Yes, keeping reference count would be much more clever, but we make + * one more one thing there: reattach optmem to newsk. + */ +- if (np->opt != NULL) +- newnp->opt = ipv6_dup_options(newsk, np->opt); +- ++ opt = rcu_dereference(np->opt); ++ if (opt) { ++ opt = ipv6_dup_options(newsk, opt); ++ RCU_INIT_POINTER(newnp->opt, opt); ++ } + inet_csk(newsk)->icsk_ext_hdr_len = 0; +- if (newnp->opt != NULL) +- inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + +- newnp->opt->opt_flen); ++ if (opt) ++ inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + ++ opt->opt_flen; + + dccp_sync_mss(newsk, dst_mtu(dst)); + +@@ -829,6 +837,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + struct ipv6_pinfo *np = inet6_sk(sk); + struct dccp_sock *dp = dccp_sk(sk); + struct in6_addr *saddr = NULL, *final_p, final; ++ struct ipv6_txoptions *opt; + struct flowi6 fl6; + struct dst_entry *dst; + int addr_type; +@@ -931,7 +940,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + fl6.fl6_sport = inet->inet_sport; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ final_p = fl6_update_dst(&fl6, opt, &final); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); + if (IS_ERR(dst)) { +@@ -951,9 +961,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + __ip6_dst_store(sk, dst, NULL, NULL); + + icsk->icsk_ext_hdr_len = 0; +- if (np->opt != NULL) +- icsk->icsk_ext_hdr_len = (np->opt->opt_flen + +- np->opt->opt_nflen); ++ if (opt) ++ icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; + + inet->inet_dport = usin->sin6_port; + +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index d29ae19ae698f..04e88b508d4e8 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -448,9 +448,11 @@ void inet6_destroy_sock(struct sock *sk) + + /* Free tx options */ + +- opt = xchg(&np->opt, NULL); +- if (opt != NULL) +- sock_kfree_s(sk, opt, opt->tot_len); ++ opt = xchg((__force struct ipv6_txoptions **)&np->opt, NULL); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + } + EXPORT_SYMBOL_GPL(inet6_destroy_sock); + +@@ -697,7 +699,10 @@ int inet6_sk_rebuild_header(struct sock *sk) + fl6.flowi6_uid = sock_i_uid(sk); + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), ++ &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); + if (IS_ERR(dst)) { +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index 2b7cbebcd2b1f..7d766307438c0 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -169,8 +169,10 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- opt = flowlabel ? flowlabel->opt : np->opt; ++ rcu_read_lock(); ++ opt = flowlabel ? flowlabel->opt : rcu_dereference(np->opt); + final_p = fl6_update_dst(&fl6, opt, &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true); + err = 0; +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index 8d67900aa0036..33dbd6c1a00df 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -727,6 +727,7 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt) + *((char **)&opt2->dst1opt) += dif; + if (opt2->srcrt) + *((char **)&opt2->srcrt) += dif; ++ atomic_set(&opt2->refcnt, 1); + } + return opt2; + } +@@ -790,7 +791,7 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, + return ERR_PTR(-ENOBUFS); + + memset(opt2, 0, tot_len); +- ++ atomic_set(&opt2->refcnt, 1); + opt2->tot_len = tot_len; + p = (char *)(opt2 + 1); + +diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c +index 65a46058c8544..157f2b2bb3ee8 100644 +--- a/net/ipv6/inet6_connection_sock.c ++++ b/net/ipv6/inet6_connection_sock.c +@@ -78,7 +78,9 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, + memset(fl6, 0, sizeof(*fl6)); + fl6->flowi6_proto = IPPROTO_TCP; + fl6->daddr = treq->rmt_addr; +- final_p = fl6_update_dst(fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + fl6->saddr = treq->loc_addr; + fl6->flowi6_oif = treq->iif; + fl6->flowi6_mark = inet_rsk(req)->ir_mark; +@@ -215,7 +217,9 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk, + fl6->flowi6_uid = sock_i_uid(sk); + security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); + +- final_p = fl6_update_dst(fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + + dst = __inet6_csk_dst_check(sk, np->dst_cookie); + if (!dst) { +@@ -249,7 +253,8 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) + /* Restore final destination back after routing done */ + fl6.daddr = np->daddr; + +- res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); ++ res = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), ++ np->tclass); + rcu_read_unlock(); + return res; + } +diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c +index d1e2e8ef29c54..f4d2412d9c608 100644 +--- a/net/ipv6/ipv6_sockglue.c ++++ b/net/ipv6/ipv6_sockglue.c +@@ -110,10 +110,12 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk, + icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; + icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); + } +- opt = xchg(&inet6_sk(sk)->opt, opt); ++ opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt, ++ opt); + } else { + spin_lock(&sk->sk_dst_lock); +- opt = xchg(&inet6_sk(sk)->opt, opt); ++ opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt, ++ opt); + spin_unlock(&sk->sk_dst_lock); + } + sk_dst_reset(sk); +@@ -213,9 +215,12 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + sk->sk_socket->ops = &inet_dgram_ops; + sk->sk_family = PF_INET; + } +- opt = xchg(&np->opt, NULL); +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ opt = xchg((__force struct ipv6_txoptions **)&np->opt, ++ NULL); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + pktopt = xchg(&np->pktoptions, NULL); + kfree_skb(pktopt); + +@@ -385,7 +390,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW)) + break; + +- opt = ipv6_renew_options(sk, np->opt, optname, ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ opt = ipv6_renew_options(sk, opt, optname, + (struct ipv6_opt_hdr __user *)optval, + optlen); + if (IS_ERR(opt)) { +@@ -414,8 +420,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + retv = 0; + opt = ipv6_update_options(sk, opt); + sticky_done: +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + break; + } + +@@ -468,6 +476,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + break; + + memset(opt, 0, sizeof(*opt)); ++ atomic_set(&opt->refcnt, 1); + opt->tot_len = sizeof(*opt) + optlen; + retv = -EFAULT; + if (copy_from_user(opt+1, optval, optlen)) +@@ -484,8 +493,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + retv = 0; + opt = ipv6_update_options(sk, opt); + done: +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + break; + } + case IPV6_UNICAST_HOPS: +@@ -1085,10 +1096,11 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, + case IPV6_RTHDR: + case IPV6_DSTOPTS: + { ++ struct ipv6_txoptions *opt; + + lock_sock(sk); +- len = ipv6_getsockopt_sticky(sk, np->opt, +- optname, optval, len); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len); + release_sock(sk); + /* check if ipv6_getsockopt_sticky() returns err code */ + if (len < 0) +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index a9db8d252c9b4..5693cf212e8d7 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -726,6 +726,7 @@ static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg) + static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len) + { ++ struct ipv6_txoptions *opt_to_free = NULL; + struct ipv6_txoptions opt_space; + struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; + struct in6_addr *daddr, *final_p, final; +@@ -833,8 +834,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + if (!(opt->opt_nflen|opt->opt_flen)) + opt = NULL; + } +- if (opt == NULL) +- opt = np->opt; ++ if (!opt) { ++ opt = txopt_get(np); ++ opt_to_free = opt; ++ } + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); +@@ -901,6 +904,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + dst_release(dst); + out: + fl6_sock_release(flowlabel); ++ txopt_put(opt_to_free); + return err<0?err:len; + do_confirm: + dst_confirm(dst); +diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c +index ba8622daffd7e..701d0656a4021 100644 +--- a/net/ipv6/syncookies.c ++++ b/net/ipv6/syncookies.c +@@ -237,7 +237,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_TCP; + fl6.daddr = ireq6->rmt_addr; +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); + fl6.saddr = ireq6->loc_addr; + fl6.flowi6_oif = sk->sk_bound_dev_if; + fl6.flowi6_mark = ireq->ir_mark; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 32d2141a2f7e6..eea4de6b6a4d2 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -133,6 +133,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + struct ipv6_pinfo *np = inet6_sk(sk); + struct tcp_sock *tp = tcp_sk(sk); + struct in6_addr *saddr = NULL, *final_p, final; ++ struct ipv6_txoptions *opt; + struct rt6_info *rt; + struct flowi6 fl6; + struct dst_entry *dst; +@@ -254,7 +255,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + fl6.fl6_sport = inet->inet_sport; + fl6.flowi6_uid = sock_i_uid(sk); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ final_p = fl6_update_dst(&fl6, opt, &final); + + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +@@ -283,9 +285,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + tcp_fetch_timewait_stamp(sk, dst); + + icsk->icsk_ext_hdr_len = 0; +- if (np->opt) +- icsk->icsk_ext_hdr_len = (np->opt->opt_flen + +- np->opt->opt_nflen); ++ if (opt) ++ icsk->icsk_ext_hdr_len = opt->opt_flen + ++ opt->opt_nflen; + + tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); + +@@ -481,7 +483,8 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, + + fl6->daddr = treq->rmt_addr; + skb_set_queue_mapping(skb, queue_mapping); +- err = ip6_xmit(sk, skb, fl6, np->opt, np->tclass); ++ err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), ++ np->tclass); + err = net_xmit_eval(err); + } + +@@ -1090,6 +1093,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, + struct inet6_request_sock *treq; + struct ipv6_pinfo *newnp, *np = inet6_sk(sk); + struct tcp6_sock *newtcp6sk; ++ struct ipv6_txoptions *opt; + struct inet_sock *newinet; + struct tcp_sock *newtp; + struct sock *newsk; +@@ -1223,13 +1227,15 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, + but we make one more one thing there: reattach optmem + to newsk. + */ +- if (np->opt) +- newnp->opt = ipv6_dup_options(newsk, np->opt); +- ++ opt = rcu_dereference(np->opt); ++ if (opt) { ++ opt = ipv6_dup_options(newsk, opt); ++ RCU_INIT_POINTER(newnp->opt, opt); ++ } + inet_csk(newsk)->icsk_ext_hdr_len = 0; +- if (newnp->opt) +- inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + +- newnp->opt->opt_flen); ++ if (opt) ++ inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + ++ opt->opt_flen; + + tcp_mtup_init(newsk); + tcp_sync_mss(newsk, dst_mtu(dst)); +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index a2a6dab2363e5..5720144529d59 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1017,6 +1017,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name; + struct in6_addr *daddr, *final_p, final; + struct ipv6_txoptions *opt = NULL; ++ struct ipv6_txoptions *opt_to_free = NULL; + struct ip6_flowlabel *flowlabel = NULL; + struct flowi6 fl6; + struct dst_entry *dst; +@@ -1171,8 +1172,10 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + opt = NULL; + connected = 0; + } +- if (opt == NULL) +- opt = np->opt; ++ if (!opt) { ++ opt = txopt_get(np); ++ opt_to_free = opt; ++ } + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); +@@ -1273,6 +1276,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + out: + dst_release(dst); + fl6_sock_release(flowlabel); ++ txopt_put(opt_to_free); + if (!err) + return len; + /* +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index e6e8408c9e367..3b61ddd6e4a67 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -485,6 +485,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, + (struct sockaddr_l2tpip6 *) msg->msg_name; + struct in6_addr *daddr, *final_p, final; + struct ipv6_pinfo *np = inet6_sk(sk); ++ struct ipv6_txoptions *opt_to_free = NULL; + struct ipv6_txoptions *opt = NULL; + struct ip6_flowlabel *flowlabel = NULL; + struct dst_entry *dst = NULL; +@@ -575,8 +576,10 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, + opt = NULL; + } + +- if (opt == NULL) +- opt = np->opt; ++ if (!opt) { ++ opt = txopt_get(np); ++ opt_to_free = opt; ++ } + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); +@@ -637,6 +640,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, + dst_release(dst); + out: + fl6_sock_release(flowlabel); ++ txopt_put(opt_to_free); + + return err < 0 ? err : len; + diff --git a/Patches/Linux_CVEs/CVE-2016-3841/2.patch b/Patches/Linux_CVEs/CVE-2016-3841/2.patch new file mode 100644 index 00000000..3fd8d1c8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3841/2.patch @@ -0,0 +1,572 @@ +From 46ddb98e2018a5a62cefa75b3c80882850c91e39 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 29 Nov 2015 19:37:57 -0800 +Subject: [PATCH] ipv6: add complete rcu protection around np->opt + +[ Upstream commit 45f6fad84cc305103b28d73482b344d7f5b76f39 ] + +This patch addresses multiple problems : + +UDP/RAW sendmsg() need to get a stable struct ipv6_txoptions +while socket is not locked : Other threads can change np->opt +concurrently. Dmitry posted a syzkaller +(http://github.com/google/syzkaller) program desmonstrating +use-after-free. + +Starting with TCP/DCCP lockless listeners, tcp_v6_syn_recv_sock() +and dccp_v6_request_recv_sock() also need to use RCU protection +to dereference np->opt once (before calling ipv6_dup_options()) + +This patch adds full RCU protection to np->opt + +Reported-by: Dmitry Vyukov +Signed-off-by: Eric Dumazet +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/linux/ipv6.h | 2 +- + include/net/ipv6.h | 21 ++++++++++++++++++++- + net/dccp/ipv6.c | 33 +++++++++++++++++++++------------ + net/ipv6/af_inet6.c | 13 +++++++++---- + net/ipv6/datagram.c | 4 +++- + net/ipv6/exthdrs.c | 3 ++- + net/ipv6/inet6_connection_sock.c | 11 ++++++++--- + net/ipv6/ipv6_sockglue.c | 36 ++++++++++++++++++++++++------------ + net/ipv6/raw.c | 8 ++++++-- + net/ipv6/syncookies.c | 2 +- + net/ipv6/tcp_ipv6.c | 28 +++++++++++++++++----------- + net/ipv6/udp.c | 8 ++++++-- + net/l2tp/l2tp_ip6.c | 8 ++++++-- + 13 files changed, 124 insertions(+), 53 deletions(-) + +diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h +index ff560537dd61b..2725b03b4ae2d 100644 +--- a/include/linux/ipv6.h ++++ b/include/linux/ipv6.h +@@ -212,7 +212,7 @@ struct ipv6_pinfo { + struct ipv6_ac_socklist *ipv6_ac_list; + struct ipv6_fl_socklist __rcu *ipv6_fl_list; + +- struct ipv6_txoptions *opt; ++ struct ipv6_txoptions __rcu *opt; + struct sk_buff *pktoptions; + struct sk_buff *rxpmtu; + struct { +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index bc56e8a6fbd98..a5169a4e9ef76 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -207,6 +207,7 @@ extern rwlock_t ip6_ra_lock; + */ + + struct ipv6_txoptions { ++ atomic_t refcnt; + /* Length of this structure */ + int tot_len; + +@@ -219,7 +220,7 @@ struct ipv6_txoptions { + struct ipv6_opt_hdr *dst0opt; + struct ipv6_rt_hdr *srcrt; /* Routing Header */ + struct ipv6_opt_hdr *dst1opt; +- ++ struct rcu_head rcu; + /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */ + }; + +@@ -252,6 +253,24 @@ struct ipv6_fl_socklist { + struct rcu_head rcu; + }; + ++static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np) ++{ ++ struct ipv6_txoptions *opt; ++ ++ rcu_read_lock(); ++ opt = rcu_dereference(np->opt); ++ if (opt && !atomic_inc_not_zero(&opt->refcnt)) ++ opt = NULL; ++ rcu_read_unlock(); ++ return opt; ++} ++ ++static inline void txopt_put(struct ipv6_txoptions *opt) ++{ ++ if (opt && atomic_dec_and_test(&opt->refcnt)) ++ kfree_rcu(opt, rcu); ++} ++ + struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label); + struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space, + struct ip6_flowlabel *fl, +diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c +index 6bcaa33cd804d..7bcb223178415 100644 +--- a/net/dccp/ipv6.c ++++ b/net/dccp/ipv6.c +@@ -238,7 +238,9 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req) + security_req_classify_flow(req, flowi6_to_flowi(&fl6)); + + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p); + if (IS_ERR(dst)) { +@@ -255,7 +257,10 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req) + &ireq->ir_v6_loc_addr, + &ireq->ir_v6_rmt_addr); + fl6.daddr = ireq->ir_v6_rmt_addr; +- err = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); ++ rcu_read_lock(); ++ err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), ++ np->tclass); ++ rcu_read_unlock(); + err = net_xmit_eval(err); + } + +@@ -450,6 +455,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, + { + struct inet_request_sock *ireq = inet_rsk(req); + struct ipv6_pinfo *newnp, *np = inet6_sk(sk); ++ struct ipv6_txoptions *opt; + struct inet_sock *newinet; + struct dccp6_sock *newdp6; + struct sock *newsk; +@@ -573,13 +579,15 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, + * Yes, keeping reference count would be much more clever, but we make + * one more one thing there: reattach optmem to newsk. + */ +- if (np->opt != NULL) +- newnp->opt = ipv6_dup_options(newsk, np->opt); +- ++ opt = rcu_dereference(np->opt); ++ if (opt) { ++ opt = ipv6_dup_options(newsk, opt); ++ RCU_INIT_POINTER(newnp->opt, opt); ++ } + inet_csk(newsk)->icsk_ext_hdr_len = 0; +- if (newnp->opt != NULL) +- inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + +- newnp->opt->opt_flen); ++ if (opt) ++ inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + ++ opt->opt_flen; + + dccp_sync_mss(newsk, dst_mtu(dst)); + +@@ -832,6 +840,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + struct ipv6_pinfo *np = inet6_sk(sk); + struct dccp_sock *dp = dccp_sk(sk); + struct in6_addr *saddr = NULL, *final_p, final; ++ struct ipv6_txoptions *opt; + struct flowi6 fl6; + struct dst_entry *dst; + int addr_type; +@@ -933,7 +942,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + fl6.fl6_sport = inet->inet_sport; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ final_p = fl6_update_dst(&fl6, opt, &final); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p); + if (IS_ERR(dst)) { +@@ -953,9 +963,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + __ip6_dst_store(sk, dst, NULL, NULL); + + icsk->icsk_ext_hdr_len = 0; +- if (np->opt != NULL) +- icsk->icsk_ext_hdr_len = (np->opt->opt_flen + +- np->opt->opt_nflen); ++ if (opt) ++ icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; + + inet->inet_dport = usin->sin6_port; + +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index e8c4400f23e9b..05417c330f4ed 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -425,9 +425,11 @@ void inet6_destroy_sock(struct sock *sk) + + /* Free tx options */ + +- opt = xchg(&np->opt, NULL); +- if (opt != NULL) +- sock_kfree_s(sk, opt, opt->tot_len); ++ opt = xchg((__force struct ipv6_txoptions **)&np->opt, NULL); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + } + EXPORT_SYMBOL_GPL(inet6_destroy_sock); + +@@ -656,7 +658,10 @@ int inet6_sk_rebuild_header(struct sock *sk) + fl6.fl6_sport = inet->inet_sport; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), ++ &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p); + if (IS_ERR(dst)) { +diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c +index e069aeb2cf72b..9e3b0b66a4f38 100644 +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -167,8 +167,10 @@ static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int a + + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +- opt = flowlabel ? flowlabel->opt : np->opt; ++ rcu_read_lock(); ++ opt = flowlabel ? flowlabel->opt : rcu_dereference(np->opt); + final_p = fl6_update_dst(&fl6, opt, &final); ++ rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, &fl6, final_p); + err = 0; +diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c +index bfde361b61340..4f08a0f452eb2 100644 +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -727,6 +727,7 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt) + *((char **)&opt2->dst1opt) += dif; + if (opt2->srcrt) + *((char **)&opt2->srcrt) += dif; ++ atomic_set(&opt2->refcnt, 1); + } + return opt2; + } +@@ -790,7 +791,7 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, + return ERR_PTR(-ENOBUFS); + + memset(opt2, 0, tot_len); +- ++ atomic_set(&opt2->refcnt, 1); + opt2->tot_len = tot_len; + p = (char *)(opt2 + 1); + +diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c +index 29b32206e4948..6cc516c825b68 100644 +--- a/net/ipv6/inet6_connection_sock.c ++++ b/net/ipv6/inet6_connection_sock.c +@@ -77,7 +77,9 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk, + memset(fl6, 0, sizeof(*fl6)); + fl6->flowi6_proto = IPPROTO_TCP; + fl6->daddr = ireq->ir_v6_rmt_addr; +- final_p = fl6_update_dst(fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + fl6->saddr = ireq->ir_v6_loc_addr; + fl6->flowi6_oif = ireq->ir_iif; + fl6->flowi6_mark = ireq->ir_mark; +@@ -208,7 +210,9 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk, + fl6->fl6_dport = inet->inet_dport; + security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); + +- final_p = fl6_update_dst(fl6, np->opt, &final); ++ rcu_read_lock(); ++ final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); ++ rcu_read_unlock(); + + dst = __inet6_csk_dst_check(sk, np->dst_cookie); + if (!dst) { +@@ -241,7 +245,8 @@ int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused + /* Restore final destination back after routing done */ + fl6.daddr = sk->sk_v6_daddr; + +- res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); ++ res = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt), ++ np->tclass); + rcu_read_unlock(); + return res; + } +diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c +index e1a9583bb4191..f81fcc09ea6c8 100644 +--- a/net/ipv6/ipv6_sockglue.c ++++ b/net/ipv6/ipv6_sockglue.c +@@ -110,10 +110,12 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk, + icsk->icsk_ext_hdr_len = opt->opt_flen + opt->opt_nflen; + icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); + } +- opt = xchg(&inet6_sk(sk)->opt, opt); ++ opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt, ++ opt); + } else { + spin_lock(&sk->sk_dst_lock); +- opt = xchg(&inet6_sk(sk)->opt, opt); ++ opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt, ++ opt); + spin_unlock(&sk->sk_dst_lock); + } + sk_dst_reset(sk); +@@ -213,9 +215,12 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + sk->sk_socket->ops = &inet_dgram_ops; + sk->sk_family = PF_INET; + } +- opt = xchg(&np->opt, NULL); +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ opt = xchg((__force struct ipv6_txoptions **)&np->opt, ++ NULL); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + pktopt = xchg(&np->pktoptions, NULL); + kfree_skb(pktopt); + +@@ -385,7 +390,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW)) + break; + +- opt = ipv6_renew_options(sk, np->opt, optname, ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ opt = ipv6_renew_options(sk, opt, optname, + (struct ipv6_opt_hdr __user *)optval, + optlen); + if (IS_ERR(opt)) { +@@ -414,8 +420,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + retv = 0; + opt = ipv6_update_options(sk, opt); + sticky_done: +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + break; + } + +@@ -468,6 +476,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + break; + + memset(opt, 0, sizeof(*opt)); ++ atomic_set(&opt->refcnt, 1); + opt->tot_len = sizeof(*opt) + optlen; + retv = -EFAULT; + if (copy_from_user(opt+1, optval, optlen)) +@@ -484,8 +493,10 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, + retv = 0; + opt = ipv6_update_options(sk, opt); + done: +- if (opt) +- sock_kfree_s(sk, opt, opt->tot_len); ++ if (opt) { ++ atomic_sub(opt->tot_len, &sk->sk_omem_alloc); ++ txopt_put(opt); ++ } + break; + } + case IPV6_UNICAST_HOPS: +@@ -1092,10 +1103,11 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, + case IPV6_RTHDR: + case IPV6_DSTOPTS: + { ++ struct ipv6_txoptions *opt; + + lock_sock(sk); +- len = ipv6_getsockopt_sticky(sk, np->opt, +- optname, optval, len); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len); + release_sock(sk); + /* check if ipv6_getsockopt_sticky() returns err code */ + if (len < 0) +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 896af8807979f..a66a67d17ed67 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -735,6 +735,7 @@ static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg) + static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len) + { ++ struct ipv6_txoptions *opt_to_free = NULL; + struct ipv6_txoptions opt_space; + DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); + struct in6_addr *daddr, *final_p, final; +@@ -840,8 +841,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + if (!(opt->opt_nflen|opt->opt_flen)) + opt = NULL; + } +- if (opt == NULL) +- opt = np->opt; ++ if (!opt) { ++ opt = txopt_get(np); ++ opt_to_free = opt; ++ } + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); +@@ -902,6 +905,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, + dst_release(dst); + out: + fl6_sock_release(flowlabel); ++ txopt_put(opt_to_free); + return err < 0 ? err : len; + do_confirm: + dst_confirm(dst); +diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c +index 2f25cb6347ca5..aa9699301ea8e 100644 +--- a/net/ipv6/syncookies.c ++++ b/net/ipv6/syncookies.c +@@ -241,7 +241,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) + memset(&fl6, 0, sizeof(fl6)); + fl6.flowi6_proto = IPPROTO_TCP; + fl6.daddr = ireq->ir_v6_rmt_addr; +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), &final); + fl6.saddr = ireq->ir_v6_loc_addr; + fl6.flowi6_oif = sk->sk_bound_dev_if; + fl6.flowi6_mark = ireq->ir_mark; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index a3f9f11abf4cf..26feadd0b763f 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -134,6 +134,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + struct ipv6_pinfo *np = inet6_sk(sk); + struct tcp_sock *tp = tcp_sk(sk); + struct in6_addr *saddr = NULL, *final_p, final; ++ struct ipv6_txoptions *opt; + struct rt6_info *rt; + struct flowi6 fl6; + struct dst_entry *dst; +@@ -253,7 +254,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + fl6.fl6_dport = usin->sin6_port; + fl6.fl6_sport = inet->inet_sport; + +- final_p = fl6_update_dst(&fl6, np->opt, &final); ++ opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk)); ++ final_p = fl6_update_dst(&fl6, opt, &final); + + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + +@@ -282,9 +284,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + tcp_fetch_timewait_stamp(sk, dst); + + icsk->icsk_ext_hdr_len = 0; +- if (np->opt) +- icsk->icsk_ext_hdr_len = (np->opt->opt_flen + +- np->opt->opt_nflen); ++ if (opt) ++ icsk->icsk_ext_hdr_len = opt->opt_flen + ++ opt->opt_nflen; + + tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); + +@@ -501,7 +503,8 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, + fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); + + skb_set_queue_mapping(skb, queue_mapping); +- err = ip6_xmit(sk, skb, fl6, np->opt, np->tclass); ++ err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), ++ np->tclass); + err = net_xmit_eval(err); + } + +@@ -1052,6 +1055,7 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, + struct inet_request_sock *ireq; + struct ipv6_pinfo *newnp, *np = inet6_sk(sk); + struct tcp6_sock *newtcp6sk; ++ struct ipv6_txoptions *opt; + struct inet_sock *newinet; + struct tcp_sock *newtp; + struct sock *newsk; +@@ -1191,13 +1195,15 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, + but we make one more one thing there: reattach optmem + to newsk. + */ +- if (np->opt) +- newnp->opt = ipv6_dup_options(newsk, np->opt); +- ++ opt = rcu_dereference(np->opt); ++ if (opt) { ++ opt = ipv6_dup_options(newsk, opt); ++ RCU_INIT_POINTER(newnp->opt, opt); ++ } + inet_csk(newsk)->icsk_ext_hdr_len = 0; +- if (newnp->opt) +- inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + +- newnp->opt->opt_flen); ++ if (opt) ++ inet_csk(newsk)->icsk_ext_hdr_len = opt->opt_nflen + ++ opt->opt_flen; + + tcp_sync_mss(newsk, dst_mtu(dst)); + newtp->advmss = dst_metric_advmss(dst); +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index dd530f0e5a8a2..a5ce705026993 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1082,6 +1082,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); + struct in6_addr *daddr, *final_p, final; + struct ipv6_txoptions *opt = NULL; ++ struct ipv6_txoptions *opt_to_free = NULL; + struct ip6_flowlabel *flowlabel = NULL; + struct flowi6 fl6; + struct dst_entry *dst; +@@ -1234,8 +1235,10 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + opt = NULL; + connected = 0; + } +- if (opt == NULL) +- opt = np->opt; ++ if (!opt) { ++ opt = txopt_get(np); ++ opt_to_free = opt; ++ } + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); +@@ -1329,6 +1332,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, + out: + dst_release(dst); + fl6_sock_release(flowlabel); ++ txopt_put(opt_to_free); + if (!err) + return len; + /* +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index 0edb263cc002e..38658826175ca 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -487,6 +487,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, + DECLARE_SOCKADDR(struct sockaddr_l2tpip6 *, lsa, msg->msg_name); + struct in6_addr *daddr, *final_p, final; + struct ipv6_pinfo *np = inet6_sk(sk); ++ struct ipv6_txoptions *opt_to_free = NULL; + struct ipv6_txoptions *opt = NULL; + struct ip6_flowlabel *flowlabel = NULL; + struct dst_entry *dst = NULL; +@@ -576,8 +577,10 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, + opt = NULL; + } + +- if (opt == NULL) +- opt = np->opt; ++ if (!opt) { ++ opt = txopt_get(np); ++ opt_to_free = opt; ++ } + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); +@@ -632,6 +635,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, + dst_release(dst); + out: + fl6_sock_release(flowlabel); ++ txopt_put(opt_to_free); + + return err < 0 ? err : len; + diff --git a/Patches/Linux_CVEs/CVE-2016-3842/0.patch b/Patches/Linux_CVEs/CVE-2016-3842/0.patch new file mode 100644 index 00000000..53de44d3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3842/0.patch @@ -0,0 +1,208 @@ +From 15701ca335357e98a0eb98ef079fe45e3b830591 Mon Sep 17 00:00:00 2001 +From: Sunil Khatri +Date: Mon, 13 Jun 2016 15:45:19 -0700 +Subject: [PATCH] msm: kgsl: Defer adding the mem entry to a process + +If we add the mem entry pointer in the process idr and rb tree +too early, other threads can do operations on the entry by +guessing the ID or GPU address before the object gets returned +by the creating operation. + +Allocate an ID for the object but don't assign the pointer until +right before the creating function returns ensuring that another +operation can't access it until it is ready. + +Bug: 28026365 +CRs-Fixed: 1002974 +Change-Id: Ic0dedbadc0dd2125bd2a7bcc152972c0555e07f8 +Signed-off-by: Jordan Crouse +Signed-off-by: Sunil Khatri +Signed-off-by: Santhosh Punugu +--- + drivers/gpu/msm/kgsl.c | 103 +++++++++++++++++++++++++++++++------------------ + 1 file changed, 65 insertions(+), 38 deletions(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index a4986a75b6260..31a403a939242 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2008-2013,2016, The 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 +@@ -246,18 +246,13 @@ kgsl_mem_entry_destroy(struct kref *kref) + EXPORT_SYMBOL(kgsl_mem_entry_destroy); + + /** +- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and +- * assign it with a gpu address space before insertion ++ * kgsl_mem_entry_track_gpuaddr - Get the entry gpu address space before ++ * insertion to the process + * @process: the process that owns the memory + * @entry: the memory entry + * +- * @returns - 0 on succcess else error code ++ * @returns - 0 on success else error code + * +- * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address. +- * The assignment of gpu address and insertion into list needs to +- * happen with the memory lock held to avoid race conditions between +- * gpu address being selected and some other thread looking through the +- * rb list in search of memory based on gpuaddr + * This function should be called with processes memory spinlock held + */ + static int +@@ -265,8 +260,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, + struct kgsl_mem_entry *entry) + { + int ret = 0; +- struct rb_node **node; +- struct rb_node *parent = NULL; + + assert_spin_locked(&process->mem_lock); + /* +@@ -274,36 +267,17 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, + * gpu address + */ + if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { +- if (!entry->memdesc.gpuaddr) +- goto done; +- } else if (entry->memdesc.gpuaddr) { +- WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n"); +- ret = -EINVAL; +- goto done; +- } +- if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) { +- ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc); +- if (ret) ++ /* cpu map flag is enabled. do nothing */ ++ } else { ++ if (entry->memdesc.gpuaddr) { ++ WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n"); ++ ret = -EINVAL; + goto done; +- } +- +- node = &process->mem_rb.rb_node; +- +- while (*node) { +- struct kgsl_mem_entry *cur; +- +- parent = *node; +- cur = rb_entry(parent, struct kgsl_mem_entry, node); ++ } + +- if (entry->memdesc.gpuaddr < cur->memdesc.gpuaddr) +- node = &parent->rb_left; +- else +- node = &parent->rb_right; ++ ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc); + } + +- rb_link_node(&entry->node, parent, node); +- rb_insert_color(&entry->node, &process->mem_rb); +- + done: + return ret; + } +@@ -327,6 +301,47 @@ kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, + } + } + ++static void kgsl_mem_entry_commit_mem_list(struct kgsl_process_private *process, ++ struct kgsl_mem_entry *entry) ++{ ++ struct rb_node **node; ++ struct rb_node *parent = NULL; ++ ++ if (!entry->memdesc.gpuaddr) ++ return; ++ ++ /* Insert mem entry in mem_rb tree */ ++ node = &process->mem_rb.rb_node; ++ while (*node) { ++ struct kgsl_mem_entry *cur; ++ ++ parent = *node; ++ cur = rb_entry(parent, struct kgsl_mem_entry, node); ++ ++ if (entry->memdesc.gpuaddr < cur->memdesc.gpuaddr) ++ node = &parent->rb_left; ++ else ++ node = &parent->rb_right; ++ } ++ ++ rb_link_node(&entry->node, parent, node); ++ rb_insert_color(&entry->node, &process->mem_rb); ++} ++ ++static void kgsl_mem_entry_commit_process(struct kgsl_process_private *process, ++ struct kgsl_mem_entry *entry) ++{ ++ if (!entry) ++ return; ++ ++ spin_lock(&entry->priv->mem_lock); ++ /* Insert mem entry in mem_rb tree */ ++ kgsl_mem_entry_commit_mem_list(process, entry); ++ /* Replace mem entry in mem_idr using id */ ++ idr_replace(&entry->priv->mem_idr, entry, entry->id); ++ spin_unlock(&entry->priv->mem_lock); ++} ++ + /** + * kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process + * @entry: the memory entry +@@ -357,9 +372,11 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, + } + + spin_lock(&process->mem_lock); +- ret = idr_get_new_above(&process->mem_idr, entry, 1, ++ /* Allocate the ID but don't attach the pointer just yet */ ++ ret = idr_get_new_above(&process->mem_idr, NULL, 1, + &entry->id); + spin_unlock(&process->mem_lock); ++ + if (ret == 0) + break; + else if (ret != -EAGAIN) +@@ -2894,6 +2911,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, + + trace_kgsl_mem_map(entry, param->fd); + ++ kgsl_mem_entry_commit_process(private, entry); + return result; + + error_attach: +@@ -3181,6 +3199,8 @@ kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, + param->gpuaddr = entry->memdesc.gpuaddr; + param->size = entry->memdesc.size; + param->flags = entry->memdesc.flags; ++ ++ kgsl_mem_entry_commit_process(private, entry); + return result; + err: + kgsl_sharedmem_free(&entry->memdesc); +@@ -3217,6 +3237,8 @@ kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, + param->size = entry->memdesc.size; + param->mmapsize = kgsl_memdesc_mmapsize(&entry->memdesc); + param->gpuaddr = entry->memdesc.gpuaddr; ++ ++ kgsl_mem_entry_commit_process(private, entry); + return result; + err: + if (entry) +@@ -3804,6 +3826,11 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, + kgsl_mem_entry_untrack_gpuaddr(private, entry); + spin_unlock(&private->mem_lock); + ret = ret_val; ++ } else { ++ /* Insert mem entry in mem_rb tree */ ++ spin_lock(&private->mem_lock); ++ kgsl_mem_entry_commit_mem_list(private, entry); ++ spin_unlock(&private->mem_lock); + } + break; + } diff --git a/Patches/Linux_CVEs/CVE-2016-3842/1.patch b/Patches/Linux_CVEs/CVE-2016-3842/1.patch new file mode 100644 index 00000000..56181300 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3842/1.patch @@ -0,0 +1,163 @@ +From f5f0a2fe84b589793baa5713ea2aa16779e00d5e Mon Sep 17 00:00:00 2001 +From: Sunil Khatri +Date: Mon, 13 Jun 2016 15:42:24 -0700 +Subject: [PATCH] msm: kgsl: Defer adding the mem entry to a process + +If we add the mem entry pointer in the process idr and rb tree +too early, other threads can do operations on the entry by +guessing the ID or GPU address before the object gets returned +by the creating operation. + +Allocate an ID for the object but don't assign the pointer until +right before the creating function returns ensuring that another +operation can't access it until it is ready. + +Bug: 28026365 +Bug: 28377352 +CRs-Fixed: 1002974 +Change-Id: Ic0dedbadc0dd2125bd2a7bcc152972c0555e07f8 +Signed-off-by: Jordan Crouse +Signed-off-by: Sunil Khatri +Signed-off-by: Santhosh Punugu +--- + drivers/gpu/msm/kgsl.c | 60 ++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 43 insertions(+), 17 deletions(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index a1394b6d3d824..f62fe8ad0b857 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2008-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2008-2016, The 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 +@@ -296,18 +296,13 @@ kgsl_mem_entry_destroy(struct kref *kref) + EXPORT_SYMBOL(kgsl_mem_entry_destroy); + + /** +- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and +- * assign it with a gpu address space before insertion ++ * kgsl_mem_entry_track_gpuaddr - Get the entry gpu address space before ++ * insertion to the process + * @process: the process that owns the memory + * @entry: the memory entry + * +- * @returns - 0 on succcess else error code ++ * @returns - 0 on success else error code + * +- * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address. +- * The assignment of gpu address and insertion into list needs to +- * happen with the memory lock held to avoid race conditions between +- * gpu address being selected and some other thread looking through the +- * rb list in search of memory based on gpuaddr + * This function should be called with processes memory spinlock held + */ + static int +@@ -315,8 +310,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, + struct kgsl_mem_entry *entry) + { + int ret = 0; +- struct rb_node **node; +- struct rb_node *parent = NULL; + struct kgsl_pagetable *pagetable = process->pagetable; + + assert_spin_locked(&process->mem_lock); +@@ -337,11 +330,22 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, + pagetable = pagetable->mmu->securepagetable; + + ret = kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc); +- if (ret) +- goto done; + +- node = &process->mem_rb.rb_node; ++done: ++ return ret; ++} + ++static void kgsl_mem_entry_commit_mem_list(struct kgsl_process_private *process, ++ struct kgsl_mem_entry *entry) ++{ ++ struct rb_node **node; ++ struct rb_node *parent = NULL; ++ ++ if (!entry->memdesc.gpuaddr) ++ return; ++ ++ /* Insert mem entry in mem_rb tree */ ++ node = &process->mem_rb.rb_node; + while (*node) { + struct kgsl_mem_entry *cur; + +@@ -356,9 +360,20 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, + + rb_link_node(&entry->node, parent, node); + rb_insert_color(&entry->node, &process->mem_rb); ++} + +-done: +- return ret; ++static void kgsl_mem_entry_commit_process(struct kgsl_process_private *process, ++ struct kgsl_mem_entry *entry) ++{ ++ if (!entry) ++ return; ++ ++ spin_lock(&entry->priv->mem_lock); ++ /* Insert mem entry in mem_rb tree */ ++ kgsl_mem_entry_commit_mem_list(process, entry); ++ /* Replace mem entry in mem_idr using id */ ++ idr_replace(&entry->priv->mem_idr, entry, entry->id); ++ spin_unlock(&entry->priv->mem_lock); + } + + /** +@@ -407,7 +422,8 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, + return -EBADF; + idr_preload(GFP_KERNEL); + spin_lock(&process->mem_lock); +- id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT); ++ /* Allocate the ID but don't attach the pointer just yet */ ++ id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT); + spin_unlock(&process->mem_lock); + idr_preload_end(); + +@@ -3247,6 +3263,7 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, + + trace_kgsl_mem_map(entry, param->fd); + ++ kgsl_mem_entry_commit_process(private, entry); + return result; + + error_attach: +@@ -3601,6 +3618,8 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, + param->gpuaddr = entry->memdesc.gpuaddr; + param->size = entry->memdesc.size; + param->flags = entry->memdesc.flags; ++ ++ kgsl_mem_entry_commit_process(private, entry); + return result; + err: + kgsl_sharedmem_free(&entry->memdesc); +@@ -3646,6 +3665,8 @@ long kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, + param->size = entry->memdesc.size; + param->mmapsize = kgsl_memdesc_mmapsize(&entry->memdesc); + param->gpuaddr = entry->memdesc.gpuaddr; ++ ++ kgsl_mem_entry_commit_process(private, entry); + return result; + err: + if (entry) +@@ -4169,6 +4190,11 @@ static int kgsl_check_gpu_addr_collision( + spin_lock(&private->mem_lock); + kgsl_mem_entry_untrack_gpuaddr(private, entry); + spin_unlock(&private->mem_lock); ++ } else { ++ /* Insert mem entry in mem_rb tree */ ++ spin_lock(&private->mem_lock); ++ kgsl_mem_entry_commit_mem_list(private, entry); ++ spin_unlock(&private->mem_lock); + } + } else { + trace_kgsl_mem_unmapped_area_collision(entry, addr, len, diff --git a/Patches/Linux_CVEs/CVE-2016-3842/2.patch b/Patches/Linux_CVEs/CVE-2016-3842/2.patch new file mode 100644 index 00000000..b1ed3898 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3842/2.patch @@ -0,0 +1,77 @@ +From 905de01dda0bc6663f8ce5c8f0f3831dae49bb36 Mon Sep 17 00:00:00 2001 +From: Jordan Crouse +Date: Tue, 3 May 2016 14:11:03 -0600 +Subject: [PATCH] msm: kgsl: Defer adding the mem entry to a process + +If we add the mem entry pointer in the process mem_idr too early +other threads can do operations on the entry by guessing the ID +or GPU address before the object gets returned by the creating +operation. + +Allocate an ID for the object but don't assign the pointer until +right before the creating function returns ensuring that another +operation can't access it until it is ready. + +CRs-Fixed: 1002974 +Change-Id: Ic0dedbadc0dd2125bd2a7bcc152972c0555e07f8 +Signed-off-by: Jordan Crouse +--- + drivers/gpu/msm/kgsl.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index 51dc781b2bd47..2563591f376e2 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -388,6 +388,17 @@ kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, + kgsl_mmu_put_gpuaddr(pagetable, &entry->memdesc); + } + ++/* Commit the entry to the process so it can be accessed by other operations */ ++static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry) ++{ ++ if (!entry) ++ return; ++ ++ spin_lock(&entry->priv->mem_lock); ++ idr_replace(&entry->priv->mem_idr, entry, entry->id); ++ spin_unlock(&entry->priv->mem_lock); ++} ++ + /** + * kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process + * @entry: the memory entry +@@ -418,7 +429,8 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, + + idr_preload(GFP_KERNEL); + spin_lock(&process->mem_lock); +- id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT); ++ /* Allocate the ID but don't attach the pointer just yet */ ++ id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT); + spin_unlock(&process->mem_lock); + idr_preload_end(); + +@@ -2317,6 +2329,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, + + trace_kgsl_mem_map(entry, fd); + ++ kgsl_mem_entry_commit_process(entry); + return 0; + + unmap: +@@ -2580,6 +2593,7 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, + + trace_kgsl_mem_map(entry, param->fd); + ++ kgsl_mem_entry_commit_process(entry); + return result; + + error_attach: +@@ -2971,6 +2985,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( + entry->memdesc.size); + trace_kgsl_mem_alloc(entry); + ++ kgsl_mem_entry_commit_process(entry); + return entry; + err: + kfree(entry); diff --git a/Patches/Linux_CVEs/CVE-2016-3843/0.patch b/Patches/Linux_CVEs/CVE-2016-3843/0.patch new file mode 100644 index 00000000..5f8608b5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3843/0.patch @@ -0,0 +1,132 @@ +From e65cc8f9c46c6b8119826fbc22ffeb4e96e80e8a Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Tue, 19 Jan 2016 21:35:15 +0000 +Subject: BACKPORT: perf tools: Document the perf sysctls + +perf_event_paranoid was only documented in source code and a perf error +message. Copy the documentation from the error message to +Documentation/sysctl/kernel.txt. + +Conflicts: + Documentation/sysctl/kernel.txt + tools/perf/util/evsel.c + +Signed-off-by: Ben Hutchings +Cc: Peter Zijlstra +Cc: linux-doc@vger.kernel.org +Link: http://lkml.kernel.org/r/20160119213515.GG2637@decadent.org.uk +[ Remove reference to external Documentation file, provide info inline, as before ] +Signed-off-by: Arnaldo Carvalho de Melo +Bug: 29054680 +Bug: 29119870 +Signed-off-by: Dennis Cagle +Change-Id: I13e73cfb2ad761c94762d0c8196df7725abdf5c5 +(cherry picked from commit 746938f9d97d74f6c2833a0ede49506bdfcd89e4) +--- + Documentation/sysctl/kernel.txt | 41 ++++++++++++++++++++++++++--------------- + tools/perf/util/evsel.c | 15 +++++++++------ + 2 files changed, 35 insertions(+), 21 deletions(-) + +diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt +index 550ece7..942d769 100644 +--- a/Documentation/sysctl/kernel.txt ++++ b/Documentation/sysctl/kernel.txt +@@ -51,8 +51,9 @@ show up in /proc/sys/kernel: + - overflowuid + - panic + - panic_on_oops +-- panic_on_unrecovered_nmi + - panic_on_stackoverflow ++- panic_on_unrecovered_nmi ++- perf_event_paranoid + - pid_max + - powersave-nap [ PPC only ] + - printk +@@ -427,19 +428,6 @@ the recommended setting is 60. + + ============================================================== + +-panic_on_unrecovered_nmi: +- +-The default Linux behaviour on an NMI of either memory or unknown is +-to continue operation. For many environments such as scientific +-computing it is preferable that the box is taken out and the error +-dealt with than an uncorrected parity/ECC error get propagated. +- +-A small number of systems do generate NMI's for bizarre random reasons +-such as power management so the default is off. That sysctl works like +-the existing panic controls already in that directory. +- +-============================================================== +- + panic_on_oops: + + Controls the kernel's behaviour when an oops or BUG is encountered. +@@ -459,7 +447,6 @@ This file shows up if CONFIG_DEBUG_STACKOVERFLOW is enabled. + + 0: try to continue operation. + +-1: panic immediately. + + ============================================================== + +@@ -489,6 +476,30 @@ allowed to execute. + + ============================================================== + ++panic_on_unrecovered_nmi: ++ ++The default Linux behaviour on an NMI of either memory or unknown is ++to continue operation. For many environments such as scientific ++computing it is preferable that the box is taken out and the error ++dealt with than an uncorrected parity/ECC error get propagated. ++ ++A small number of systems do generate NMI's for bizarre random reasons ++such as power management so the default is off. That sysctl works like ++the existing panic controls already in that directory. ++ ++============================================================== ++ ++perf_event_paranoid: ++ ++Controls use of the performance events system by unprivileged ++users (without CAP_SYS_ADMIN). The default value is 1. ++ ++ -1: Allow use of (almost) all events by all users ++>=0: Disallow raw tracepoint access by users without CAP_IOC_LOCK ++>=1: Disallow CPU event access by users without CAP_SYS_ADMIN ++>=2: Disallow kernel profiling by users without CAP_SYS_ADMIN ++ ++============================================================== + + pid_max: + +diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c +index 63b6f8c..54494df 100644 +--- a/tools/perf/util/evsel.c ++++ b/tools/perf/util/evsel.c +@@ -1515,12 +1515,15 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, + case EPERM: + case EACCES: + return scnprintf(msg, size, +- "You may not have permission to collect %sstats.\n" +- "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" +- " -1 - Not paranoid at all\n" +- " 0 - Disallow raw tracepoint access for unpriv\n" +- " 1 - Disallow cpu events for unpriv\n" +- " 2 - Disallow kernel profiling for unpriv", ++ "You may not have permission to collect %sstats.\n\n" ++ "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n" ++ "which controls use of the performance events system by\n" ++ "unprivileged users (without CAP_SYS_ADMIN).\n\n" ++ "The default value is 1:\n\n" ++ " -1: Allow use of (almost) all events by all users\n" ++ ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" ++ ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" ++ ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN", + target->system_wide ? "system-wide " : ""); + case ENOENT: + return scnprintf(msg, size, "The %s event is not supported.", +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3843/1.patch b/Patches/Linux_CVEs/CVE-2016-3843/1.patch new file mode 100644 index 00000000..b12531f6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3843/1.patch @@ -0,0 +1,119 @@ +From 149cf87192059fab0cb49ec5c691783c3565c215 Mon Sep 17 00:00:00 2001 +From: Jeff Vander Stoep +Date: Sun, 29 May 2016 14:22:32 -0700 +Subject: FROMLIST: security,perf: Allow further restriction of perf_event_open + +When kernel.perf_event_open is set to 3 (or greater), disallow all +access to performance events by users without CAP_SYS_ADMIN. +Add a Kconfig symbol CONFIG_SECURITY_PERF_EVENTS_RESTRICT that +makes this value the default. + +This is based on a similar feature in grsecurity +(CONFIG_GRKERNSEC_PERF_HARDEN). This version doesn't include making +the variable read-only. It also allows enabling further restriction +at run-time regardless of whether the default is changed. + +https://lkml.org/lkml/2016/1/11/587 + +Conflicts: + kernel/events/core.c + +Signed-off-by: Ben Hutchings +Signed-off-by: Dennis Cagle +Bug: 29054680 +Bug: 29119870 +Change-Id: Iff5bff4fc1042e85866df9faa01bce8d04335ab8 +(cherry picked from commit f16929ac8586f37949c638c738a6f0de969ed1ea) +--- + Documentation/sysctl/kernel.txt | 4 +++- + include/linux/perf_event.h | 5 +++++ + kernel/events/core.c | 6 ++++++ + security/Kconfig | 9 +++++++++ + 4 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt +index 942d769..d438fd2 100644 +--- a/Documentation/sysctl/kernel.txt ++++ b/Documentation/sysctl/kernel.txt +@@ -492,12 +492,14 @@ the existing panic controls already in that directory. + perf_event_paranoid: + + Controls use of the performance events system by unprivileged +-users (without CAP_SYS_ADMIN). The default value is 1. ++users (without CAP_SYS_ADMIN). The default value is 3 if ++CONFIG_SECURITY_PERF_EVENTS_RESTRICT is set, or 1 otherwise. + + -1: Allow use of (almost) all events by all users + >=0: Disallow raw tracepoint access by users without CAP_IOC_LOCK + >=1: Disallow CPU event access by users without CAP_SYS_ADMIN + >=2: Disallow kernel profiling by users without CAP_SYS_ADMIN ++>=3: Disallow all event access by users without CAP_SYS_ADMIN + + ============================================================== + +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index 4410efa..86b43c1 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -715,6 +715,11 @@ extern int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, + loff_t *ppos); + + ++static inline bool perf_paranoid_any(void) ++{ ++ return sysctl_perf_event_paranoid > 2; ++} ++ + static inline bool perf_paranoid_tracepoint_raw(void) + { + return sysctl_perf_event_paranoid > -1; +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 7ab36de..e8cae75 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -166,9 +166,12 @@ static struct srcu_struct pmus_srcu; + * 0 - disallow raw tracepoint access for unpriv + * 1 - disallow cpu events for unpriv + * 2 - disallow kernel profiling for unpriv ++ * 3 - disallow all unpriv perf event use + */ + #ifdef CONFIG_PERF_EVENTS_USERMODE + int sysctl_perf_event_paranoid __read_mostly = -1; ++#elif defined CONFIG_SECURITY_PERF_EVENTS_RESTRICT ++int sysctl_perf_event_paranoid __read_mostly = 3; + #else + int sysctl_perf_event_paranoid __read_mostly = 1; + #endif +@@ -6826,6 +6829,9 @@ SYSCALL_DEFINE5(perf_event_open, + if (flags & ~PERF_FLAG_ALL) + return -EINVAL; + ++ if (perf_paranoid_any() && !capable(CAP_SYS_ADMIN)) ++ return -EACCES; ++ + err = perf_copy_attr(attr_uptr, &attr); + if (err) + return err; +diff --git a/security/Kconfig b/security/Kconfig +index 0114543..66a5f80 100644 +--- a/security/Kconfig ++++ b/security/Kconfig +@@ -18,6 +18,15 @@ config SECURITY_DMESG_RESTRICT + + If you are unsure how to answer this question, answer N. + ++config SECURITY_PERF_EVENTS_RESTRICT ++ bool "Restrict unprivileged use of performance events" ++ depends on PERF_EVENTS ++ help ++ If you say Y here, the kernel.perf_event_paranoid sysctl ++ will be set to 3 by default, and no unprivileged use of the ++ perf_event_open syscall will be permitted unless it is ++ changed. ++ + config SECURITY + bool "Enable different security models" + depends on SYSFS +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3843/2.patch b/Patches/Linux_CVEs/CVE-2016-3843/2.patch new file mode 100644 index 00000000..5881ba06 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3843/2.patch @@ -0,0 +1,30 @@ +From 8fe72ba71e08fbc2c5a5d4985557247904d76054 Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Mon, 15 Aug 2016 14:35:18 -0700 +Subject: msm_defconfig: Enable config for b/29119870 + +Restriction of kernel performance events requires +a change to the defconfig. + +Bug: 29119870 +Change-Id: Ib7e565a52446e2dcae1aa8c561d4770f2762a4d7 +Signed-off-by: Dennis Cagle +--- + arch/arm64/configs/msm_defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig +index 0473936..7755ea1 100644 +--- a/arch/arm64/configs/msm_defconfig ++++ b/arch/arm64/configs/msm_defconfig +@@ -620,6 +620,7 @@ CONFIG_KERNEL_TEXT_RDONLY=y + CONFIG_KEYS=y + CONFIG_SECURITY=y + CONFIG_SECURITY_NETWORK=y ++CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y + CONFIG_LSM_MMAP_MIN_ADDR=4096 + CONFIG_SECURITY_SELINUX=y + CONFIG_CRYPTO=y +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3843/3.patch b/Patches/Linux_CVEs/CVE-2016-3843/3.patch new file mode 100644 index 00000000..ec5ae396 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3843/3.patch @@ -0,0 +1,35 @@ +From 15c897f31ba18f67559d6b7f1a6afa855baa756c Mon Sep 17 00:00:00 2001 +From: Jeff Vander Stoep +Date: Wed, 1 Jun 2016 13:44:47 -0700 +Subject: ANDROID: restrict access to perf events + +Add: +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y + +to android-base.cfg + +The kernel.perf_event_paranoid sysctl is set to 3 by default. +No unprivileged use of the perf_event_open syscall will be +permitted unless it is changed. + +Bug: 29054680 +Change-Id: Ie7512259150e146d8e382dc64d40e8faaa438917 +--- + android/configs/android-base.cfg | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg +index 85e4a93..f820d56 100644 +--- a/android/configs/android-base.cfg ++++ b/android/configs/android-base.cfg +@@ -143,6 +143,7 @@ CONFIG_RTC_CLASS=y + CONFIG_RT_GROUP_SCHED=y + CONFIG_SECURITY=y + CONFIG_SECURITY_NETWORK=y ++CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y + CONFIG_SECURITY_SELINUX=y + CONFIG_SETEND_EMULATION=y + CONFIG_STAGING=y +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3854/0.patch b/Patches/Linux_CVEs/CVE-2016-3854/0.patch new file mode 100644 index 00000000..3c57c8ec --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3854/0.patch @@ -0,0 +1,34 @@ +From cc96def76dfd18fba88575065b29f2ae9191fafa Mon Sep 17 00:00:00 2001 +From: Terence Ho +Date: Thu, 5 Nov 2015 14:49:03 -0500 +Subject: msm: camera: Add check to prevent array index out of bounds + +Add check in msm_mctl_buf_return_buf to prevent array index +out-of-bounds. + +Change-Id: Ie0bbbb1c97e8851ef004074726e90c78d5cdefa7 +Signed-off-by: Terence Ho +--- + drivers/media/video/msm/msm_mctl_buf.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c +index e258097..8b37391 100644 +--- a/drivers/media/video/msm/msm_mctl_buf.c ++++ b/drivers/media/video/msm/msm_mctl_buf.c +@@ -917,6 +917,12 @@ int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl, + struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr; + unsigned long flags = 0; + ++ if (image_mode < 0 || image_mode >= MSM_MAX_IMG_MODE) { ++ pr_err("%s: image_mode %d out-of-bounds", ++ __func__, image_mode); ++ return -EINVAL; ++ } ++ + if (pcam->mctl_node.dev_inst_map[image_mode]) { + idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index; + pcam_inst = pcam->mctl_node.dev_inst[idx]; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3855/0.patch b/Patches/Linux_CVEs/CVE-2016-3855/0.patch new file mode 100644 index 00000000..24f90187 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3855/0.patch @@ -0,0 +1,41 @@ +From ab3f46119ca10de87a11fe966b0723c48f27acd4 Mon Sep 17 00:00:00 2001 +From: Manaf Meethalavalappu Pallikunhi +Date: Wed, 30 Mar 2016 17:12:16 +0530 +Subject: msm: limits: Check user buffer size before copying to local buffer + +User input data is passed in from userspace through debugfs interface +of supply lm core to validate supply lm core functionality. Ensure +user buffer size is not greater than expected stack buffer size +to avoid out of bounds array accesses. + +Change-Id: I5a93774855241b50895c5e2b3ff939e4c33a0185 +Signed-off-by: Manaf Meethalavalappu Pallikunhi +--- + drivers/thermal/supply_lm_core.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/thermal/supply_lm_core.c b/drivers/thermal/supply_lm_core.c +index fc8e807..a4d137f 100644 +--- a/drivers/thermal/supply_lm_core.c ++++ b/drivers/thermal/supply_lm_core.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2016, The 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 +@@ -303,6 +303,11 @@ static ssize_t supply_lm_input_write(struct file *fp, + enum corner_state gpu; + enum corner_state modem; + ++ if (count > (MODE_MAX - 1)) { ++ pr_err("Invalid user input\n"); ++ return -EINVAL; ++ } ++ + if (copy_from_user(&buf, user_buffer, count)) + return -EFAULT; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3857/0.patch b/Patches/Linux_CVEs/CVE-2016-3857/0.patch new file mode 100644 index 00000000..6a2d672d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3857/0.patch @@ -0,0 +1,52 @@ +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/Linux_CVEs/CVE-2016-3857/1.patch b/Patches/Linux_CVEs/CVE-2016-3857/1.patch new file mode 100644 index 00000000..98d5e7c5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3857/1.patch @@ -0,0 +1,32 @@ +From cd169f77b41de0fc1c8b790d71ac8c6c0c0dc7ef Mon Sep 17 00:00:00 2001 +From: Thierry Strudel +Date: Mon, 13 Jun 2016 16:58:43 -0700 +Subject: [PATCH] flo_defconfig: disable CONFIG_OABI_COMPAT + +Bug: 28522518 +Change-Id: I11ec8e02bdb330c10f06e923c1c3d45a145ced15 +Signed-off-by: Thierry Strudel +--- + arch/arm/configs/flo_defconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig +index cd2ddd65d3325..81c433b95aa40 100644 +--- a/arch/arm/configs/flo_defconfig ++++ b/arch/arm/configs/flo_defconfig +@@ -89,6 +89,7 @@ CONFIG_SMP=y + CONFIG_SCHED_MC=y + CONFIG_PREEMPT=y + CONFIG_AEABI=y ++# CONFIG_OABI_COMPAT is not set + CONFIG_HIGHMEM=y + CONFIG_SECCOMP=y + CONFIG_CC_STACKPROTECTOR=y +@@ -364,7 +365,6 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y + CONFIG_USB_VIDEO_CLASS=y + CONFIG_V4L_PLATFORM_DRIVERS=y + CONFIG_MSM_WFD=y +-# CONFIG_RADIO_IRIS is not set + CONFIG_ION=y + CONFIG_ION_MSM=y + CONFIG_MSM_KGSL=y diff --git a/Patches/Linux_CVEs/CVE-2016-3859/0.patch b/Patches/Linux_CVEs/CVE-2016-3859/0.patch new file mode 100644 index 00000000..ef80afd2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3859/0.patch @@ -0,0 +1,36 @@ +From fe297dc01f7ea95bb1bff25f6fc4257f0ef832ff Mon Sep 17 00:00:00 2001 +From: Trishansh Bhardwaj +Date: Wed, 29 Jun 2016 14:34:31 +0530 +Subject: msm: camera: Fix memory read security flaw + +Adds bound check on reg_cfg_cmd->u.dmi_info.hi_tbl_offset. + +IOCTL VIDIOC_MSM_VFE_REG_CFG uses usersupplied value without +performing bounds check for following cmd_type. +VFE_READ_DMI_16BIT +VFE_READ_DMI_32BIT +VFE_READ_DMI_64BIT + +Change-Id: I554c45ef3a172f5b5891b67a7e8e7a1f3f3882ed +Signed-off-by: Trishansh Bhardwaj +--- + drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +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 7ea77dd..4f4884a 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 +@@ -969,7 +969,8 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + 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->cmd_type == VFE_WRITE_DMI_64BIT || ++ 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.lo_tbl_offset) || + (reg_cfg_cmd->u.dmi_info.hi_tbl_offset - +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3865/0.patch b/Patches/Linux_CVEs/CVE-2016-3865/0.patch new file mode 100644 index 00000000..7f461976 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3865/0.patch @@ -0,0 +1,86 @@ +From a92e71c20f4e6b2aa94b7614fd494833ea76b8b9 Mon Sep 17 00:00:00 2001 +From: Biswajit Paul +Date: Thu, 30 Jun 2016 19:00:50 -0700 +Subject: [PATCH] input: synaptics: allocate heap memory for temp buf + +rmidev file operations structure include write() and +read() which accepts data from user space. Temp +buffers are allocated through variable length arrays +which can pose security problems. So allocate memory +on heap instead of stack to avoid this. + +Bug: 28799389 +CRs-Fixed: 1032459 +Change-Id: I44443f91d435715dd0097ef8e8dfc48e291f93fc +Signed-off-by: Mohan Pallaka +Signed-off-by: Biswajit Paul +--- + drivers/input/touchscreen/synaptics_rmi_dev.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c +index 88595582579e0..e2d7c27eb6832 100644 +--- a/drivers/input/touchscreen/synaptics_rmi_dev.c ++++ b/drivers/input/touchscreen/synaptics_rmi_dev.c +@@ -291,7 +291,7 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) + { + ssize_t retval; +- unsigned char tmpbuf[count + 1]; ++ unsigned char *tmpbuf; + struct rmidev_data *dev_data = filp->private_data; + + if (IS_ERR(dev_data)) { +@@ -305,6 +305,10 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + ++ tmpbuf = kzalloc(count + 1, GFP_KERNEL); ++ if (!tmpbuf) ++ return -ENOMEM; ++ + mutex_lock(&(dev_data->file_mutex)); + + retval = rmidev->fn_ptr->read(rmidev->rmi4_data, +@@ -322,6 +326,7 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + clean_up: + mutex_unlock(&(dev_data->file_mutex)); + ++ kfree(tmpbuf); + return retval; + } + +@@ -337,7 +342,7 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) + { + ssize_t retval; +- unsigned char tmpbuf[count + 1]; ++ unsigned char *tmpbuf; + struct rmidev_data *dev_data = filp->private_data; + + if (IS_ERR(dev_data)) { +@@ -351,8 +356,14 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + +- if (copy_from_user(tmpbuf, buf, count)) ++ tmpbuf = kzalloc(count + 1, GFP_KERNEL); ++ if (!tmpbuf) ++ return -ENOMEM; ++ ++ if (copy_from_user(tmpbuf, buf, count)) { ++ kfree(tmpbuf); + return -EFAULT; ++ } + + mutex_lock(&(dev_data->file_mutex)); + +@@ -364,7 +375,7 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + *f_pos += retval; + + mutex_unlock(&(dev_data->file_mutex)); +- ++ kfree(tmpbuf); + return retval; + } + diff --git a/Patches/Linux_CVEs/CVE-2016-3865/1.patch b/Patches/Linux_CVEs/CVE-2016-3865/1.patch new file mode 100644 index 00000000..cd0e3117 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3865/1.patch @@ -0,0 +1,86 @@ +From 92242610894d1dc26759e486af1d11f2eb78c922 Mon Sep 17 00:00:00 2001 +From: Biswajit Paul +Date: Thu, 30 Jun 2016 19:00:50 -0700 +Subject: [PATCH] input: synaptics_dsx: allocate heap memory for temp buf + +rmidev file operations structure include write() and +read() which accepts data from user space. Temp +buffers are allocated through variable length arrays +which can pose security problems. So allocate memory +on heap instead of stack to avoid this. + +Bug: 28799389 +CRs-Fixed: 1032459 +Change-Id: I44443f91d435715dd0097ef8e8dfc48e291f93fc +Signed-off-by: Mohan Pallaka +Signed-off-by: Biswajit Paul +--- + .../touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c +index 4c341ffb60940..bb9ddd9873cb1 100644 +--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c ++++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c +@@ -347,7 +347,7 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) + { + ssize_t retval; +- unsigned char tmpbuf[count + 1]; ++ unsigned char *tmpbuf; + struct rmidev_data *dev_data = filp->private_data; + + if (IS_ERR(dev_data)) { +@@ -361,6 +361,10 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + ++ tmpbuf = kzalloc(count + 1, GFP_KERNEL); ++ if (!tmpbuf) ++ return -ENOMEM; ++ + mutex_lock(&(dev_data->file_mutex)); + + retval = synaptics_rmi4_reg_read(rmidev->rmi4_data, +@@ -378,6 +382,7 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + clean_up: + mutex_unlock(&(dev_data->file_mutex)); + ++ kfree(tmpbuf); + return retval; + } + +@@ -393,7 +398,7 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) + { + ssize_t retval; +- unsigned char tmpbuf[count + 1]; ++ unsigned char *tmpbuf; + struct rmidev_data *dev_data = filp->private_data; + + if (IS_ERR(dev_data)) { +@@ -407,8 +412,14 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + +- if (copy_from_user(tmpbuf, buf, count)) ++ tmpbuf = kzalloc(count + 1, GFP_KERNEL); ++ if (!tmpbuf) ++ return -ENOMEM; ++ ++ if (copy_from_user(tmpbuf, buf, count)) { ++ kfree(tmpbuf); + return -EFAULT; ++ } + + mutex_lock(&(dev_data->file_mutex)); + +@@ -420,7 +431,7 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + *f_pos += retval; + + mutex_unlock(&(dev_data->file_mutex)); +- ++ kfree(tmpbuf); + return retval; + } + diff --git a/Patches/Linux_CVEs/CVE-2016-3867/0.patch b/Patches/Linux_CVEs/CVE-2016-3867/0.patch new file mode 100644 index 00000000..81970697 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3867/0.patch @@ -0,0 +1,505 @@ +From 816da3d19cfee937f5add485a112bb1cdfcb72c8 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Fri, 8 Jul 2016 16:20:33 -0700 +Subject: msm: ipa: fix potential race condition ioctls + +There are numerous potential race condition +ioctls in the IPA driver. The fix is to add +check wherever it copies arguments from +user-space memory and process. + +Change-Id: I5a440f89153518507acdf5dad42625503732e59a +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa.c | 236 ++++++++++++++++++++++++++++++++++------- + 1 file changed, 196 insertions(+), 40 deletions(-) + +diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c +index adce191..5cfbbc9 100644 +--- a/drivers/platform/msm/ipa/ipa.c ++++ b/drivers/platform/msm/ipa/ipa.c +@@ -390,6 +390,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + struct ipa_ioc_v4_nat_del nat_del; + struct ipa_ioc_rm_dependency rm_depend; + size_t sz; ++ int pre_entry; + + IPADBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd)); + +@@ -438,11 +439,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- ++ pre_entry = ++ ((struct ipa_ioc_nat_dma_cmd *)header)->entries; + pyld_sz = + sizeof(struct ipa_ioc_nat_dma_cmd) + +- ((struct ipa_ioc_nat_dma_cmd *)header)->entries * +- sizeof(struct ipa_ioc_nat_dma_one); ++ pre_entry * sizeof(struct ipa_ioc_nat_dma_one); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -453,7 +454,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_nat_dma_cmd *)param)->entries ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_nat_dma_cmd *)param)->entries, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_nat_dma_cmd((struct ipa_ioc_nat_dma_cmd *)param)) { + retval = -EFAULT; + break; +@@ -478,10 +487,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_hdr *)header)->num_hdrs; + pyld_sz = + sizeof(struct ipa_ioc_add_hdr) + +- ((struct ipa_ioc_add_hdr *)header)->num_hdrs * +- sizeof(struct ipa_hdr_add); ++ pre_entry * sizeof(struct ipa_hdr_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -491,6 +501,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_hdr *)param)->num_hdrs ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_add_hdr *)param)->num_hdrs, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_add_hdr((struct ipa_ioc_add_hdr *)param)) { + retval = -EFAULT; + break; +@@ -507,10 +526,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_hdr *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_hdr) + +- ((struct ipa_ioc_del_hdr *)header)->num_hdls * +- sizeof(struct ipa_hdr_del); ++ pre_entry * sizeof(struct ipa_hdr_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -520,6 +540,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_hdr *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_del_hdr *)param)->num_hdls, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_del_hdr((struct ipa_ioc_del_hdr *)param)) { + retval = -EFAULT; + break; +@@ -536,10 +565,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_rt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_add_rt_rule) + +- ((struct ipa_ioc_add_rt_rule *)header)->num_rules * +- sizeof(struct ipa_rt_rule_add); ++ pre_entry * sizeof(struct ipa_rt_rule_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -549,6 +579,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_rt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_add_rt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -565,10 +605,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_mdfy_rt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_mdfy_rt_rule) + +- ((struct ipa_ioc_mdfy_rt_rule *)header)->num_rules * +- sizeof(struct ipa_rt_rule_mdfy); ++ pre_entry * sizeof(struct ipa_rt_rule_mdfy); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -578,6 +619,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_mdfy_rt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_mdfy_rt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_mdfy_rt_rule((struct ipa_ioc_mdfy_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -594,10 +645,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_rt_rule *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_rt_rule) + +- ((struct ipa_ioc_del_rt_rule *)header)->num_hdls * +- sizeof(struct ipa_rt_rule_del); ++ pre_entry * sizeof(struct ipa_rt_rule_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -607,6 +659,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_rt_rule *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_del_rt_rule *)param)->num_hdls, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_del_rt_rule((struct ipa_ioc_del_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -623,10 +684,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_flt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_add_flt_rule) + +- ((struct ipa_ioc_add_flt_rule *)header)->num_rules * +- sizeof(struct ipa_flt_rule_add); ++ pre_entry * sizeof(struct ipa_flt_rule_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -636,6 +698,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_flt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_add_flt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -652,10 +724,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_flt_rule *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_flt_rule) + +- ((struct ipa_ioc_del_flt_rule *)header)->num_hdls * +- sizeof(struct ipa_flt_rule_del); ++ pre_entry * sizeof(struct ipa_flt_rule_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -665,6 +738,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_flt_rule *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_del_flt_rule *)param)-> ++ num_hdls, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_del_flt_rule((struct ipa_ioc_del_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -681,10 +764,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_mdfy_flt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_mdfy_flt_rule) + +- ((struct ipa_ioc_mdfy_flt_rule *)header)->num_rules * +- sizeof(struct ipa_flt_rule_mdfy); ++ pre_entry * sizeof(struct ipa_flt_rule_mdfy); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -694,6 +778,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_mdfy_flt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_mdfy_flt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_mdfy_flt_rule((struct ipa_ioc_mdfy_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -801,15 +895,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- if (((struct ipa_ioc_query_intf_tx_props *)header)->num_tx_props +- > IPA_NUM_PROPS_MAX) { ++ if (((struct ipa_ioc_query_intf_tx_props *) ++ header)->num_tx_props > IPA_NUM_PROPS_MAX) { + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_tx_props *) +- header)->num_tx_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_tx_props *) ++ header)->num_tx_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_tx_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -820,6 +914,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_tx_props *) ++ param)->num_tx_props ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_query_intf_tx_props *) ++ param)->num_tx_props, pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_query_intf_tx_props( + (struct ipa_ioc_query_intf_tx_props *)param)) { + retval = -1; +@@ -836,15 +940,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- if (((struct ipa_ioc_query_intf_rx_props *)header)->num_rx_props +- > IPA_NUM_PROPS_MAX) { ++ if (((struct ipa_ioc_query_intf_rx_props *) ++ header)->num_rx_props > IPA_NUM_PROPS_MAX) { + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_rx_props *) +- header)->num_rx_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_rx_props *) ++ header)->num_rx_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_rx_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -855,6 +959,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_rx_props *) ++ param)->num_rx_props != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_query_intf_rx_props *) ++ param)->num_rx_props, pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_query_intf_rx_props( + (struct ipa_ioc_query_intf_rx_props *)param)) { + retval = -1; +@@ -877,9 +990,10 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_ext_props *) +- header)->num_ext_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_ext_props *) ++ header)->num_ext_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_ext_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -890,6 +1004,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_ext_props *) ++ param)->num_ext_props != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_query_intf_ext_props *) ++ param)->num_ext_props, pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_query_intf_ext_props( + (struct ipa_ioc_query_intf_ext_props *)param)) { + retval = -1; +@@ -906,8 +1029,10 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_msg_meta *)header)->msg_len; + pyld_sz = sizeof(struct ipa_msg_meta) + +- ((struct ipa_msg_meta *)header)->msg_len; ++ pre_entry; + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -917,6 +1042,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_msg_meta *)param)->msg_len ++ != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_msg_meta *)param)->msg_len, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_pull_msg((struct ipa_msg_meta *)param, + (char *)param + sizeof(struct ipa_msg_meta), + ((struct ipa_msg_meta *)param)->msg_len) != +@@ -1032,10 +1166,12 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_hdr_proc_ctx *) ++ header)->num_proc_ctxs; + pyld_sz = + sizeof(struct ipa_ioc_add_hdr_proc_ctx) + +- ((struct ipa_ioc_add_hdr_proc_ctx *)header)->num_proc_ctxs * +- sizeof(struct ipa_hdr_proc_ctx_add); ++ pre_entry * sizeof(struct ipa_hdr_proc_ctx_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -1045,6 +1181,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_hdr_proc_ctx *) ++ param)->num_proc_ctxs != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_add_hdr_proc_ctx *) ++ param)->num_proc_ctxs, pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_add_hdr_proc_ctx( + (struct ipa_ioc_add_hdr_proc_ctx *)param)) { + retval = -EFAULT; +@@ -1061,10 +1206,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_hdr_proc_ctx *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_hdr_proc_ctx) + +- ((struct ipa_ioc_del_hdr_proc_ctx *)header)->num_hdls * +- sizeof(struct ipa_hdr_proc_ctx_del); ++ pre_entry * sizeof(struct ipa_hdr_proc_ctx_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -1074,6 +1220,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_hdr_proc_ctx *) ++ param)->num_hdls != pre_entry)) { ++ IPAERR("current %d pre %d\n", ++ ((struct ipa_ioc_del_hdr_proc_ctx *)param)-> ++ num_hdls, ++ pre_entry); ++ retval = -EFAULT; ++ break; ++ } + if (ipa_del_hdr_proc_ctx( + (struct ipa_ioc_del_hdr_proc_ctx *)param)) { + retval = -EFAULT; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3867/1.patch b/Patches/Linux_CVEs/CVE-2016-3867/1.patch new file mode 100644 index 00000000..3d1fa1a4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3867/1.patch @@ -0,0 +1,1026 @@ +From b518b33d4b7da7df5a0348a97ffb4f35be819937 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Fri, 8 Jul 2016 16:20:33 -0700 +Subject: msm: ipa: fix potential race condition ioctls + +There are potential race condition ioctls in +the IPA driver when it copies the actual +arguments from the user-space memory to the +IPA-driver. The fix is to add check on the 2nd +copy to make sure the same payload size is copied +to the pre-allocated kernel memory as in during +the 1st copy. + +Change-Id: I5a440f89153518507acdf5dad42625503732e59a +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa_v2/ipa.c | 226 +++++++++++++++++++++++++----- + drivers/platform/msm/ipa/ipa_v3/ipa.c | 257 +++++++++++++++++++++++++++++----- + 2 files changed, 411 insertions(+), 72 deletions(-) + +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c +index 07b934f..72c9e8e 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c +@@ -575,6 +575,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + struct ipa_ioc_v4_nat_del nat_del; + struct ipa_ioc_rm_dependency rm_depend; + size_t sz; ++ int pre_entry; + + IPADBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd)); + +@@ -623,11 +624,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- ++ pre_entry = ++ ((struct ipa_ioc_nat_dma_cmd *)header)->entries; + pyld_sz = + sizeof(struct ipa_ioc_nat_dma_cmd) + +- ((struct ipa_ioc_nat_dma_cmd *)header)->entries * +- sizeof(struct ipa_ioc_nat_dma_one); ++ pre_entry * sizeof(struct ipa_ioc_nat_dma_one); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -638,7 +639,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_nat_dma_cmd *)param)->entries ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_nat_dma_cmd *)param)->entries, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_nat_dma_cmd((struct ipa_ioc_nat_dma_cmd *)param)) { + retval = -EFAULT; + break; +@@ -663,10 +672,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_hdr *)header)->num_hdrs; + pyld_sz = + sizeof(struct ipa_ioc_add_hdr) + +- ((struct ipa_ioc_add_hdr *)header)->num_hdrs * +- sizeof(struct ipa_hdr_add); ++ pre_entry * sizeof(struct ipa_hdr_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -676,6 +686,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_hdr *)param)->num_hdrs ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_hdr *)param)->num_hdrs, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_add_hdr((struct ipa_ioc_add_hdr *)param)) { + retval = -EFAULT; + break; +@@ -692,10 +711,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_hdr *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_hdr) + +- ((struct ipa_ioc_del_hdr *)header)->num_hdls * +- sizeof(struct ipa_hdr_del); ++ pre_entry * sizeof(struct ipa_hdr_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -705,6 +725,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_hdr *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_del_hdr *)param)->num_hdls, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_del_hdr((struct ipa_ioc_del_hdr *)param)) { + retval = -EFAULT; + break; +@@ -721,10 +750,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_rt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_add_rt_rule) + +- ((struct ipa_ioc_add_rt_rule *)header)->num_rules * +- sizeof(struct ipa_rt_rule_add); ++ pre_entry * sizeof(struct ipa_rt_rule_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -734,6 +764,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_rt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_rt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -750,10 +790,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_mdfy_rt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_mdfy_rt_rule) + +- ((struct ipa_ioc_mdfy_rt_rule *)header)->num_rules * +- sizeof(struct ipa_rt_rule_mdfy); ++ pre_entry * sizeof(struct ipa_rt_rule_mdfy); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -763,6 +804,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_mdfy_rt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_mdfy_rt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_mdfy_rt_rule((struct ipa_ioc_mdfy_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -779,10 +830,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_rt_rule *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_rt_rule) + +- ((struct ipa_ioc_del_rt_rule *)header)->num_hdls * +- sizeof(struct ipa_rt_rule_del); ++ pre_entry * sizeof(struct ipa_rt_rule_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -792,6 +844,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_rt_rule *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_del_rt_rule *)param)->num_hdls, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_del_rt_rule((struct ipa_ioc_del_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -808,10 +869,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_flt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_add_flt_rule) + +- ((struct ipa_ioc_add_flt_rule *)header)->num_rules * +- sizeof(struct ipa_flt_rule_add); ++ pre_entry * sizeof(struct ipa_flt_rule_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -821,6 +883,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_flt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_flt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -837,10 +909,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_flt_rule *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_flt_rule) + +- ((struct ipa_ioc_del_flt_rule *)header)->num_hdls * +- sizeof(struct ipa_flt_rule_del); ++ pre_entry * sizeof(struct ipa_flt_rule_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -850,6 +923,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_flt_rule *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_del_flt_rule *)param)-> ++ num_hdls, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_del_flt_rule((struct ipa_ioc_del_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -866,10 +949,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_mdfy_flt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_mdfy_flt_rule) + +- ((struct ipa_ioc_mdfy_flt_rule *)header)->num_rules * +- sizeof(struct ipa_flt_rule_mdfy); ++ pre_entry * sizeof(struct ipa_flt_rule_mdfy); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -879,6 +963,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_mdfy_flt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_mdfy_flt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_mdfy_flt_rule((struct ipa_ioc_mdfy_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -992,9 +1086,10 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_tx_props *) +- header)->num_tx_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_tx_props *) ++ header)->num_tx_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_tx_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -1005,6 +1100,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_tx_props *) ++ param)->num_tx_props ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_query_intf_tx_props *) ++ param)->num_tx_props, pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa_query_intf_tx_props( + (struct ipa_ioc_query_intf_tx_props *)param)) { + retval = -1; +@@ -1027,9 +1132,10 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_rx_props *) +- header)->num_rx_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_rx_props *) ++ header)->num_rx_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_rx_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -1040,6 +1146,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_rx_props *) ++ param)->num_rx_props != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_query_intf_rx_props *) ++ param)->num_rx_props, pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa_query_intf_rx_props( + (struct ipa_ioc_query_intf_rx_props *)param)) { + retval = -1; +@@ -1062,9 +1177,10 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_ext_props *) +- header)->num_ext_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_ext_props *) ++ header)->num_ext_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_ext_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -1075,6 +1191,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_ext_props *) ++ param)->num_ext_props != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_query_intf_ext_props *) ++ param)->num_ext_props, pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa_query_intf_ext_props( + (struct ipa_ioc_query_intf_ext_props *)param)) { + retval = -1; +@@ -1091,8 +1216,10 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- pyld_sz = sizeof(struct ipa_msg_meta) + ++ pre_entry = + ((struct ipa_msg_meta *)header)->msg_len; ++ pyld_sz = sizeof(struct ipa_msg_meta) + ++ pre_entry; + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -1102,6 +1229,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_msg_meta *)param)->msg_len ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_msg_meta *)param)->msg_len, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa_pull_msg((struct ipa_msg_meta *)param, + (char *)param + sizeof(struct ipa_msg_meta), + ((struct ipa_msg_meta *)param)->msg_len) != +@@ -1218,10 +1354,12 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_hdr_proc_ctx *) ++ header)->num_proc_ctxs; + pyld_sz = + sizeof(struct ipa_ioc_add_hdr_proc_ctx) + +- ((struct ipa_ioc_add_hdr_proc_ctx *)header)->num_proc_ctxs * +- sizeof(struct ipa_hdr_proc_ctx_add); ++ pre_entry * sizeof(struct ipa_hdr_proc_ctx_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -1231,6 +1369,15 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_hdr_proc_ctx *) ++ param)->num_proc_ctxs != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_hdr_proc_ctx *) ++ param)->num_proc_ctxs, pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_add_hdr_proc_ctx( + (struct ipa_ioc_add_hdr_proc_ctx *)param)) { + retval = -EFAULT; +@@ -1247,10 +1394,11 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_hdr_proc_ctx *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_hdr_proc_ctx) + +- ((struct ipa_ioc_del_hdr_proc_ctx *)header)->num_hdls * +- sizeof(struct ipa_hdr_proc_ctx_del); ++ pre_entry * sizeof(struct ipa_hdr_proc_ctx_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -1260,6 +1408,16 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_hdr_proc_ctx *) ++ param)->num_hdls != pre_entry)) { ++ IPAERR(" prevent memory corruption( %d not match %d)\n", ++ ((struct ipa_ioc_del_hdr_proc_ctx *)param)-> ++ num_hdls, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa2_del_hdr_proc_ctx( + (struct ipa_ioc_del_hdr_proc_ctx *)param)) { + retval = -EFAULT; +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c +index 041b461..d7e98eb 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c +@@ -592,6 +592,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + struct ipa_ioc_v4_nat_del nat_del; + struct ipa_ioc_rm_dependency rm_depend; + size_t sz; ++ int pre_entry; + + IPADBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd)); + +@@ -645,11 +646,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- ++ pre_entry = ++ ((struct ipa_ioc_nat_dma_cmd *)header)->entries; + pyld_sz = + sizeof(struct ipa_ioc_nat_dma_cmd) + +- ((struct ipa_ioc_nat_dma_cmd *)header)->entries * +- sizeof(struct ipa_ioc_nat_dma_one); ++ pre_entry * sizeof(struct ipa_ioc_nat_dma_one); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -660,7 +661,15 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_nat_dma_cmd *)param)->entries ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_nat_dma_cmd *)param)->entries, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_nat_dma_cmd((struct ipa_ioc_nat_dma_cmd *)param)) { + retval = -EFAULT; + break; +@@ -685,10 +694,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_hdr *)header)->num_hdrs; + pyld_sz = + sizeof(struct ipa_ioc_add_hdr) + +- ((struct ipa_ioc_add_hdr *)header)->num_hdrs * +- sizeof(struct ipa_hdr_add); ++ pre_entry * sizeof(struct ipa_hdr_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -698,6 +708,15 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_hdr *)param)->num_hdrs ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_hdr *)param)->num_hdrs, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_add_hdr((struct ipa_ioc_add_hdr *)param)) { + retval = -EFAULT; + break; +@@ -714,10 +733,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_hdr *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_hdr) + +- ((struct ipa_ioc_del_hdr *)header)->num_hdls * +- sizeof(struct ipa_hdr_del); ++ pre_entry * sizeof(struct ipa_hdr_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -727,6 +747,15 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_hdr *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_del_hdr *)param)->num_hdls, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_del_hdr((struct ipa_ioc_del_hdr *)param)) { + retval = -EFAULT; + break; +@@ -743,10 +772,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_rt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_add_rt_rule) + +- ((struct ipa_ioc_add_rt_rule *)header)->num_rules * +- sizeof(struct ipa_rt_rule_add); ++ pre_entry * sizeof(struct ipa_rt_rule_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -756,6 +786,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_rt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_rt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -772,10 +812,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_rt_rule_after *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_add_rt_rule_after) + +- ((struct ipa_ioc_add_rt_rule_after *)header)->num_rules * +- sizeof(struct ipa_rt_rule_add); ++ pre_entry * sizeof(struct ipa_rt_rule_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -785,6 +826,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_rt_rule_after *)param)-> ++ num_rules != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_rt_rule_after *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_add_rt_rule_after( + (struct ipa_ioc_add_rt_rule_after *)param)) { + +@@ -803,10 +854,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_mdfy_rt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_mdfy_rt_rule) + +- ((struct ipa_ioc_mdfy_rt_rule *)header)->num_rules * +- sizeof(struct ipa_rt_rule_mdfy); ++ pre_entry * sizeof(struct ipa_rt_rule_mdfy); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -816,6 +868,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_mdfy_rt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_mdfy_rt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_mdfy_rt_rule((struct ipa_ioc_mdfy_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -832,10 +894,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_rt_rule *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_rt_rule) + +- ((struct ipa_ioc_del_rt_rule *)header)->num_hdls * +- sizeof(struct ipa_rt_rule_del); ++ pre_entry * sizeof(struct ipa_rt_rule_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -845,6 +908,15 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_rt_rule *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_del_rt_rule *)param)->num_hdls, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_del_rt_rule((struct ipa_ioc_del_rt_rule *)param)) { + retval = -EFAULT; + break; +@@ -861,10 +933,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_flt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_add_flt_rule) + +- ((struct ipa_ioc_add_flt_rule *)header)->num_rules * +- sizeof(struct ipa_flt_rule_add); ++ pre_entry * sizeof(struct ipa_flt_rule_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -874,6 +947,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_flt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_flt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -891,10 +974,12 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_flt_rule_after *)header)-> ++ num_rules; + pyld_sz = + sizeof(struct ipa_ioc_add_flt_rule_after) + +- ((struct ipa_ioc_add_flt_rule_after *)header)->num_rules * +- sizeof(struct ipa_flt_rule_add); ++ pre_entry * sizeof(struct ipa_flt_rule_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -904,6 +989,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_flt_rule_after *)param)-> ++ num_rules != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_flt_rule_after *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_add_flt_rule_after( + (struct ipa_ioc_add_flt_rule_after *)param)) { + retval = -EFAULT; +@@ -921,10 +1016,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_flt_rule *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_flt_rule) + +- ((struct ipa_ioc_del_flt_rule *)header)->num_hdls * +- sizeof(struct ipa_flt_rule_del); ++ pre_entry * sizeof(struct ipa_flt_rule_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -934,6 +1030,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_flt_rule *)param)->num_hdls ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_del_flt_rule *)param)-> ++ num_hdls, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_del_flt_rule((struct ipa_ioc_del_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -950,10 +1056,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_mdfy_flt_rule *)header)->num_rules; + pyld_sz = + sizeof(struct ipa_ioc_mdfy_flt_rule) + +- ((struct ipa_ioc_mdfy_flt_rule *)header)->num_rules * +- sizeof(struct ipa_flt_rule_mdfy); ++ pre_entry * sizeof(struct ipa_flt_rule_mdfy); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -963,6 +1070,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_mdfy_flt_rule *)param)->num_rules ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_mdfy_flt_rule *)param)-> ++ num_rules, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_mdfy_flt_rule((struct ipa_ioc_mdfy_flt_rule *)param)) { + retval = -EFAULT; + break; +@@ -1076,9 +1193,10 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_tx_props *) +- header)->num_tx_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_tx_props *) ++ header)->num_tx_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_tx_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -1089,6 +1207,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_tx_props *) ++ param)->num_tx_props ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_query_intf_tx_props *) ++ param)->num_tx_props, pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_query_intf_tx_props( + (struct ipa_ioc_query_intf_tx_props *)param)) { + retval = -1; +@@ -1111,9 +1239,10 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_rx_props *) +- header)->num_rx_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_rx_props *) ++ header)->num_rx_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_rx_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -1124,6 +1253,15 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_rx_props *) ++ param)->num_rx_props != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_query_intf_rx_props *) ++ param)->num_rx_props, pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_query_intf_rx_props( + (struct ipa_ioc_query_intf_rx_props *)param)) { + retval = -1; +@@ -1146,9 +1284,10 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- +- pyld_sz = sz + ((struct ipa_ioc_query_intf_ext_props *) +- header)->num_ext_props * ++ pre_entry = ++ ((struct ipa_ioc_query_intf_ext_props *) ++ header)->num_ext_props; ++ pyld_sz = sz + pre_entry * + sizeof(struct ipa_ioc_ext_intf_prop); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { +@@ -1159,6 +1298,15 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_query_intf_ext_props *) ++ param)->num_ext_props != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_query_intf_ext_props *) ++ param)->num_ext_props, pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_query_intf_ext_props( + (struct ipa_ioc_query_intf_ext_props *)param)) { + retval = -1; +@@ -1175,8 +1323,10 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } +- pyld_sz = sizeof(struct ipa_msg_meta) + ++ pre_entry = + ((struct ipa_msg_meta *)header)->msg_len; ++ pyld_sz = sizeof(struct ipa_msg_meta) + ++ pre_entry; + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -1186,6 +1336,15 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_msg_meta *)param)->msg_len ++ != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_msg_meta *)param)->msg_len, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_pull_msg((struct ipa_msg_meta *)param, + (char *)param + sizeof(struct ipa_msg_meta), + ((struct ipa_msg_meta *)param)->msg_len) != +@@ -1302,10 +1461,12 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_add_hdr_proc_ctx *) ++ header)->num_proc_ctxs; + pyld_sz = + sizeof(struct ipa_ioc_add_hdr_proc_ctx) + +- ((struct ipa_ioc_add_hdr_proc_ctx *)header)->num_proc_ctxs * +- sizeof(struct ipa_hdr_proc_ctx_add); ++ pre_entry * sizeof(struct ipa_hdr_proc_ctx_add); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -1315,6 +1476,15 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_add_hdr_proc_ctx *) ++ param)->num_proc_ctxs != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_add_hdr_proc_ctx *) ++ param)->num_proc_ctxs, pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_add_hdr_proc_ctx( + (struct ipa_ioc_add_hdr_proc_ctx *)param)) { + retval = -EFAULT; +@@ -1331,10 +1501,11 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ pre_entry = ++ ((struct ipa_ioc_del_hdr_proc_ctx *)header)->num_hdls; + pyld_sz = + sizeof(struct ipa_ioc_del_hdr_proc_ctx) + +- ((struct ipa_ioc_del_hdr_proc_ctx *)header)->num_hdls * +- sizeof(struct ipa_hdr_proc_ctx_del); ++ pre_entry * sizeof(struct ipa_hdr_proc_ctx_del); + param = kzalloc(pyld_sz, GFP_KERNEL); + if (!param) { + retval = -ENOMEM; +@@ -1344,6 +1515,16 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EFAULT; + break; + } ++ /* add check in case user-space module compromised */ ++ if (unlikely(((struct ipa_ioc_del_hdr_proc_ctx *) ++ param)->num_hdls != pre_entry)) { ++ IPAERR(" prevent memory corruption(%d not match %d)\n", ++ ((struct ipa_ioc_del_hdr_proc_ctx *)param)-> ++ num_hdls, ++ pre_entry); ++ retval = -EINVAL; ++ break; ++ } + if (ipa3_del_hdr_proc_ctx( + (struct ipa_ioc_del_hdr_proc_ctx *)param)) { + retval = -EFAULT; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3893/0.patch b/Patches/Linux_CVEs/CVE-2016-3893/0.patch new file mode 100644 index 00000000..6e74ecb2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3893/0.patch @@ -0,0 +1,37 @@ +From a7a6ddc91cce7ad5ad55c9709b24bfc80f5ac873 Mon Sep 17 00:00:00 2001 +From: Patrick Daly +Date: Thu, 28 May 2015 18:32:49 -0700 +Subject: ASoC: wcd9xxx: Fix unprotected userspace access + +Protect against memory faults while accessing userspace addresses. + +Change-Id: I1433bac73d24d428749558e530e6869c2e5ee98f +Signed-off-by: Patrick Daly +--- + sound/soc/codecs/wcdcal-hwdep.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/wcdcal-hwdep.c b/sound/soc/codecs/wcdcal-hwdep.c +index 5013bee..954620a 100644 +--- a/sound/soc/codecs/wcdcal-hwdep.c ++++ b/sound/soc/codecs/wcdcal-hwdep.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2015, The 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 +@@ -82,7 +82,8 @@ static int wcdcal_hwdep_ioctl_shared(struct snd_hwdep *hw, + return -EFAULT; + } + data = fw[fw_user.cal_type]->data; +- memcpy(data, fw_user.buffer, fw_user.size); ++ if (copy_from_user(data, fw_user.buffer, fw_user.size)) ++ return -EFAULT; + fw[fw_user.cal_type]->size = fw_user.size; + mutex_lock(&fw_data->lock); + set_bit(WCDCAL_RECIEVED, &fw_data->wcdcal_state[fw_user.cal_type]); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3894/0.patch b/Patches/Linux_CVEs/CVE-2016-3894/0.patch new file mode 100644 index 00000000..c1f6cbc8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3894/0.patch @@ -0,0 +1,26 @@ +From c91479f60bbca0ece50d184e4cfcda52ddb5983e Mon Sep 17 00:00:00 2001 +From: Min Chong +Date: Sun, 17 Jul 2016 23:23:02 -0700 +Subject: [PATCH] msm: dma: remove dma_test from defconfig + +Unset CONFIG_MSM_DMA_TEST since it is not required. + +Bug: 29618014 +Change-Id: Iac46f1b028c96af765d5c2a5a501cdcd19513f84 +Signed-off-by: Min Chong +--- + arch/arm/configs/shamu_defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm/configs/shamu_defconfig b/arch/arm/configs/shamu_defconfig +index 558714ebd51ff..92fa34b5597c4 100644 +--- a/arch/arm/configs/shamu_defconfig ++++ b/arch/arm/configs/shamu_defconfig +@@ -37,6 +37,7 @@ CONFIG_MSM_SMD=y + CONFIG_MSM_PCIE=y + CONFIG_MSM_SMP2P=y + CONFIG_MSM_SMP2P_TEST=y ++# CONFIG_MSM_DMA_TEST is not set + CONFIG_MSM_SUBSYSTEM_RESTART=y + CONFIG_MSM_SYSMON_COMM=y + CONFIG_MSM_PIL_SSR_GENERIC=y diff --git a/Patches/Linux_CVEs/CVE-2016-3894/1.patch b/Patches/Linux_CVEs/CVE-2016-3894/1.patch new file mode 100644 index 00000000..3c220f50 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3894/1.patch @@ -0,0 +1,31 @@ +From de3e3e5930b1edfebec7870390443279ec5b65fe Mon Sep 17 00:00:00 2001 +From: Srinivasarao P +Date: Fri, 22 Jul 2016 12:48:33 +0530 +Subject: msm : dma_test: Initialize newly allocated memory + +The MSM_DMA_IOALLOC ioctl command allocates kernel memory and +this memory can be read back using the MSM_DMA_IORBUF ioctl command. +This memory is not zero-initialized and may contain sensitive data. + +Change-Id: I8c55d6fe500e7607690b89806715893783eecf9c +Signed-off-by: Srinivasarao P +--- + arch/arm/mach-msm/dma_test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mach-msm/dma_test.c b/arch/arm/mach-msm/dma_test.c +index 3d13e4e..1d717c3 100644 +--- a/arch/arm/mach-msm/dma_test.c ++++ b/arch/arm/mach-msm/dma_test.c +@@ -99,7 +99,7 @@ static int buffer_req(struct msm_dma_alloc_req *req) + if (i >= MAX_TEST_BUFFERS) + goto error; + +- buffers[i] = kmalloc(req->size, GFP_KERNEL | __GFP_DMA); ++ buffers[i] = kzalloc(req->size, GFP_KERNEL | __GFP_DMA); + if (buffers[i] == 0) + goto error; + sizes[i] = req->size; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3902/0.patch b/Patches/Linux_CVEs/CVE-2016-3902/0.patch new file mode 100644 index 00000000..66c6ddff --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3902/0.patch @@ -0,0 +1,44 @@ +From 2fca425d781572393fbe51abe2e27a932d24a768 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Fri, 22 Jul 2016 15:03:16 -0700 +Subject: msm: ipa: handle information leak on ADD_FLT_RULE_INDEX ioctl + +IPA might have Information leak and device crash due to +kernel heap overread in IPA driver when processing +WAN_IOC_ADD_FLT_RULE_INDEX ioctl. The fix is to add +check on max number of filter rules send to modem. + +Change-Id: I454e04d05cfcb7af8fc4bd2b4a1bade55c4684d0 +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa_qmi_service.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/msm/ipa/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_qmi_service.c +index d68350a..58d7c181 100644 +--- a/drivers/platform/msm/ipa/ipa_qmi_service.c ++++ b/drivers/platform/msm/ipa/ipa_qmi_service.c +@@ -491,7 +491,7 @@ int qmi_filter_request_send(struct ipa_install_fltr_rule_req_msg_v01 *req) + if (req->filter_spec_list_len == 0) { + IPAWANDBG("IPACM pass zero rules to Q6\n"); + } else { +- IPAWANDBG("IPACM pass %d rules to Q6\n", ++ IPAWANDBG("IPACM pass %u rules to Q6\n", + req->filter_spec_list_len); + } + +@@ -622,6 +622,11 @@ int qmi_filter_notify_send(struct ipa_fltr_installed_notif_req_msg_v01 *req) + IPAWANERR(" delete UL filter rule for pipe %d\n", + req->source_pipe_index); + return -EINVAL; ++ } else if (req->filter_index_list_len > QMI_IPA_MAX_FILTERS_V01) { ++ IPAWANERR(" UL filter rule for pipe %d exceed max (%u)\n", ++ req->source_pipe_index, ++ req->filter_index_list_len); ++ return -EINVAL; + } else if (req->filter_index_list[0].filter_index == 0 && + req->source_pipe_index != + ipa_get_ep_mapping(IPA_CLIENT_APPS_LAN_WAN_PROD)) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3903/0.patch b/Patches/Linux_CVEs/CVE-2016-3903/0.patch new file mode 100644 index 00000000..2b2badff --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3903/0.patch @@ -0,0 +1,57 @@ +From b8874573428e8ce024f57c6242d662fcca5e5d55 Mon Sep 17 00:00:00 2001 +From: VijayaKumar T M +Date: Mon, 25 Jul 2016 11:53:19 +0530 +Subject: msm: camera: sensor: Fix use after free condition + +Add a check to return value before calling csid config which will +otherwise lead to use after free scenario. + +CRs-Fixed: 1040857 +Change-Id: I4f4d9e38eeb537875e0d01de0e99913a44dd3f3f +Signed-off-by: VijayaKumar T M +--- + drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +index 5864096..7dd2959 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2016, The 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 +@@ -518,7 +518,7 @@ static int32_t msm_csid_cmd(struct csid_device *csid_dev, void __user *arg) + break; + } + if (csid_params.lut_params.num_cid < 1 || +- csid_params.lut_params.num_cid > 16) { ++ csid_params.lut_params.num_cid > MAX_CID) { + pr_err("%s: %d num_cid outside range\n", + __func__, __LINE__); + rc = -EINVAL; +@@ -547,6 +547,10 @@ static int32_t msm_csid_cmd(struct csid_device *csid_dev, void __user *arg) + csid_params.lut_params.vc_cfg[i] = vc_cfg; + } + csid_dev->csid_sof_debug = 0; ++ if (rc < 0) { ++ pr_err("%s:%d failed\n", __func__, __LINE__); ++ break; ++ } + rc = msm_csid_config(csid_dev, &csid_params); + for (i--; i >= 0; i--) + kfree(csid_params.lut_params.vc_cfg[i]); +@@ -658,7 +662,7 @@ static int32_t msm_csid_cmd32(struct csid_device *csid_dev, void __user *arg) + csid_params.lut_params.num_cid = lut_par32.num_cid; + + if (csid_params.lut_params.num_cid < 1 || +- csid_params.lut_params.num_cid > 16) { ++ csid_params.lut_params.num_cid > MAX_CID) { + pr_err("%s: %d num_cid outside range\n", + __func__, __LINE__); + rc = -EINVAL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3904/0.patch b/Patches/Linux_CVEs/CVE-2016-3904/0.patch new file mode 100644 index 00000000..78d2a26b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3904/0.patch @@ -0,0 +1,39 @@ +From 069683407ca9a820d05c914b57c587bcd3f16a3a Mon Sep 17 00:00:00 2001 +From: David Dai +Date: Fri, 5 Aug 2016 15:14:25 -0700 +Subject: msm: msm_bus: limit max chars read by sscanf + +Current bus_floor_vote_store_api does not limit/check +the size of the string in input, allowing stack overflow. +Specify the max number of characters read allowable to +the size of destination buffer. + +CRs-Fixed: 1050455 +Change-Id: Ia9227480be6ea4f3ade71f5675f95a3efd9fcf99 +Signed-off-by: David Dai +--- + drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c b/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c +index e4c8f1f..a876484 100644 +--- a/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c ++++ b/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * + * This program is Mree software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -133,7 +133,7 @@ static ssize_t bus_floor_vote_store_api(struct device *dev, + return 0; + } + +- if (sscanf(buf, "%s %llu", name, &vote_khz) != 2) { ++ if (sscanf(buf, "%9s %llu", name, &vote_khz) != 2) { + pr_err("%s:return error", __func__); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3906/0.patch b/Patches/Linux_CVEs/CVE-2016-3906/0.patch new file mode 100644 index 00000000..bf4ab19e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3906/0.patch @@ -0,0 +1,143 @@ +From 46d740d12c2a8bd9e0b27a968af6544682f7cb0e Mon Sep 17 00:00:00 2001 +From: Archana Sathyakumar +Date: Mon, 22 Aug 2016 15:20:02 -0600 +Subject: msm-core: debug: Update the number of supported pstates + +Update the number of power-freq pair value supported in the debug +interface. Parse the arguments as uint32_t instead of uint64_t which +might cause memory corruption. + +CRs-fixed: 1054344 +Change-Id: I30492b79b96356177cdcc72e4e2ee656317de500 +Signed-off-by: Archana Sathyakumar +--- + drivers/power/qcom/debug_core.c | 51 +++++++++++++++++++++++++---------------- + 1 file changed, 31 insertions(+), 20 deletions(-) + +diff --git a/drivers/power/qcom/debug_core.c b/drivers/power/qcom/debug_core.c +index e1375ff..f0333cb 100644 +--- a/drivers/power/qcom/debug_core.c ++++ b/drivers/power/qcom/debug_core.c +@@ -83,15 +83,28 @@ static struct debugfs_blob_wrapper help_msg = { + + }; + +-static void add_to_ptable(uint64_t *arg) ++static void add_to_ptable(unsigned int *arg) + { + struct core_debug *node; + int i, cpu = arg[CPU_OFFSET]; ++ uint32_t freq = arg[FREQ_OFFSET]; ++ uint32_t power = arg[POWER_OFFSET]; + + if (!cpu_possible(cpu)) + return; + ++ if ((freq == 0) || (power == 0)) { ++ pr_warn("Incorrect power data\n"); ++ return; ++ } ++ + node = &per_cpu(c_dgfs, cpu); ++ ++ if (node->len >= MAX_PSTATES) { ++ pr_warn("Dropped ptable update - no space left.\n"); ++ return; ++ } ++ + if (!node->head) { + node->head = kzalloc(sizeof(struct cpu_pstate_pwr) * + (MAX_PSTATES + 1), +@@ -99,24 +112,18 @@ static void add_to_ptable(uint64_t *arg) + if (!node->head) + return; + } +- for (i = 0; i < MAX_PSTATES; i++) { +- if (node->head[i].freq == arg[FREQ_OFFSET]) { +- node->head[i].power = arg[POWER_OFFSET]; ++ ++ for (i = 0; i < node->len; i++) { ++ if (node->head[i].freq == freq) { ++ node->head[i].power = power; + return; + } +- if (node->head[i].freq == 0) +- break; +- } +- +- if (i == MAX_PSTATES) { +- pr_warn("Dropped ptable update - no space left.\n"); +- return; + } + + /* Insert a new frequency (may need to move things around to + keep in ascending order). */ + for (i = MAX_PSTATES - 1; i > 0; i--) { +- if (node->head[i-1].freq > arg[FREQ_OFFSET]) { ++ if (node->head[i-1].freq > freq) { + node->head[i].freq = node->head[i-1].freq; + node->head[i].power = node->head[i-1].power; + } else if (node->head[i-1].freq != 0) { +@@ -124,15 +131,17 @@ static void add_to_ptable(uint64_t *arg) + } + } + +- node->head[i].freq = arg[FREQ_OFFSET]; +- node->head[i].power = arg[POWER_OFFSET]; +- node->len++; ++ if (node->len < MAX_PSTATES) { ++ node->head[i].freq = freq; ++ node->head[i].power = power; ++ node->len++; ++ } + + if (node->ptr) + node->ptr->len = node->len; + } + +-static int split_ptable_args(char *line, uint64_t *arg, uint32_t n) ++static int split_ptable_args(char *line, unsigned int *arg, uint32_t n) + { + char *args; + int i; +@@ -142,7 +151,9 @@ static int split_ptable_args(char *line, uint64_t *arg, uint32_t n) + if (!line) + break; + args = strsep(&line, " "); +- ret = kstrtoull(args, 10, &arg[i]); ++ ret = kstrtouint(args, 10, &arg[i]); ++ if (ret) ++ return ret; + } + return ret; + } +@@ -152,7 +163,7 @@ static ssize_t msm_core_ptable_write(struct file *file, + { + char *kbuf; + int ret; +- uint64_t arg[3]; ++ unsigned int arg[3]; + + if (len == 0) + return 0; +@@ -204,7 +215,7 @@ static int msm_core_ptable_read(struct seq_file *m, void *data) + seq_printf(m, "--- CPU%d - Live numbers at %ldC---\n", + cpu, node->ptr->temp); + print_table(m, msm_core_data[cpu].ptable, +- msm_core_data[cpu].len); ++ node->driver_len); + } + } + return 0; +@@ -215,7 +226,7 @@ static ssize_t msm_core_enable_write(struct file *file, + { + char *kbuf; + int ret; +- uint64_t arg[3]; ++ unsigned int arg[3]; + int cpu; + + if (len == 0) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3907/0.patch b/Patches/Linux_CVEs/CVE-2016-3907/0.patch new file mode 100644 index 00000000..3dab7180 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3907/0.patch @@ -0,0 +1,33 @@ +From 744330f4e5d70dce71c4c9e03c5b6a8b59bb0cda Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Tue, 16 Aug 2016 13:03:56 -0700 +Subject: misc: qcom: qdsp6v2: initialize wma_config_32 + +Not all memebers of wma_config_32 are set before they are used which +might lead to invalid values being passed and used. To fix this issue +initialize all member variables of struct wma_config_32 to 0 before +assigning specific values individually. + +Change-Id: Ibb082ce691625527e9a9ffd4978dea7ba4df9e84 +CRs-Fixed: 1054352 +Signed-off-by: Siena Richard +--- + drivers/misc/qcom/qdsp6v2/audio_wma.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_wma.c b/drivers/misc/qcom/qdsp6v2/audio_wma.c +index 9877937..cb5a9b1 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_wma.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_wma.c +@@ -162,6 +162,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, + struct msm_audio_wma_config_v2 *wma_config; + struct msm_audio_wma_config_v2_32 wma_config_32; + ++ memset(&wma_config_32, 0, sizeof(wma_config_32)); ++ + wma_config = (struct msm_audio_wma_config_v2 *)audio->codec_cfg; + wma_config_32.format_tag = wma_config->format_tag; + wma_config_32.numchannels = wma_config->numchannels; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3931/0.patch b/Patches/Linux_CVEs/CVE-2016-3931/0.patch new file mode 100644 index 00000000..054d871e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3931/0.patch @@ -0,0 +1,134 @@ +From e80b88323f9ff0bb0e545f209eec08ec56fca816 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Mon, 18 Jul 2016 13:20:18 -0700 +Subject: qseecom: validate the inputs of __qseecom_send_modfd_resp + +The resp_len and resp_buf_ptr of qseecom_send_modfd_listener_resp +are not checked, then an userspace application that manipulates +resp_len can corrupt the kernel memory. Thus make changes to +validate these parameters. + +CRs-fixed: 1036418 +Change-Id: Id43ec6b55b332d0dac09a9abb998a410f49b44f7 +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 78 +++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 61 insertions(+), 17 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index b175965c..1168181 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -3065,41 +3065,80 @@ static int qseecom_send_resp(void) + } + + +-static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data, +- void __user *argp) ++static int __validate_send_modfd_resp_inputs(struct qseecom_dev_handle *data, ++ struct qseecom_send_modfd_listener_resp *resp, ++ struct qseecom_registered_listener_list *this_lstnr) + { +- 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"); ++ if (!data || !resp || !this_lstnr) { ++ pr_err("listener handle or resp msg is null\n"); + return -EINVAL; + } +- this_lstnr = __qseecom_find_svc(data->listener.id); +- if (this_lstnr == NULL) ++ ++ if (resp->resp_buf_ptr == NULL) { ++ pr_err("resp buffer is null\n"); ++ return -EINVAL; ++ } ++ /* validate resp buf length */ ++ if ((resp->resp_len == 0) || ++ (resp->resp_len > this_lstnr->sb_length)) { ++ pr_err("resp buf length %d not valid\n", resp->resp_len); + return -EINVAL; ++ } + +- if (resp.resp_buf_ptr == NULL) { +- pr_err("Invalid resp_buf_ptr\n"); ++ if ((uintptr_t)resp->resp_buf_ptr > (ULONG_MAX - resp->resp_len)) { ++ pr_err("Integer overflow in resp_len & resp_buf\n"); ++ return -EINVAL; ++ } ++ if ((uintptr_t)this_lstnr->user_virt_sb_base > ++ (ULONG_MAX - this_lstnr->sb_length)) { ++ pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); + return -EINVAL; + } ++ /* validate resp buf */ ++ if (((uintptr_t)resp->resp_buf_ptr < ++ (uintptr_t)this_lstnr->user_virt_sb_base) || ++ ((uintptr_t)resp->resp_buf_ptr >= ++ ((uintptr_t)this_lstnr->user_virt_sb_base + ++ this_lstnr->sb_length)) || ++ (((uintptr_t)resp->resp_buf_ptr + resp->resp_len) > ++ ((uintptr_t)this_lstnr->user_virt_sb_base + ++ this_lstnr->sb_length))) { ++ pr_err("resp buf is out of shared buffer region\n"); ++ return -EINVAL; ++ } ++ + /* validate offsets */ + for (i = 0; i < MAX_ION_FD; i++) { +- if (resp.ifd_data[i].cmd_buf_offset >= resp.resp_len) { ++ if (resp->ifd_data[i].cmd_buf_offset >= resp->resp_len) { + pr_err("Invalid offset %d = 0x%x\n", +- i, resp.ifd_data[i].cmd_buf_offset); ++ i, resp->ifd_data[i].cmd_buf_offset); + return -EINVAL; + } + } + +- if ((resp.resp_buf_ptr < this_lstnr->user_virt_sb_base) || +- ((uintptr_t)resp.resp_buf_ptr >= +- ((uintptr_t)this_lstnr->user_virt_sb_base + +- this_lstnr->sb_length))) { +- pr_err("resp_buf_ptr address not within shared buffer\n"); ++ return 0; ++} ++ ++static int __qseecom_send_modfd_resp(struct qseecom_dev_handle *data, ++ void __user *argp, bool is_64bit_addr) ++{ ++ struct qseecom_send_modfd_listener_resp resp; ++ 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 (__validate_send_modfd_resp_inputs(data, &resp, this_lstnr)) ++ return -EINVAL; ++ + resp.resp_buf_ptr = this_lstnr->sb_virt + + (uintptr_t)(resp.resp_buf_ptr - this_lstnr->user_virt_sb_base); + __qseecom_update_cmd_buf(&resp, false, data, true); +@@ -3108,6 +3147,11 @@ static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data, + return 0; + } + ++static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data, ++ void __user *argp) ++{ ++ return __qseecom_send_modfd_resp(data, argp, false); ++} + + static int qseecom_get_qseos_version(struct qseecom_dev_handle *data, + void __user *argp) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3934/0.patch b/Patches/Linux_CVEs/CVE-2016-3934/0.patch new file mode 100644 index 00000000..a0cdb855 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3934/0.patch @@ -0,0 +1,74 @@ +From 27fbeb6b025d5d46ccb0497cbed4c6e78ed1c5cc Mon Sep 17 00:00:00 2001 +From: Vasko Kalanoski +Date: Tue, 3 Feb 2015 13:17:44 +0200 +Subject: msm: camera: restructure data handling to be more robust + +add dynamic array allocation instead of static to prevent +stack overflow. + +Change-Id: Id12ed5b01809021d2b1d1d71436f2523b575d9de +Signed-off-by: Vasko Kalanoski +--- + .../msm/camera_v2/sensor/io/msm_camera_cci_i2c.c | 25 +++++++++++++++------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +index 4b0bde95..59ad29f 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2015, The 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 +@@ -138,23 +138,30 @@ int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client, + int32_t rc = -EFAULT; + uint8_t i = 0; + struct msm_camera_cci_ctrl cci_ctrl; +- struct msm_camera_i2c_reg_array reg_conf_tbl[num_byte]; ++ struct msm_camera_i2c_reg_array *reg_conf_tbl = NULL; + + if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR + && client->addr_type != MSM_CAMERA_I2C_WORD_ADDR) + || num_byte == 0) + return rc; + +- S_I2C_DBG("%s reg addr = 0x%x num bytes: %d\n", +- __func__, addr, num_byte); +- memset(reg_conf_tbl, 0, +- num_byte * sizeof(struct msm_camera_i2c_reg_array)); +- reg_conf_tbl[0].reg_addr = addr; + if (num_byte > I2C_SEQ_REG_DATA_MAX) { + pr_err("%s: num_byte=%d clamped to max supported %d\n", + __func__, num_byte, I2C_SEQ_REG_DATA_MAX); +- num_byte = I2C_SEQ_REG_DATA_MAX; ++ return rc; + } ++ ++ S_I2C_DBG("%s reg addr = 0x%x num bytes: %d\n", ++ __func__, addr, num_byte); ++ ++ reg_conf_tbl = kzalloc(num_byte * ++ (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); ++ if (!reg_conf_tbl) { ++ pr_err("%s:%d no memory\n", __func__, __LINE__); ++ return -ENOMEM; ++ } ++ ++ reg_conf_tbl[0].reg_addr = addr; + for (i = 0; i < num_byte; i++) { + reg_conf_tbl[i].reg_data = data[i]; + reg_conf_tbl[i].delay = 0; +@@ -169,6 +176,8 @@ int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client, + core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl); + CDBG("%s line %d rc = %d\n", __func__, __LINE__, rc); + rc = cci_ctrl.status; ++ kfree(reg_conf_tbl); ++ reg_conf_tbl = NULL; + return rc; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-3935/0.patch b/Patches/Linux_CVEs/CVE-2016-3935/0.patch new file mode 100644 index 00000000..4b807753 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-3935/0.patch @@ -0,0 +1,59 @@ +From 5f69ccf3b011c1d14a1b1b00dbaacf74307c9132 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Fri, 29 Jul 2016 15:32:31 -0700 +Subject: msm: crypto: Fix integer over flow check in qcedev driver + +Integer overflow check always fails when ULONG_MAX is used, +as ULONG_MAX is 2^64-1, while req->data[i].len and total +are uint32_t. Make change to use U32_MAX instead of +ULONG_MAX. + +CRs-fixed: 1046507 +Change-Id: Iccf9c32400ecc7ffc0afae16f58c38e5d78a5b64 +Signed-off-by: Zhen Kong +--- + drivers/crypto/msm/qcedev.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c +index 51f5069..e63f061 100644 +--- a/drivers/crypto/msm/qcedev.c ++++ b/drivers/crypto/msm/qcedev.c +@@ -1,6 +1,6 @@ + /* Qualcomm CE device driver. + * +- * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2010-2016, The 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 +@@ -1543,7 +1543,7 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, + } + /* Check for sum of all dst length is equal to data_len */ + for (i = 0; i < req->entries; i++) { +- if (req->vbuf.dst[i].len >= ULONG_MAX - total) { ++ if (req->vbuf.dst[i].len >= U32_MAX - total) { + pr_err("%s: Integer overflow on total req dst vbuf length\n", + __func__); + goto error; +@@ -1557,7 +1557,7 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, + } + /* Check for sum of all src length is equal to data_len */ + for (i = 0, total = 0; i < req->entries; i++) { +- if (req->vbuf.src[i].len > ULONG_MAX - total) { ++ if (req->vbuf.src[i].len > U32_MAX - total) { + pr_err("%s: Integer overflow on total req src vbuf length\n", + __func__); + goto error; +@@ -1619,7 +1619,7 @@ static int qcedev_check_sha_params(struct qcedev_sha_op_req *req, + + /* Check for sum of all src length is equal to data_len */ + for (i = 0, total = 0; i < req->entries; i++) { +- if (req->data[i].len > ULONG_MAX - total) { ++ if (req->data[i].len > U32_MAX - total) { + pr_err("%s: Integer overflow on total req buf length\n", + __func__); + goto sha_error; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-4486/0.patch b/Patches/Linux_CVEs/CVE-2016-4486/0.patch new file mode 100644 index 00000000..cd795789 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-4486/0.patch @@ -0,0 +1,50 @@ +From 5f8e44741f9f216e33736ea4ec65ca9ac03036e6 Mon Sep 17 00:00:00 2001 +From: Kangjie Lu +Date: Tue, 3 May 2016 16:46:24 -0400 +Subject: net: fix infoleak in rtnetlink +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The stack object “map” has a total size of 32 bytes. Its last 4 +bytes are padding generated by compiler. These padding bytes are +not initialized and sent out via “nla_put”. + +Signed-off-by: Kangjie Lu +Signed-off-by: David S. Miller +--- + net/core/rtnetlink.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index a75f7e9..65763c2 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -1180,14 +1180,16 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, + + static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev) + { +- struct rtnl_link_ifmap map = { +- .mem_start = dev->mem_start, +- .mem_end = dev->mem_end, +- .base_addr = dev->base_addr, +- .irq = dev->irq, +- .dma = dev->dma, +- .port = dev->if_port, +- }; ++ struct rtnl_link_ifmap map; ++ ++ memset(&map, 0, sizeof(map)); ++ map.mem_start = dev->mem_start; ++ map.mem_end = dev->mem_end; ++ map.base_addr = dev->base_addr; ++ map.irq = dev->irq; ++ map.dma = dev->dma; ++ map.port = dev->if_port; ++ + if (nla_put(skb, IFLA_MAP, sizeof(map), &map)) + return -EMSGSIZE; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-4569/0.patch b/Patches/Linux_CVEs/CVE-2016-4569/0.patch new file mode 100644 index 00000000..853cd474 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-4569/0.patch @@ -0,0 +1,33 @@ +From cec8f96e49d9be372fdb0c3836dcf31ec71e457e Mon Sep 17 00:00:00 2001 +From: Kangjie Lu +Date: Tue, 3 May 2016 16:44:07 -0400 +Subject: ALSA: timer: Fix leak in SNDRV_TIMER_IOCTL_PARAMS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The stack object “tread” has a total size of 32 bytes. Its field +“event” and “val” both contain 4 bytes padding. These 8 bytes +padding bytes are sent to user without being initialized. + +Signed-off-by: Kangjie Lu +Signed-off-by: Takashi Iwai +--- + sound/core/timer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 0cfc028..306a93d 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -1737,6 +1737,7 @@ static int snd_timer_user_params(struct file *file, + if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { + if (tu->tread) { + struct snd_timer_tread tread; ++ memset(&tread, 0, sizeof(tread)); + tread.event = SNDRV_TIMER_EVENT_EARLY; + tread.tstamp.tv_sec = 0; + tread.tstamp.tv_nsec = 0; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-4578/0.patch b/Patches/Linux_CVEs/CVE-2016-4578/0.patch new file mode 100644 index 00000000..ca174f91 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-4578/0.patch @@ -0,0 +1,33 @@ +From 9a47e9cff994f37f7f0dbd9ae23740d0f64f9fe6 Mon Sep 17 00:00:00 2001 +From: Kangjie Lu +Date: Tue, 3 May 2016 16:44:20 -0400 +Subject: ALSA: timer: Fix leak in events via snd_timer_user_ccallback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The stack object “r1” has a total size of 32 bytes. Its field +“event” and “val” both contain 4 bytes padding. These 8 bytes +padding bytes are sent to user without being initialized. + +Signed-off-by: Kangjie Lu +Signed-off-by: Takashi Iwai +--- + sound/core/timer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 306a93d..cc3c08d 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -1223,6 +1223,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, + tu->tstamp = *tstamp; + if ((tu->filter & (1 << event)) == 0 || !tu->tread) + return; ++ memset(&r1, 0, sizeof(r1)); + r1.event = event; + r1.tstamp = *tstamp; + r1.val = resolution; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-4794/0.patch b/Patches/Linux_CVEs/CVE-2016-4794/0.patch new file mode 100644 index 00000000..92a1bcb5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-4794/0.patch @@ -0,0 +1,107 @@ +From 6710e594f71ccaad8101bc64321152af7cd9ea28 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 25 May 2016 11:48:25 -0400 +Subject: percpu: fix synchronization between synchronous map extension and + chunk destruction + +For non-atomic allocations, pcpu_alloc() can try to extend the area +map synchronously after dropping pcpu_lock; however, the extension +wasn't synchronized against chunk destruction and the chunk might get +freed while extension is in progress. + +This patch fixes the bug by putting most of non-atomic allocations +under pcpu_alloc_mutex to synchronize against pcpu_balance_work which +is responsible for async chunk management including destruction. + +Signed-off-by: Tejun Heo +Reported-and-tested-by: Alexei Starovoitov +Reported-by: Vlastimil Babka +Reported-by: Sasha Levin +Cc: stable@vger.kernel.org # v3.18+ +Fixes: 1a4d76076cda ("percpu: implement asynchronous chunk population") +--- + mm/percpu.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/mm/percpu.c b/mm/percpu.c +index b1d2a38..9903830 100644 +--- a/mm/percpu.c ++++ b/mm/percpu.c +@@ -162,7 +162,7 @@ static struct pcpu_chunk *pcpu_reserved_chunk; + static int pcpu_reserved_chunk_limit; + + static DEFINE_SPINLOCK(pcpu_lock); /* all internal data structures */ +-static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop */ ++static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop, map ext */ + + static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */ + +@@ -444,6 +444,8 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc) + size_t old_size = 0, new_size = new_alloc * sizeof(new[0]); + unsigned long flags; + ++ lockdep_assert_held(&pcpu_alloc_mutex); ++ + new = pcpu_mem_zalloc(new_size); + if (!new) + return -ENOMEM; +@@ -890,6 +892,9 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved, + return NULL; + } + ++ if (!is_atomic) ++ mutex_lock(&pcpu_alloc_mutex); ++ + spin_lock_irqsave(&pcpu_lock, flags); + + /* serve reserved allocations from the reserved chunk if available */ +@@ -962,12 +967,9 @@ restart: + if (is_atomic) + goto fail; + +- mutex_lock(&pcpu_alloc_mutex); +- + if (list_empty(&pcpu_slot[pcpu_nr_slots - 1])) { + chunk = pcpu_create_chunk(); + if (!chunk) { +- mutex_unlock(&pcpu_alloc_mutex); + err = "failed to allocate new chunk"; + goto fail; + } +@@ -978,7 +980,6 @@ restart: + spin_lock_irqsave(&pcpu_lock, flags); + } + +- mutex_unlock(&pcpu_alloc_mutex); + goto restart; + + area_found: +@@ -988,8 +989,6 @@ area_found: + if (!is_atomic) { + int page_start, page_end, rs, re; + +- mutex_lock(&pcpu_alloc_mutex); +- + page_start = PFN_DOWN(off); + page_end = PFN_UP(off + size); + +@@ -1000,7 +999,6 @@ area_found: + + spin_lock_irqsave(&pcpu_lock, flags); + if (ret) { +- mutex_unlock(&pcpu_alloc_mutex); + pcpu_free_area(chunk, off, &occ_pages); + err = "failed to populate"; + goto fail_unlock; +@@ -1040,6 +1038,8 @@ fail: + /* see the flag handling in pcpu_blance_workfn() */ + pcpu_atomic_alloc_failed = true; + pcpu_schedule_balance_work(); ++ } else { ++ mutex_unlock(&pcpu_alloc_mutex); + } + return NULL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-4794/1.patch b/Patches/Linux_CVEs/CVE-2016-4794/1.patch new file mode 100644 index 00000000..6ab2f0a9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-4794/1.patch @@ -0,0 +1,156 @@ +From 4f996e234dad488e5d9ba0858bc1bae12eff82c3 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 25 May 2016 11:48:25 -0400 +Subject: percpu: fix synchronization between chunk->map_extend_work and chunk + destruction + +Atomic allocations can trigger async map extensions which is serviced +by chunk->map_extend_work. pcpu_balance_work which is responsible for +destroying idle chunks wasn't synchronizing properly against +chunk->map_extend_work and may end up freeing the chunk while the work +item is still in flight. + +This patch fixes the bug by rolling async map extension operations +into pcpu_balance_work. + +Signed-off-by: Tejun Heo +Reported-and-tested-by: Alexei Starovoitov +Reported-by: Vlastimil Babka +Reported-by: Sasha Levin +Cc: stable@vger.kernel.org # v3.18+ +Fixes: 9c824b6a172c ("percpu: make sure chunk->map array has available space") +--- + mm/percpu.c | 57 ++++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 36 insertions(+), 21 deletions(-) + +diff --git a/mm/percpu.c b/mm/percpu.c +index 0c59684..b1d2a38 100644 +--- a/mm/percpu.c ++++ b/mm/percpu.c +@@ -112,7 +112,7 @@ struct pcpu_chunk { + int map_used; /* # of map entries used before the sentry */ + int map_alloc; /* # of map entries allocated */ + int *map; /* allocation map */ +- struct work_struct map_extend_work;/* async ->map[] extension */ ++ struct list_head map_extend_list;/* on pcpu_map_extend_chunks */ + + void *data; /* chunk data */ + int first_free; /* no free below this */ +@@ -166,6 +166,9 @@ static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop */ + + static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */ + ++/* chunks which need their map areas extended, protected by pcpu_lock */ ++static LIST_HEAD(pcpu_map_extend_chunks); ++ + /* + * The number of empty populated pages, protected by pcpu_lock. The + * reserved chunk doesn't contribute to the count. +@@ -395,13 +398,19 @@ static int pcpu_need_to_extend(struct pcpu_chunk *chunk, bool is_atomic) + { + int margin, new_alloc; + ++ lockdep_assert_held(&pcpu_lock); ++ + if (is_atomic) { + margin = 3; + + if (chunk->map_alloc < +- chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW && +- pcpu_async_enabled) +- schedule_work(&chunk->map_extend_work); ++ chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW) { ++ if (list_empty(&chunk->map_extend_list)) { ++ list_add_tail(&chunk->map_extend_list, ++ &pcpu_map_extend_chunks); ++ pcpu_schedule_balance_work(); ++ } ++ } + } else { + margin = PCPU_ATOMIC_MAP_MARGIN_HIGH; + } +@@ -467,20 +476,6 @@ out_unlock: + return 0; + } + +-static void pcpu_map_extend_workfn(struct work_struct *work) +-{ +- struct pcpu_chunk *chunk = container_of(work, struct pcpu_chunk, +- map_extend_work); +- int new_alloc; +- +- spin_lock_irq(&pcpu_lock); +- new_alloc = pcpu_need_to_extend(chunk, false); +- spin_unlock_irq(&pcpu_lock); +- +- if (new_alloc) +- pcpu_extend_area_map(chunk, new_alloc); +-} +- + /** + * pcpu_fit_in_area - try to fit the requested allocation in a candidate area + * @chunk: chunk the candidate area belongs to +@@ -740,7 +735,7 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void) + chunk->map_used = 1; + + INIT_LIST_HEAD(&chunk->list); +- INIT_WORK(&chunk->map_extend_work, pcpu_map_extend_workfn); ++ INIT_LIST_HEAD(&chunk->map_extend_list); + chunk->free_size = pcpu_unit_size; + chunk->contig_hint = pcpu_unit_size; + +@@ -1129,6 +1124,7 @@ static void pcpu_balance_workfn(struct work_struct *work) + if (chunk == list_first_entry(free_head, struct pcpu_chunk, list)) + continue; + ++ list_del_init(&chunk->map_extend_list); + list_move(&chunk->list, &to_free); + } + +@@ -1146,6 +1142,25 @@ static void pcpu_balance_workfn(struct work_struct *work) + pcpu_destroy_chunk(chunk); + } + ++ /* service chunks which requested async area map extension */ ++ do { ++ int new_alloc = 0; ++ ++ spin_lock_irq(&pcpu_lock); ++ ++ chunk = list_first_entry_or_null(&pcpu_map_extend_chunks, ++ struct pcpu_chunk, map_extend_list); ++ if (chunk) { ++ list_del_init(&chunk->map_extend_list); ++ new_alloc = pcpu_need_to_extend(chunk, false); ++ } ++ ++ spin_unlock_irq(&pcpu_lock); ++ ++ if (new_alloc) ++ pcpu_extend_area_map(chunk, new_alloc); ++ } while (chunk); ++ + /* + * Ensure there are certain number of free populated pages for + * atomic allocs. Fill up from the most packed so that atomic +@@ -1644,7 +1659,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, + */ + schunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0); + INIT_LIST_HEAD(&schunk->list); +- INIT_WORK(&schunk->map_extend_work, pcpu_map_extend_workfn); ++ INIT_LIST_HEAD(&schunk->map_extend_list); + schunk->base_addr = base_addr; + schunk->map = smap; + schunk->map_alloc = ARRAY_SIZE(smap); +@@ -1673,7 +1688,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, + if (dyn_size) { + dchunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0); + INIT_LIST_HEAD(&dchunk->list); +- INIT_WORK(&dchunk->map_extend_work, pcpu_map_extend_workfn); ++ INIT_LIST_HEAD(&dchunk->map_extend_list); + dchunk->base_addr = base_addr; + dchunk->map = dmap; + dchunk->map_alloc = ARRAY_SIZE(dmap); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-4805/0.patch b/Patches/Linux_CVEs/CVE-2016-4805/0.patch new file mode 100644 index 00000000..21930a35 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-4805/0.patch @@ -0,0 +1,149 @@ +From 1f461dcdd296eecedaffffc6bae2bfa90bd7eb89 Mon Sep 17 00:00:00 2001 +From: Guillaume Nault +Date: Wed, 23 Mar 2016 16:38:55 +0100 +Subject: ppp: take reference on channels netns + +Let channels hold a reference on their network namespace. +Some channel types, like ppp_async and ppp_synctty, can have their +userspace controller running in a different namespace. Therefore they +can't rely on them to preclude their netns from being removed from +under them. + +================================================================== +BUG: KASAN: use-after-free in ppp_unregister_channel+0x372/0x3a0 at +addr ffff880064e217e0 +Read of size 8 by task syz-executor/11581 +============================================================================= +BUG net_namespace (Not tainted): kasan: bad access detected +----------------------------------------------------------------------------- + +Disabling lock debugging due to kernel taint +INFO: Allocated in copy_net_ns+0x6b/0x1a0 age=92569 cpu=3 pid=6906 +[< none >] ___slab_alloc+0x4c7/0x500 kernel/mm/slub.c:2440 +[< none >] __slab_alloc+0x4c/0x90 kernel/mm/slub.c:2469 +[< inline >] slab_alloc_node kernel/mm/slub.c:2532 +[< inline >] slab_alloc kernel/mm/slub.c:2574 +[< none >] kmem_cache_alloc+0x23a/0x2b0 kernel/mm/slub.c:2579 +[< inline >] kmem_cache_zalloc kernel/include/linux/slab.h:597 +[< inline >] net_alloc kernel/net/core/net_namespace.c:325 +[< none >] copy_net_ns+0x6b/0x1a0 kernel/net/core/net_namespace.c:360 +[< none >] create_new_namespaces+0x2f6/0x610 kernel/kernel/nsproxy.c:95 +[< none >] copy_namespaces+0x297/0x320 kernel/kernel/nsproxy.c:150 +[< none >] copy_process.part.35+0x1bf4/0x5760 kernel/kernel/fork.c:1451 +[< inline >] copy_process kernel/kernel/fork.c:1274 +[< none >] _do_fork+0x1bc/0xcb0 kernel/kernel/fork.c:1723 +[< inline >] SYSC_clone kernel/kernel/fork.c:1832 +[< none >] SyS_clone+0x37/0x50 kernel/kernel/fork.c:1826 +[< none >] entry_SYSCALL_64_fastpath+0x16/0x7a kernel/arch/x86/entry/entry_64.S:185 + +INFO: Freed in net_drop_ns+0x67/0x80 age=575 cpu=2 pid=2631 +[< none >] __slab_free+0x1fc/0x320 kernel/mm/slub.c:2650 +[< inline >] slab_free kernel/mm/slub.c:2805 +[< none >] kmem_cache_free+0x2a0/0x330 kernel/mm/slub.c:2814 +[< inline >] net_free kernel/net/core/net_namespace.c:341 +[< none >] net_drop_ns+0x67/0x80 kernel/net/core/net_namespace.c:348 +[< none >] cleanup_net+0x4e5/0x600 kernel/net/core/net_namespace.c:448 +[< none >] process_one_work+0x794/0x1440 kernel/kernel/workqueue.c:2036 +[< none >] worker_thread+0xdb/0xfc0 kernel/kernel/workqueue.c:2170 +[< none >] kthread+0x23f/0x2d0 kernel/drivers/block/aoe/aoecmd.c:1303 +[< none >] ret_from_fork+0x3f/0x70 kernel/arch/x86/entry/entry_64.S:468 +INFO: Slab 0xffffea0001938800 objects=3 used=0 fp=0xffff880064e20000 +flags=0x5fffc0000004080 +INFO: Object 0xffff880064e20000 @offset=0 fp=0xffff880064e24200 + +CPU: 1 PID: 11581 Comm: syz-executor Tainted: G B 4.4.0+ +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 + 00000000ffffffff ffff8800662c7790 ffffffff8292049d ffff88003e36a300 + ffff880064e20000 ffff880064e20000 ffff8800662c77c0 ffffffff816f2054 + ffff88003e36a300 ffffea0001938800 ffff880064e20000 0000000000000000 +Call Trace: + [< inline >] __dump_stack kernel/lib/dump_stack.c:15 + [] dump_stack+0x6f/0xa2 kernel/lib/dump_stack.c:50 + [] print_trailer+0xf4/0x150 kernel/mm/slub.c:654 + [] object_err+0x2f/0x40 kernel/mm/slub.c:661 + [< inline >] print_address_description kernel/mm/kasan/report.c:138 + [] kasan_report_error+0x215/0x530 kernel/mm/kasan/report.c:236 + [< inline >] kasan_report kernel/mm/kasan/report.c:259 + [] __asan_report_load8_noabort+0x3e/0x40 kernel/mm/kasan/report.c:280 + [< inline >] ? ppp_pernet kernel/include/linux/compiler.h:218 + [] ? ppp_unregister_channel+0x372/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392 + [< inline >] ppp_pernet kernel/include/linux/compiler.h:218 + [] ppp_unregister_channel+0x372/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392 + [< inline >] ? ppp_pernet kernel/drivers/net/ppp/ppp_generic.c:293 + [] ? ppp_unregister_channel+0xe6/0x3a0 kernel/drivers/net/ppp/ppp_generic.c:2392 + [] ppp_asynctty_close+0xa3/0x130 kernel/drivers/net/ppp/ppp_async.c:241 + [] ? async_lcp_peek+0x5b0/0x5b0 kernel/drivers/net/ppp/ppp_async.c:1000 + [] tty_ldisc_close.isra.1+0x99/0xe0 kernel/drivers/tty/tty_ldisc.c:478 + [] tty_ldisc_kill+0x40/0x170 kernel/drivers/tty/tty_ldisc.c:744 + [] tty_ldisc_release+0x1b3/0x260 kernel/drivers/tty/tty_ldisc.c:772 + [] tty_release+0xac1/0x13e0 kernel/drivers/tty/tty_io.c:1901 + [] ? release_tty+0x320/0x320 kernel/drivers/tty/tty_io.c:1688 + [] __fput+0x236/0x780 kernel/fs/file_table.c:208 + [] ____fput+0x15/0x20 kernel/fs/file_table.c:244 + [] task_work_run+0x16b/0x200 kernel/kernel/task_work.c:115 + [< inline >] exit_task_work kernel/include/linux/task_work.h:21 + [] do_exit+0x8b5/0x2c60 kernel/kernel/exit.c:750 + [] ? debug_check_no_locks_freed+0x290/0x290 kernel/kernel/locking/lockdep.c:4123 + [] ? mm_update_next_owner+0x6f0/0x6f0 kernel/kernel/exit.c:357 + [] ? __dequeue_signal+0x136/0x470 kernel/kernel/signal.c:550 + [] ? recalc_sigpending_tsk+0x13b/0x180 kernel/kernel/signal.c:145 + [] do_group_exit+0x108/0x330 kernel/kernel/exit.c:880 + [] get_signal+0x5e4/0x14f0 kernel/kernel/signal.c:2307 + [< inline >] ? kretprobe_table_lock kernel/kernel/kprobes.c:1113 + [] ? kprobe_flush_task+0xb5/0x450 kernel/kernel/kprobes.c:1158 + [] do_signal+0x83/0x1c90 kernel/arch/x86/kernel/signal.c:712 + [] ? recycle_rp_inst+0x310/0x310 kernel/include/linux/list.h:655 + [] ? setup_sigcontext+0x780/0x780 kernel/arch/x86/kernel/signal.c:165 + [] ? finish_task_switch+0x424/0x5f0 kernel/kernel/sched/core.c:2692 + [< inline >] ? finish_lock_switch kernel/kernel/sched/sched.h:1099 + [] ? finish_task_switch+0x120/0x5f0 kernel/kernel/sched/core.c:2678 + [< inline >] ? context_switch kernel/kernel/sched/core.c:2807 + [] ? __schedule+0x919/0x1bd0 kernel/kernel/sched/core.c:3283 + [] exit_to_usermode_loop+0xf1/0x1a0 kernel/arch/x86/entry/common.c:247 + [< inline >] prepare_exit_to_usermode kernel/arch/x86/entry/common.c:282 + [] syscall_return_slowpath+0x19f/0x210 kernel/arch/x86/entry/common.c:344 + [] int_ret_from_sys_call+0x25/0x9f kernel/arch/x86/entry/entry_64.S:281 +Memory state around the buggy address: + ffff880064e21680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff880064e21700: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +>ffff880064e21780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff880064e21800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff880064e21880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +================================================================== + +Fixes: 273ec51dd7ce ("net: ppp_generic - introduce net-namespace functionality v2") +Reported-by: Baozeng Ding +Signed-off-by: Guillaume Nault +Reviewed-by: Cyrill Gorcunov +Signed-off-by: David S. Miller +--- + drivers/net/ppp/ppp_generic.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 4fd8610..f572b31 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2307,7 +2307,7 @@ int ppp_register_net_channel(struct net *net, struct ppp_channel *chan) + + pch->ppp = NULL; + pch->chan = chan; +- pch->chan_net = net; ++ pch->chan_net = get_net(net); + chan->ppp = pch; + init_ppp_file(&pch->file, CHANNEL); + pch->file.hdrlen = chan->hdrlen; +@@ -2404,6 +2404,8 @@ ppp_unregister_channel(struct ppp_channel *chan) + spin_lock_bh(&pn->all_channels_lock); + list_del(&pch->list); + spin_unlock_bh(&pn->all_channels_lock); ++ put_net(pch->chan_net); ++ pch->chan_net = NULL; + + pch->file.dead = 1; + wake_up_interruptible(&pch->file.rwait); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-4805/1.patch b/Patches/Linux_CVEs/CVE-2016-4805/1.patch new file mode 100644 index 00000000..981bf9af --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-4805/1.patch @@ -0,0 +1,55 @@ +From 205e1e255c479f3fd77446415706463b282f94e4 Mon Sep 17 00:00:00 2001 +From: WANG Cong +Date: Tue, 5 Jul 2016 22:12:36 -0700 +Subject: ppp: defer netns reference release for ppp channel + +Matt reported that we have a NULL pointer dereference +in ppp_pernet() from ppp_connect_channel(), +i.e. pch->chan_net is NULL. + +This is due to that a parallel ppp_unregister_channel() +could happen while we are in ppp_connect_channel(), during +which pch->chan_net set to NULL. Since we need a reference +to net per channel, it makes sense to sync the refcnt +with the life time of the channel, therefore we should +release this reference when we destroy it. + +Fixes: 1f461dcdd296 ("ppp: take reference on channels netns") +Reported-by: Matt Bennett +Cc: Paul Mackerras +Cc: linux-ppp@vger.kernel.org +Cc: Guillaume Nault +Cc: Cyrill Gorcunov +Signed-off-by: Cong Wang +Reviewed-by: Cyrill Gorcunov +Signed-off-by: David S. Miller +--- + drivers/net/ppp/ppp_generic.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 8dedafa..a30ee42 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2601,8 +2601,6 @@ ppp_unregister_channel(struct ppp_channel *chan) + spin_lock_bh(&pn->all_channels_lock); + list_del(&pch->list); + spin_unlock_bh(&pn->all_channels_lock); +- put_net(pch->chan_net); +- pch->chan_net = NULL; + + pch->file.dead = 1; + wake_up_interruptible(&pch->file.rwait); +@@ -3136,6 +3134,9 @@ ppp_disconnect_channel(struct channel *pch) + */ + static void ppp_destroy_channel(struct channel *pch) + { ++ put_net(pch->chan_net); ++ pch->chan_net = NULL; ++ + atomic_dec(&channel_count); + + if (!pch->file.dead) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-4998/0.patch b/Patches/Linux_CVEs/CVE-2016-4998/0.patch new file mode 100644 index 00000000..8b21bbdb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-4998/0.patch @@ -0,0 +1,91 @@ +From 6e94e0cfb0887e4013b3b930fa6ab1fe6bb6ba91 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Tue, 22 Mar 2016 18:02:50 +0100 +Subject: netfilter: x_tables: make sure e->next_offset covers remaining blob + size + +Otherwise this function may read data beyond the ruleset blob. + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +--- + net/ipv4/netfilter/arp_tables.c | 6 ++++-- + net/ipv4/netfilter/ip_tables.c | 6 ++++-- + net/ipv6/netfilter/ip6_tables.c | 6 ++++-- + 3 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c +index 830bbe8..51d4fe5 100644 +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -573,7 +573,8 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, + int err; + + if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 || +- (unsigned char *)e + sizeof(struct arpt_entry) >= limit) { ++ (unsigned char *)e + sizeof(struct arpt_entry) >= limit || ++ (unsigned char *)e + e->next_offset > limit) { + duprintf("Bad offset %p\n", e); + return -EINVAL; + } +@@ -1232,7 +1233,8 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, + + duprintf("check_compat_entry_size_and_hooks %p\n", e); + if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 || +- (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit) { ++ (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit || ++ (unsigned char *)e + e->next_offset > limit) { + duprintf("Bad offset %p, limit = %p\n", e, limit); + return -EINVAL; + } +diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c +index 1d72a3c..fb7694e6 100644 +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -738,7 +738,8 @@ check_entry_size_and_hooks(struct ipt_entry *e, + int err; + + if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 || +- (unsigned char *)e + sizeof(struct ipt_entry) >= limit) { ++ (unsigned char *)e + sizeof(struct ipt_entry) >= limit || ++ (unsigned char *)e + e->next_offset > limit) { + duprintf("Bad offset %p\n", e); + return -EINVAL; + } +@@ -1492,7 +1493,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, + + duprintf("check_compat_entry_size_and_hooks %p\n", e); + if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 || +- (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) { ++ (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit || ++ (unsigned char *)e + e->next_offset > limit) { + duprintf("Bad offset %p, limit = %p\n", e, limit); + return -EINVAL; + } +diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c +index 26a5ad1..b248528f 100644 +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -750,7 +750,8 @@ check_entry_size_and_hooks(struct ip6t_entry *e, + int err; + + if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 || +- (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) { ++ (unsigned char *)e + sizeof(struct ip6t_entry) >= limit || ++ (unsigned char *)e + e->next_offset > limit) { + duprintf("Bad offset %p\n", e); + return -EINVAL; + } +@@ -1504,7 +1505,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, + + duprintf("check_compat_entry_size_and_hooks %p\n", e); + if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 || +- (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) { ++ (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit || ++ (unsigned char *)e + e->next_offset > limit) { + duprintf("Bad offset %p, limit = %p\n", e, limit); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5195/0.patch b/Patches/Linux_CVEs/CVE-2016-5195/0.patch new file mode 100644 index 00000000..cce6b2c1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5195/0.patch @@ -0,0 +1,148 @@ +From 1c8544a93151329be95f702f6f4029f860b77ee7 Mon Sep 17 00:00:00 2001 +From: Michal Hocko +Date: Sun, 16 Oct 2016 11:55:00 +0200 +Subject: mm, gup: close FOLL MAP_PRIVATE race + +commit 19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619 upstream. + +faultin_page drops FOLL_WRITE after the page fault handler did the CoW +and then we retry follow_page_mask to get our CoWed page. This is racy, +however because the page might have been unmapped by that time and so +we would have to do a page fault again, this time without CoW. This +would cause the page cache corruption for FOLL_FORCE on MAP_PRIVATE +read only mappings with obvious consequences. + +This is an ancient bug that was actually already fixed once by Linus +eleven years ago in commit 4ceb5db9757a ("Fix get_user_pages() race +for write access") but that was then undone due to problems on s390 +by commit f33ea7f404e5 ("fix get_user_pages bug") because s390 didn't +have proper dirty pte tracking until abf09bed3cce ("s390/mm: implement +software dirty bits"). This wasn't a problem at the time as pointed out +by Hugh Dickins because madvise relied on mmap_sem for write up until +0a27a14a6292 ("mm: madvise avoid exclusive mmap_sem") but since then we +can race with madvise which can unmap the fresh COWed page or with KSM +and corrupt the content of the shared page. + +This patch is based on the Linus' approach to not clear FOLL_WRITE after +the CoW page fault (aka VM_FAULT_WRITE) but instead introduces FOLL_COW +to note this fact. The flag is then rechecked during follow_pfn_pte to +enforce the page fault again if we do not see the CoWed page. Linus was +suggesting to check pte_dirty again as s390 is OK now. But that would +make backporting to some old kernels harder. So instead let's just make +sure that vm_normal_page sees a pure anonymous page. + +This would guarantee we are seeing a real CoW page. Introduce +can_follow_write_pte which checks both pte_write and falls back to +PageAnon on forced write faults which passed CoW already. Thanks to Hugh +to point out that a special care has to be taken for KSM pages because +our COWed page might have been merged with a KSM one and keep its +PageAnon flag. + +Fixes: 0a27a14a6292 ("mm: madvise avoid exclusive mmap_sem") +Reported-by: Phil "not Paul" Oester +Disclosed-by: Andy Lutomirski +Signed-off-by: Linus Torvalds +Signed-off-by: Michal Hocko +[bwh: Backported to 3.2: + - Adjust filename, context, indentation + - The 'no_page' exit path in follow_page() is different, so open-code the + cleanup + - Delete a now-unused label] +Signed-off-by: Ben Hutchings +Signed-off-by: Zefan Li +--- + include/linux/mm.h | 1 + + mm/memory.c | 39 ++++++++++++++++++++++++++++----------- + 2 files changed, 29 insertions(+), 11 deletions(-) + +diff --git a/include/linux/mm.h b/include/linux/mm.h +index ceebf63..ef706ab 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1525,6 +1525,7 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address, + #define FOLL_MLOCK 0x40 /* mark page as mlocked */ + #define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */ + #define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */ ++#define FOLL_COW 0x4000 /* internal GUP flag */ + + typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, + void *data); +diff --git a/mm/memory.c b/mm/memory.c +index 4774579..9701911 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1447,6 +1447,24 @@ int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address, + } + EXPORT_SYMBOL_GPL(zap_vma_ptes); + ++static inline bool can_follow_write_pte(pte_t pte, struct page *page, ++ unsigned int flags) ++{ ++ if (pte_write(pte)) ++ return true; ++ ++ /* ++ * Make sure that we are really following CoWed page. We do not really ++ * have to care about exclusiveness of the page because we only want ++ * to ensure that once COWed page hasn't disappeared in the meantime ++ * or it hasn't been merged to a KSM page. ++ */ ++ if ((flags & FOLL_FORCE) && (flags & FOLL_COW)) ++ return page && PageAnon(page) && !PageKsm(page); ++ ++ return false; ++} ++ + /** + * follow_page - look up a page descriptor from a user-virtual address + * @vma: vm_area_struct mapping @address +@@ -1529,10 +1547,13 @@ split_fallthrough: + pte = *ptep; + if (!pte_present(pte)) + goto no_page; +- if ((flags & FOLL_WRITE) && !pte_write(pte)) +- goto unlock; + + page = vm_normal_page(vma, address, pte); ++ if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, page, flags)) { ++ pte_unmap_unlock(ptep, ptl); ++ return NULL; ++ } ++ + if (unlikely(!page)) { + if ((flags & FOLL_DUMP) || + !is_zero_pfn(pte_pfn(pte))) +@@ -1575,7 +1596,7 @@ split_fallthrough: + unlock_page(page); + } + } +-unlock: ++ + pte_unmap_unlock(ptep, ptl); + out: + return page; +@@ -1809,17 +1830,13 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, + * The VM_FAULT_WRITE bit tells us that + * do_wp_page has broken COW when necessary, + * even if maybe_mkwrite decided not to set +- * pte_write. We can thus safely do subsequent +- * page lookups as if they were reads. But only +- * do so when looping for pte_write is futile: +- * in some cases userspace may also be wanting +- * to write to the gotten user page, which a +- * read fault here might prevent (a readonly +- * page might get reCOWed by userspace write). ++ * pte_write. We cannot simply drop FOLL_WRITE ++ * here because the COWed page might be gone by ++ * the time we do the subsequent page lookups. + */ + if ((ret & VM_FAULT_WRITE) && + !(vma->vm_flags & VM_WRITE)) +- foll_flags &= ~FOLL_WRITE; ++ foll_flags |= FOLL_COW; + + cond_resched(); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5195/1.patch b/Patches/Linux_CVEs/CVE-2016-5195/1.patch new file mode 100644 index 00000000..c8ae9d00 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5195/1.patch @@ -0,0 +1,101 @@ +From c33d1bdff9c4c24e73e7c7f48ce8f8c1819a233f Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Thu, 20 Oct 2016 14:11:10 -0700 +Subject: [PATCH] UPSTREAM: mm: remove gup_flags FOLL_WRITE games from + __get_user_pages() + +(cherry-picked from 9691eac5593ff1e2f82391ad327f21d90322aec1) + +commit 19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619 upstream. + +This is an ancient bug that was actually attempted to be fixed once +(badly) by me eleven years ago in commit 4ceb5db9757a ("Fix +get_user_pages() race for write access") but that was then undone due to +problems on s390 by commit f33ea7f404e5 ("fix get_user_pages bug"). + +In the meantime, the s390 situation has long been fixed, and we can now +fix it by checking the pte_dirty() bit properly (and do it better). The +s390 dirty bit was implemented in abf09bed3cce ("s390/mm: implement +software dirty bits") which made it into v3.9. Earlier kernels will +have to look at the page state itself. + +Also, the VM has become more scalable, and what used a purely +theoretical race back then has become easier to trigger. + +To fix it, we introduce a new internal FOLL_COW flag to mark the "yes, +we already did a COW" rather than play racy games with FOLL_WRITE that +is very fundamental, and then use the pte dirty flag to validate that +the FOLL_COW flag is still valid. + +Reported-and-tested-by: Phil "not Paul" Oester +Acked-by: Hugh Dickins +Reviewed-by: Michal Hocko +Cc: Andy Lutomirski +Cc: Kees Cook +Cc: Oleg Nesterov +Cc: Willy Tarreau +Cc: Nick Piggin +Cc: Greg Thelen +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +[wt: s/gup.c/memory.c; s/follow_page_pte/follow_page_mask; + s/faultin_page/__get_user_page] +Signed-off-by: Willy Tarreau +Change-Id: I42e448ecacad4781b460c4c989026307169ba1b5 +Bug: 32141528 +--- + include/linux/mm.h | 1 + + mm/memory.c | 14 ++++++++++++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/include/linux/mm.h b/include/linux/mm.h +index b582c9d07fcd5..54567b0c41d63 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1752,6 +1752,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma, + #define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */ + #define FOLL_NUMA 0x200 /* force NUMA hinting page fault */ + #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ ++#define FOLL_COW 0x4000 /* internal GUP flag */ + + typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, + void *data); +diff --git a/mm/memory.c b/mm/memory.c +index ac61bc57e3ef4..fd453654d3008 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1467,6 +1467,16 @@ int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address, + } + EXPORT_SYMBOL_GPL(zap_vma_ptes); + ++/* ++ * FOLL_FORCE can write to even unwritable pte's, but only ++ * after we've gone through a COW cycle and they are dirty. ++ */ ++static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) ++{ ++ return pte_write(pte) || ++ ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); ++} ++ + /** + * follow_page_mask - look up a page descriptor from a user-virtual address + * @vma: vm_area_struct mapping @address +@@ -1574,7 +1584,7 @@ struct page *follow_page_mask(struct vm_area_struct *vma, + } + if ((flags & FOLL_NUMA) && pte_numa(pte)) + goto no_page; +- if ((flags & FOLL_WRITE) && !pte_write(pte)) ++ if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) + goto unlock; + + page = vm_normal_page(vma, address, pte); +@@ -1894,7 +1904,7 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, + */ + if ((ret & VM_FAULT_WRITE) && + !(vma->vm_flags & VM_WRITE)) +- foll_flags &= ~FOLL_WRITE; ++ foll_flags |= FOLL_COW; + + cond_resched(); + } diff --git a/Patches/Linux_CVEs/CVE-2016-5195/2.patch b/Patches/Linux_CVEs/CVE-2016-5195/2.patch new file mode 100644 index 00000000..3cd4fded --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5195/2.patch @@ -0,0 +1,101 @@ +From 47f4f5225f27dc8b495ef2f946edd405630245ca Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Thu, 13 Oct 2016 13:07:36 -0700 +Subject: [PATCH] CHROMIUM: UPSTREAM: mm: remove gup_flags FOLL_WRITE games + from __get_user_pages() + +This is an ancient bug that was actually attempted to be fixed once +(badly) by me eleven years ago in commit 4ceb5db9757a ("Fix +get_user_pages() race for write access") but that was then undone due to +problems on s390 by commit f33ea7f404e5 ("fix get_user_pages bug"). + +In the meantime, the s390 situation has long been fixed, and we can now +fix it by checking the pte_dirty() bit properly (and do it better). The +s390 dirty bit was implemented in abf09bed3cce ("s390/mm: implement +software dirty bits") which made it into v3.9. Earlier kernels will +have to look at the page state itself. + +Also, the VM has become more scalable, and what used a purely +theoretical race back then has become easier to trigger. + +To fix it, we introduce a new internal FOLL_COW flag to mark the "yes, +we already did a COW" rather than play racy games with FOLL_WRITE that +is very fundamental, and then use the pte dirty flag to validate that +the FOLL_COW flag is still valid. + +BUG=chromium:657609 +TEST=None + +Change-Id: I42e448ecacad4781b460c4c989026307169ba1b5 +Reported-and-tested-by: Phil "not Paul" Oester +Acked-by: Hugh Dickins +Reviewed-by: Michal Hocko +Cc: Andy Lutomirski +Cc: Kees Cook +Cc: Oleg Nesterov +Cc: Willy Tarreau +Cc: Nick Piggin +Cc: Greg Thelen +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +(cherry picked from commit 19be0eaffa3ac7d8eb6784ad9bdbc7d67ed8e619) +Signed-off-by: Andrey Ulanov +Reviewed-on: https://chromium-review.googlesource.com/401142 +Reviewed-by: Guenter Roeck +Bug: 32141528 +--- + include/linux/mm.h | 1 + + mm/gup.c | 14 ++++++++++++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 4f0afdd748180..f410ba03afd93 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -2050,6 +2050,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma, + #define FOLL_NUMA 0x200 /* force NUMA hinting page fault */ + #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ + #define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */ ++#define FOLL_COW 0x4000 /* internal GUP flag */ + + typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, + void *data); +diff --git a/mm/gup.c b/mm/gup.c +index 377a5a796242e..bef4bb0f79625 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -32,6 +32,16 @@ static struct page *no_page_table(struct vm_area_struct *vma, + return NULL; + } + ++/* ++ * FOLL_FORCE can write to even unwritable pte's, but only ++ * after we've gone through a COW cycle and they are dirty. ++ */ ++static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) ++{ ++ return pte_write(pte) || ++ ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); ++} ++ + static struct page *follow_page_pte(struct vm_area_struct *vma, + unsigned long address, pmd_t *pmd, unsigned int flags) + { +@@ -66,7 +76,7 @@ static struct page *follow_page_pte(struct vm_area_struct *vma, + } + if ((flags & FOLL_NUMA) && pte_numa(pte)) + goto no_page; +- if ((flags & FOLL_WRITE) && !pte_write(pte)) { ++ if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) { + pte_unmap_unlock(ptep, ptl); + return NULL; + } +@@ -315,7 +325,7 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, + * reCOWed by userspace write). + */ + if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE)) +- *flags &= ~FOLL_WRITE; ++ *flags |= FOLL_COW; + return 0; + } + diff --git a/Patches/Linux_CVEs/CVE-2016-5340/0.patch b/Patches/Linux_CVEs/CVE-2016-5340/0.patch new file mode 100644 index 00000000..a2e3ed84 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5340/0.patch @@ -0,0 +1,82 @@ +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/Linux_CVEs/CVE-2016-5342/0.patch b/Patches/Linux_CVEs/CVE-2016-5342/0.patch new file mode 100644 index 00000000..fe78befc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5342/0.patch @@ -0,0 +1,32 @@ +From 579e796cb089324c55e0e689a180575ba81b23d9 Mon Sep 17 00:00:00 2001 +From: Anand Kumar +Date: Tue, 21 Jun 2016 17:36:05 +0530 +Subject: wcnss: Avoid user buffer overloading for write cal data + +compare size of allocated cal data buffer from heap +and count bytes provided to write by user to avoid +heap overflow for write cal data. + +Change-Id: Id70c3230f761385489e5e94c613f4519239dfb1f +CRs-Fixed: 1032174 +Signed-off-by: Anand Kumar +--- + drivers/net/wireless/wcnss/wcnss_wlan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c +index 86f3a48..3f9eeab 100644 +--- a/drivers/net/wireless/wcnss/wcnss_wlan.c ++++ b/drivers/net/wireless/wcnss/wcnss_wlan.c +@@ -3339,7 +3339,7 @@ static ssize_t wcnss_wlan_write(struct file *fp, const char __user + return -EFAULT; + + if ((UINT32_MAX - count < penv->user_cal_rcvd) || +- MAX_CALIBRATED_DATA_SIZE < count + penv->user_cal_rcvd) { ++ (penv->user_cal_exp_size < count + penv->user_cal_rcvd)) { + pr_err(DEVICE " invalid size to write %zu\n", count + + penv->user_cal_rcvd); + rc = -ENOMEM; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5343/0.patch b/Patches/Linux_CVEs/CVE-2016-5343/0.patch new file mode 100644 index 00000000..9dfae3b9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5343/0.patch @@ -0,0 +1,100 @@ +From 4b60975d224bf12fc20ccbe76bfedb411c4e833d Mon Sep 17 00:00:00 2001 +From: Josh Kirsch +Date: Mon, 2 May 2016 14:55:04 -0700 +Subject: [PATCH] drivers: soc: Add buffer overflow check for svc send request + +Add buffer overflow check in voice_svc_send_req. + +CRs-fixed: 1010081 + +Bug: 31796345 +Change-Id: Ice173a9f553022251bd58b0ac03c6fef2f4e0b40 +Signed-off-by: Josh Kirsch +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 46 +++++++++++++++++++++++++----------- + 1 file changed, 32 insertions(+), 14 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index 23b8292c8db5b..67c58d1e6d4cd 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The 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 +@@ -188,7 +188,8 @@ static int voice_svc_send_req(struct voice_svc_cmd_request *apr_request, + int ret = 0; + void *apr_handle = NULL; + struct apr_data *aprdata = NULL; +- uint32_t user_payload_size = 0; ++ uint32_t user_payload_size; ++ uint32_t payload_size; + + pr_debug("%s\n", __func__); + +@@ -200,15 +201,19 @@ static int voice_svc_send_req(struct voice_svc_cmd_request *apr_request, + } + + user_payload_size = apr_request->payload_size; ++ payload_size = sizeof(struct apr_data) + user_payload_size; + +- aprdata = kmalloc(sizeof(struct apr_data) + user_payload_size, +- GFP_KERNEL); +- +- if (aprdata == NULL) { +- pr_err("%s: aprdata kmalloc failed.\n", __func__); +- +- ret = -ENOMEM; ++ if (payload_size <= user_payload_size) { ++ pr_err("%s: invalid payload size ( 0x%x ).\n", ++ __func__, user_payload_size); ++ ret = -EINVAL; + goto done; ++ } else { ++ aprdata = kmalloc(payload_size, GFP_KERNEL); ++ if (aprdata == NULL) { ++ ret = -ENOMEM; ++ goto done; ++ } + } + + voice_svc_update_hdr(apr_request, aprdata); +@@ -388,18 +393,31 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + + switch (cmd) { + case MSG_REGISTER: +- ret = process_reg_cmd( ++ if (count >= ++ (sizeof(struct voice_svc_register) + ++ sizeof(*data))) { ++ ret = process_reg_cmd( + (struct voice_svc_register *)data->payload, prtd); +- if (!ret) +- ret = count; +- ++ if (!ret) ++ ret = count; ++ } else { ++ pr_err("%s: invalid payload size\n", __func__); ++ ret = -EINVAL; ++ goto done; ++ } + break; + case MSG_REQUEST: ++ if (count >= (sizeof(struct voice_svc_cmd_request) + ++ sizeof(*data))) { + ret = voice_svc_send_req( + (struct voice_svc_cmd_request *)data->payload, prtd); + if (!ret) + ret = count; +- ++ } else { ++ pr_err("%s: invalid payload size\n", __func__); ++ ret = -EINVAL; ++ goto done; ++ } + break; + default: + pr_debug("%s: Invalid command: %u\n", __func__, cmd); diff --git a/Patches/Linux_CVEs/CVE-2016-5345/0.patch b/Patches/Linux_CVEs/CVE-2016-5345/0.patch new file mode 100644 index 00000000..af62b131 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5345/0.patch @@ -0,0 +1,55 @@ +From 67118716a2933f6f30a25ea7e3946569a8b191c6 Mon Sep 17 00:00:00 2001 +From: Kamal Negi +Date: Wed, 19 Oct 2016 18:59:11 +0530 +Subject: radio-iris: check argument values before copying the data + +Check arguments passed in an ioctl before copying the data to kernel +buffers. If user sends an erroneous data, data length more than expected, +will lead to buffer overflow. + +Change-Id: I663e937806f38dc3b04c8d7662cd8b045facd12b +Signed-off-by: Kamal Negi +--- + drivers/media/radio/radio-iris.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c +index b3088eb..bd4eb92 100644 +--- a/drivers/media/radio/radio-iris.c ++++ b/drivers/media/radio/radio-iris.c +@@ -3884,8 +3884,20 @@ static int iris_vidioc_s_ext_ctrls(struct file *file, void *priv, + bytes_to_copy = (ctrl->controls[0]).size; + spur_tbl_req.mode = data[0]; + spur_tbl_req.no_of_freqs_entries = data[1]; +- spur_data = kmalloc((data[1] * SPUR_DATA_LEN) + 2, +- GFP_ATOMIC); ++ ++ if (((spur_tbl_req.no_of_freqs_entries * SPUR_DATA_LEN) != ++ bytes_to_copy - 2) || ++ ((spur_tbl_req.no_of_freqs_entries * SPUR_DATA_LEN) > ++ 2 * FM_SPUR_TBL_SIZE)) { ++ FMDERR("Invalid data len: data[1] = %d, bytes = %zu", ++ spur_tbl_req.no_of_freqs_entries, ++ bytes_to_copy); ++ retval = -EINVAL; ++ goto END; ++ } ++ spur_data = ++ kmalloc((spur_tbl_req.no_of_freqs_entries * SPUR_DATA_LEN) ++ + 2, GFP_ATOMIC); + if (!spur_data) { + FMDERR("Allocation failed for Spur data"); + retval = -EFAULT; +@@ -3900,7 +3912,8 @@ static int iris_vidioc_s_ext_ctrls(struct file *file, void *priv, + + if (spur_tbl_req.no_of_freqs_entries <= ENTRIES_EACH_CMD) { + memcpy(&spur_tbl_req.spur_data[0], spur_data, +- (data[1] * SPUR_DATA_LEN)); ++ (spur_tbl_req.no_of_freqs_entries * ++ SPUR_DATA_LEN)); + retval = radio_hci_request(radio->fm_hdev, + hci_fm_set_spur_tbl_req, + (unsigned long)&spur_tbl_req, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5346/0.patch b/Patches/Linux_CVEs/CVE-2016-5346/0.patch new file mode 100644 index 00000000..2b5b444e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5346/0.patch @@ -0,0 +1,48 @@ +From 6298a474322fb2182f795a622b2faa64abfd8474 Mon Sep 17 00:00:00 2001 +From: Xiaoyu Ye +Date: Wed, 7 Dec 2016 16:35:07 -0800 +Subject: drivers: soc: qcom: Add error handling in function avtimer_ioctl + +Error handling is added to prevent garbage value being passed to +user space by the uninitialized local variable avtimer_tick. + +CRs-Fixed: 1097878 +Change-Id: I3f895deaae3acf329088cf8135859cc41e781763 +Signed-off-by: Xiaoyu Ye +--- + drivers/platform/msm/avtimer.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/msm/avtimer.c b/drivers/platform/msm/avtimer.c +index 2bded5e..4331af8 100644 +--- a/drivers/platform/msm/avtimer.c ++++ b/drivers/platform/msm/avtimer.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -331,9 +331,17 @@ static long avtimer_ioctl(struct file *file, unsigned int ioctl_num, + switch (ioctl_num) { + case IOCTL_GET_AVTIMER_TICK: + { +- uint64_t avtimer_tick; ++ uint64_t avtimer_tick = 0; ++ int rc; ++ ++ rc = avcs_core_query_timer(&avtimer_tick); ++ ++ if (rc) { ++ pr_err("%s: Error: Invalid AV Timer tick, rc = %d\n", ++ __func__, rc); ++ return rc; ++ } + +- avcs_core_query_timer(&avtimer_tick); + pr_debug_ratelimited("%s: AV Timer tick: time %llx\n", + __func__, avtimer_tick); + if (copy_to_user((void *) ioctl_param, &avtimer_tick, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5347/0.patch b/Patches/Linux_CVEs/CVE-2016-5347/0.patch new file mode 100644 index 00000000..0d77e275 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5347/0.patch @@ -0,0 +1,31 @@ +From ae6485b9656470e9a64d5320cb8efd5820ddec8d Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Fri, 16 Dec 2016 16:25:27 +0800 +Subject: ASoC: soc: msm: initialize buffer to prevent kernel data leakage + +To prevent potential kernel stack data leakage, initialize +channel_map[]. + +CRs-Fixed: 1100878 +Change-Id: I7b81cea20485bc7514551672bb54c7fd455049e3 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/qdsp6v2/msm-qti-pp-config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +index 1eeb577..94d6cf7 100644 +--- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +@@ -484,7 +484,7 @@ static int msm_qti_pp_set_auxpcm_lb_vol_mixer(struct snd_kcontrol *kcontrol, + static int msm_qti_pp_get_channel_map_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { +- char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL]; ++ char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL] = {0}; + int i; + + adm_get_multi_ch_map(channel_map, ADM_PATH_PLAYBACK); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5349/0.patch b/Patches/Linux_CVEs/CVE-2016-5349/0.patch new file mode 100644 index 00000000..ea31acb6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5349/0.patch @@ -0,0 +1,774 @@ +From 7c3bf6557c62d904b15507eb451fda8fd7ef750c Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Fri, 8 Jul 2016 14:40:45 -0700 +Subject: qseecom: support whitelist memory for qseecom_send_modfd_cmd + +qseecom_send_modfd_cmd converts ION buffer's virtual address to +scatter gather(SG) list and then sends them to TA by populating +SG list into message buffer. As the physical memory address in +SG list is used directly by TA, this allows a malicious TA to +access/corrupt arbitrary physical memory and may lead to the +process gaining kernel/root privileges. Thus, make changes to +have the QSEEComm driver passing a list of whitelist buffers +that is allowed to be mapped by TA, and the QSEE kernel, in turn, +should add checks to the register_shared_buffer syscall to make +sure the shared buffers an application is mapping falls within +one of these whitelist buffers. + +CRs-fixed: 1021945 +Change-Id: I776ead0030cad167afcf41ab985db7151a42d126 +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 370 +++++++++++++++++++++++++++++++++++++++----- + include/soc/qcom/qseecomi.h | 47 +++++- + 2 files changed, 375 insertions(+), 42 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 8117be74..7e6a179 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -181,6 +181,7 @@ struct qseecom_control { + uint32_t qseos_version; + uint32_t qsee_version; + struct device *pdev; ++ bool whitelist_support; + bool commonlib_loaded; + bool commonlib64_loaded; + struct ion_handle *cmnlib_ion_handle; +@@ -242,6 +243,30 @@ struct qseecom_listener_handle { + + static struct qseecom_control qseecom; + ++struct sglist_info { ++ uint32_t indexAndFlags; ++ uint32_t sizeOrCount; ++}; ++ ++/* ++ * The 31th bit indicates only one or multiple physical address inside ++ * the request buffer. If it is set, the index locates a single physical addr ++ * inside the request buffer, and `sizeOrCount` is the size of the memory being ++ * shared at that physical address. ++ * Otherwise, the index locates an array of {start, len} pairs (a ++ * "scatter/gather list"), and `sizeOrCount` gives the number of entries in ++ * that array. ++ * ++ * The 30th bit indicates 64 or 32bit address; when it is set, physical addr ++ * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values. ++ * ++ * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer. ++ */ ++#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \ ++ ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff))) ++ ++#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD) ++ + struct qseecom_dev_handle { + enum qseecom_client_handle_type type; + union { +@@ -255,6 +280,8 @@ struct qseecom_dev_handle { + bool perf_enabled; + bool fast_load_enabled; + enum qseecom_bandwidth_request_mode mode; ++ struct sglist_info *sglistinfo_ptr; ++ uint32_t sglist_cnt; + }; + + struct qseecom_key_id_usage_desc { +@@ -565,6 +592,38 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, + ret = scm_call2(smc_id, &desc); + break; + } ++ case QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST: { ++ struct qseecom_client_send_data_ireq *req; ++ struct qseecom_client_send_data_64bit_ireq *req_64bit; ++ ++ smc_id = TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID; ++ desc.arginfo = ++ TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID_PARAM_ID; ++ if (qseecom.qsee_version < QSEE_VERSION_40) { ++ req = (struct qseecom_client_send_data_ireq *) ++ req_buf; ++ desc.args[0] = req->app_id; ++ desc.args[1] = req->req_ptr; ++ desc.args[2] = req->req_len; ++ desc.args[3] = req->rsp_ptr; ++ desc.args[4] = req->rsp_len; ++ desc.args[5] = req->sglistinfo_ptr; ++ desc.args[6] = req->sglistinfo_len; ++ } else { ++ req_64bit = ++ (struct qseecom_client_send_data_64bit_ireq *) ++ req_buf; ++ desc.args[0] = req_64bit->app_id; ++ desc.args[1] = req_64bit->req_ptr; ++ desc.args[2] = req_64bit->req_len; ++ desc.args[3] = req_64bit->rsp_ptr; ++ desc.args[4] = req_64bit->rsp_len; ++ desc.args[5] = req_64bit->sglistinfo_ptr; ++ desc.args[6] = req_64bit->sglistinfo_len; ++ } ++ ret = scm_call2(smc_id, &desc); ++ break; ++ } + case QSEOS_RPMB_PROVISION_KEY_COMMAND: { + struct qseecom_client_send_service_ireq *req; + req = (struct qseecom_client_send_service_ireq *) +@@ -686,6 +745,36 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, + ret = scm_call2(smc_id, &desc); + break; + } ++ case QSEOS_TEE_OPEN_SESSION_WHITELIST: { ++ struct qseecom_qteec_ireq *req; ++ struct qseecom_qteec_64bit_ireq *req_64bit; ++ ++ smc_id = TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID; ++ desc.arginfo = ++ TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID_PARAM_ID; ++ if (qseecom.qsee_version < QSEE_VERSION_40) { ++ req = (struct qseecom_qteec_ireq *)req_buf; ++ desc.args[0] = req->app_id; ++ desc.args[1] = req->req_ptr; ++ desc.args[2] = req->req_len; ++ desc.args[3] = req->resp_ptr; ++ desc.args[4] = req->resp_len; ++ desc.args[5] = req->sglistinfo_ptr; ++ desc.args[6] = req->sglistinfo_len; ++ } else { ++ req_64bit = (struct qseecom_qteec_64bit_ireq *) ++ req_buf; ++ desc.args[0] = req_64bit->app_id; ++ desc.args[1] = req_64bit->req_ptr; ++ desc.args[2] = req_64bit->req_len; ++ desc.args[3] = req_64bit->resp_ptr; ++ desc.args[4] = req_64bit->resp_len; ++ desc.args[5] = req_64bit->sglistinfo_ptr; ++ desc.args[6] = req_64bit->sglistinfo_len; ++ } ++ ret = scm_call2(smc_id, &desc); ++ break; ++ } + case QSEOS_TEE_INVOKE_COMMAND: { + struct qseecom_qteec_ireq *req; + struct qseecom_qteec_64bit_ireq *req_64bit; +@@ -710,6 +799,36 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, + ret = scm_call2(smc_id, &desc); + break; + } ++ case QSEOS_TEE_INVOKE_COMMAND_WHITELIST: { ++ struct qseecom_qteec_ireq *req; ++ struct qseecom_qteec_64bit_ireq *req_64bit; ++ ++ smc_id = TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID; ++ desc.arginfo = ++ TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID_PARAM_ID; ++ if (qseecom.qsee_version < QSEE_VERSION_40) { ++ req = (struct qseecom_qteec_ireq *)req_buf; ++ desc.args[0] = req->app_id; ++ desc.args[1] = req->req_ptr; ++ desc.args[2] = req->req_len; ++ desc.args[3] = req->resp_ptr; ++ desc.args[4] = req->resp_len; ++ desc.args[5] = req->sglistinfo_ptr; ++ desc.args[6] = req->sglistinfo_len; ++ } else { ++ req_64bit = (struct qseecom_qteec_64bit_ireq *) ++ req_buf; ++ desc.args[0] = req_64bit->app_id; ++ desc.args[1] = req_64bit->req_ptr; ++ desc.args[2] = req_64bit->req_len; ++ desc.args[3] = req_64bit->resp_ptr; ++ desc.args[4] = req_64bit->resp_len; ++ desc.args[5] = req_64bit->sglistinfo_ptr; ++ desc.args[6] = req_64bit->sglistinfo_len; ++ } ++ ret = scm_call2(smc_id, &desc); ++ break; ++ } + case QSEOS_TEE_CLOSE_SESSION: { + struct qseecom_qteec_ireq *req; + struct qseecom_qteec_64bit_ireq *req_64bit; +@@ -2490,8 +2609,8 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + { + int ret = 0; + u32 reqd_len_sb_in = 0; +- struct qseecom_client_send_data_ireq send_data_req; +- struct qseecom_client_send_data_64bit_ireq send_data_req_64bit; ++ struct qseecom_client_send_data_ireq send_data_req = {0}; ++ struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0}; + struct qseecom_command_scm_resp resp; + unsigned long flags; + struct qseecom_registered_app_list *ptr_app; +@@ -2499,6 +2618,7 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + int name_len = 0; + void *cmd_buf = NULL; + size_t cmd_len; ++ struct sglist_info *table = data->sglistinfo_ptr; + + reqd_len_sb_in = req->cmd_req_len + req->resp_len; + /* find app_id & img_name from list */ +@@ -2523,7 +2643,6 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + } + + if (qseecom.qsee_version < QSEE_VERSION_40) { +- send_data_req.qsee_cmd_id = QSEOS_CLIENT_SEND_DATA_COMMAND; + send_data_req.app_id = data->client.app_id; + send_data_req.req_ptr = (uint32_t)(__qseecom_uvirt_to_kphys( + data, (uintptr_t)req->cmd_req_buf)); +@@ -2531,11 +2650,14 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + send_data_req.rsp_ptr = (uint32_t)(__qseecom_uvirt_to_kphys( + data, (uintptr_t)req->resp_buf)); + send_data_req.rsp_len = req->resp_len; ++ send_data_req.sglistinfo_ptr = ++ (uint32_t)virt_to_phys(table); ++ send_data_req.sglistinfo_len = SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_req; + cmd_len = sizeof(struct qseecom_client_send_data_ireq); + } else { +- send_data_req_64bit.qsee_cmd_id = +- QSEOS_CLIENT_SEND_DATA_COMMAND; + send_data_req_64bit.app_id = data->client.app_id; + send_data_req_64bit.req_ptr = __qseecom_uvirt_to_kphys(data, + (uintptr_t)req->cmd_req_buf); +@@ -2557,10 +2679,20 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + send_data_req_64bit.rsp_len); + return -EFAULT; + } ++ send_data_req_64bit.sglistinfo_ptr = ++ (uint64_t)virt_to_phys(table); ++ send_data_req_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&send_data_req_64bit; + cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); + } + ++ if (qseecom.whitelist_support == false) ++ *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND; ++ else ++ *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; ++ + msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + data->client.sb_virt, + reqd_len_sb_in, +@@ -2814,14 +2946,26 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, + goto err; + } + } +- if (cleanup) ++ ++ if (cleanup) { + msm_ion_do_cache_op(qseecom.ion_clnt, + ihandle, NULL, len, + ION_IOC_INV_CACHES); +- else ++ } else { + msm_ion_do_cache_op(qseecom.ion_clnt, + ihandle, NULL, len, + ION_IOC_CLEAN_INV_CACHES); ++ if (data->type == QSEECOM_CLIENT_APP) { ++ data->sglistinfo_ptr[i].indexAndFlags = ++ SGLISTINFO_SET_INDEX_FLAG( ++ (sg_ptr->nents == 1), 0, ++ req->ifd_data[i].cmd_buf_offset); ++ data->sglistinfo_ptr[i].sizeOrCount = ++ (sg_ptr->nents == 1) ? ++ sg->length : sg_ptr->nents; ++ data->sglist_cnt = i + 1; ++ } ++ } + /* Deallocate the handle */ + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(qseecom.ion_clnt, ihandle); +@@ -2904,7 +3048,8 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, + pr_err("Num of scattered entries"); + pr_err(" (%d) is greater than max supported %d\n", + sg_ptr->nents, QSEECOM_MAX_SG_ENTRY); +- goto err; ++ sg = sg_ptr->sgl; ++ goto cleanup; + } + sg = sg_ptr->sgl; + if (sg_ptr->nents == 1) { +@@ -2956,14 +3101,26 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, + sg = sg_next(sg); + } + } +- if (cleanup) ++cleanup: ++ if (cleanup) { + msm_ion_do_cache_op(qseecom.ion_clnt, + ihandle, NULL, len, + ION_IOC_INV_CACHES); +- else ++ } else { + msm_ion_do_cache_op(qseecom.ion_clnt, + ihandle, NULL, len, + ION_IOC_CLEAN_INV_CACHES); ++ if (data->type == QSEECOM_CLIENT_APP) { ++ data->sglistinfo_ptr[i].indexAndFlags = ++ SGLISTINFO_SET_INDEX_FLAG( ++ (sg_ptr->nents == 1), 1, ++ req->ifd_data[i].cmd_buf_offset); ++ data->sglistinfo_ptr[i].sizeOrCount = ++ (sg_ptr->nents == 1) ? ++ sg->length : sg_ptr->nents; ++ data->sglist_cnt = i + 1; ++ } ++ } + /* Deallocate the handle */ + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(qseecom.ion_clnt, ihandle); +@@ -5544,14 +5701,23 @@ static int __qseecom_update_qteec_req_buf(struct qseecom_qteec_modfd_req *req, + *update = (uint32_t)sg_dma_address(sg_ptr->sgl); + } + clean: +- if (cleanup) ++ if (cleanup) { + msm_ion_do_cache_op(qseecom.ion_clnt, + ihandle, NULL, sg->length, + ION_IOC_INV_CACHES); +- else ++ } else { + msm_ion_do_cache_op(qseecom.ion_clnt, + ihandle, NULL, sg->length, + ION_IOC_CLEAN_INV_CACHES); ++ data->sglistinfo_ptr[i].indexAndFlags = ++ SGLISTINFO_SET_INDEX_FLAG( ++ (sg_ptr->nents == 1), 0, ++ req->ifd_data[i].cmd_buf_offset); ++ data->sglistinfo_ptr[i].sizeOrCount = ++ (sg_ptr->nents == 1) ? ++ sg->length : sg_ptr->nents; ++ data->sglist_cnt = i + 1; ++ } + /* Deallocate the handle */ + if (!IS_ERR_OR_NULL(ihandle)) + ion_free(qseecom.ion_clnt, ihandle); +@@ -5576,6 +5742,7 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, + uint32_t reqd_len_sb_in = 0; + void *cmd_buf = NULL; + size_t cmd_len; ++ struct sglist_info *table = data->sglistinfo_ptr; + + ret = __qseecom_qteec_validate_msg(data, req); + if (ret) +@@ -5600,8 +5767,15 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, + return -ENOENT; + } + ++ if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || ++ (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { ++ ret = __qseecom_update_qteec_req_buf( ++ (struct qseecom_qteec_modfd_req *)req, data, false); ++ if (ret) ++ return ret; ++ } ++ + if (qseecom.qsee_version < QSEE_VERSION_40) { +- ireq.qsee_cmd_id = cmd_id; + ireq.app_id = data->client.app_id; + ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, + (uintptr_t)req->req_ptr); +@@ -5609,10 +5783,13 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, + ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, + (uintptr_t)req->resp_ptr); + ireq.resp_len = req->resp_len; ++ ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table); ++ ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&ireq; + cmd_len = sizeof(struct qseecom_qteec_ireq); + } else { +- ireq_64bit.qsee_cmd_id = cmd_id; + ireq_64bit.app_id = data->client.app_id; + ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, + (uintptr_t)req->req_ptr); +@@ -5632,17 +5809,19 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, + ireq_64bit.resp_ptr, ireq_64bit.resp_len); + return -EFAULT; + } ++ ireq_64bit.sglistinfo_ptr = (uint64_t)virt_to_phys(table); ++ ireq_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); + cmd_buf = (void *)&ireq_64bit; + cmd_len = sizeof(struct qseecom_qteec_64bit_ireq); + } ++ if (qseecom.whitelist_support == true ++ && cmd_id == QSEOS_TEE_OPEN_SESSION) ++ *(uint32_t *)cmd_buf = QSEOS_TEE_OPEN_SESSION_WHITELIST; ++ else ++ *(uint32_t *)cmd_buf = cmd_id; + +- if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || +- (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { +- ret = __qseecom_update_qteec_req_buf( +- (struct qseecom_qteec_modfd_req *)req, data, false); +- if (ret) +- return ret; +- } + reqd_len_sb_in = req->req_len + req->resp_len; + msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + data->client.sb_virt, +@@ -5740,6 +5919,9 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, + uint32_t reqd_len_sb_in = 0; + void *cmd_buf = NULL; + size_t cmd_len; ++ struct sglist_info *table = data->sglistinfo_ptr; ++ void *req_ptr = NULL; ++ void *resp_ptr = NULL; + + ret = copy_from_user(&req, argp, + sizeof(struct qseecom_qteec_modfd_req)); +@@ -5751,6 +5933,8 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, + (struct qseecom_qteec_req *)(&req)); + if (ret) + return ret; ++ req_ptr = req.req_ptr; ++ resp_ptr = req.resp_ptr; + + /* find app_id & img_name from list */ + spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); +@@ -5771,45 +5955,56 @@ static int qseecom_qteec_invoke_modfd_cmd(struct qseecom_dev_handle *data, + return -ENOENT; + } + ++ /* validate offsets */ ++ for (i = 0; i < MAX_ION_FD; i++) { ++ if (req.ifd_data[i].fd) { ++ if (req.ifd_data[i].cmd_buf_offset >= req.req_len) ++ return -EINVAL; ++ } ++ } ++ req.req_ptr = (void *)__qseecom_uvirt_to_kvirt(data, ++ (uintptr_t)req.req_ptr); ++ req.resp_ptr = (void *)__qseecom_uvirt_to_kvirt(data, ++ (uintptr_t)req.resp_ptr); ++ ret = __qseecom_update_qteec_req_buf(&req, data, false); ++ if (ret) ++ return ret; ++ + if (qseecom.qsee_version < QSEE_VERSION_40) { +- ireq.qsee_cmd_id = QSEOS_TEE_INVOKE_COMMAND; + ireq.app_id = data->client.app_id; + ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, +- (uintptr_t)req.req_ptr); ++ (uintptr_t)req_ptr); + ireq.req_len = req.req_len; + ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, +- (uintptr_t)req.resp_ptr); ++ (uintptr_t)resp_ptr); + ireq.resp_len = req.resp_len; + cmd_buf = (void *)&ireq; + cmd_len = sizeof(struct qseecom_qteec_ireq); ++ ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table); ++ ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); + } else { +- ireq_64bit.qsee_cmd_id = QSEOS_TEE_INVOKE_COMMAND; + ireq_64bit.app_id = data->client.app_id; + ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, +- (uintptr_t)req.req_ptr); ++ (uintptr_t)req_ptr); + ireq_64bit.req_len = req.req_len; + ireq_64bit.resp_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, +- (uintptr_t)req.resp_ptr); ++ (uintptr_t)resp_ptr); + ireq_64bit.resp_len = req.resp_len; + cmd_buf = (void *)&ireq_64bit; + cmd_len = sizeof(struct qseecom_qteec_64bit_ireq); ++ ireq_64bit.sglistinfo_ptr = (uint64_t)virt_to_phys(table); ++ ireq_64bit.sglistinfo_len = SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); + } + reqd_len_sb_in = req.req_len + req.resp_len; ++ if (qseecom.whitelist_support == true) ++ *(uint32_t *)cmd_buf = QSEOS_TEE_INVOKE_COMMAND_WHITELIST; ++ else ++ *(uint32_t *)cmd_buf = QSEOS_TEE_INVOKE_COMMAND; + +- /* validate offsets */ +- for (i = 0; i < MAX_ION_FD; i++) { +- if (req.ifd_data[i].fd) { +- if (req.ifd_data[i].cmd_buf_offset >= req.req_len) +- return -EINVAL; +- } +- } +- req.req_ptr = (void *)__qseecom_uvirt_to_kvirt(data, +- (uintptr_t)req.req_ptr); +- req.resp_ptr = (void *)__qseecom_uvirt_to_kvirt(data, +- (uintptr_t)req.resp_ptr); +- ret = __qseecom_update_qteec_req_buf(&req, data, false); +- if (ret) +- return ret; + msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle, + data->client.sb_virt, + reqd_len_sb_in, +@@ -5872,6 +6067,15 @@ static int qseecom_qteec_request_cancellation(struct qseecom_dev_handle *data, + return ret; + } + ++static void __qseecom_clean_data_sglistinfo(struct qseecom_dev_handle *data) ++{ ++ if (data->sglist_cnt) { ++ memset(data->sglistinfo_ptr, 0, ++ SGLISTINFO_TABLE_SIZE); ++ data->sglist_cnt = 0; ++ } ++} ++ + long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + { + int ret = 0; +@@ -6047,6 +6251,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + mutex_unlock(&app_access_lock); + if (ret) + pr_err("failed qseecom_send_cmd: %d\n", ret); ++ __qseecom_clean_data_sglistinfo(data); + break; + } + case QSEECOM_IOCTL_RECEIVE_REQ: { +@@ -6439,6 +6644,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + mutex_unlock(&app_access_lock); + if (ret) + pr_err("failed open_session_cmd: %d\n", ret); ++ __qseecom_clean_data_sglistinfo(data); + break; + } + case QSEECOM_QTEEC_IOCTL_CLOSE_SESSION_REQ: { +@@ -6487,6 +6693,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + mutex_unlock(&app_access_lock); + if (ret) + pr_err("failed Invoke cmd: %d\n", ret); ++ __qseecom_clean_data_sglistinfo(data); + break; + } + case QSEECOM_QTEEC_IOCTL_REQUEST_CANCELLATION_REQ: { +@@ -6539,6 +6746,9 @@ static int qseecom_open(struct inode *inode, struct file *file) + init_waitqueue_head(&data->abort_wq); + atomic_set(&data->ioctl_count, 0); + ++ data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); ++ if (!(data->sglistinfo_ptr)) ++ return -ENOMEM; + return ret; + } + +@@ -6591,6 +6801,7 @@ static int qseecom_release(struct inode *inode, struct file *file) + if (data->perf_enabled == true) + qsee_disable_clock_vote(data, CLK_DFAB); + } ++ kfree(data->sglistinfo_ptr); + kfree(data); + + return ret; +@@ -6731,6 +6942,74 @@ static void __qseecom_deinit_clk(enum qseecom_ce_hw_instance ce) + qclk->instance = CLK_INVALID; + } + ++/* ++ * Check if whitelist feature is supported by making a test scm_call ++ * to send a whitelist command to an invalid app ID 0 ++ */ ++static int qseecom_check_whitelist_feature(void) ++{ ++ struct qseecom_client_send_data_ireq send_data_req = {0}; ++ struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0}; ++ struct qseecom_command_scm_resp resp; ++ uint32_t buf_size = 128; ++ void *buf = NULL; ++ void *cmd_buf = NULL; ++ size_t cmd_len; ++ int ret = 0; ++ phys_addr_t pa; ++ ++ buf = kzalloc(buf_size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ pa = virt_to_phys(buf); ++ if (qseecom.qsee_version < QSEE_VERSION_40) { ++ send_data_req.qsee_cmd_id = ++ QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; ++ send_data_req.app_id = 0; ++ send_data_req.req_ptr = (uint32_t)pa; ++ send_data_req.req_len = buf_size; ++ send_data_req.rsp_ptr = (uint32_t)pa; ++ send_data_req.rsp_len = buf_size; ++ send_data_req.sglistinfo_ptr = (uint32_t)pa; ++ send_data_req.sglistinfo_len = buf_size; ++ cmd_buf = (void *)&send_data_req; ++ cmd_len = sizeof(struct qseecom_client_send_data_ireq); ++ } else { ++ send_data_req_64bit.qsee_cmd_id = ++ QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; ++ send_data_req_64bit.app_id = 0; ++ send_data_req_64bit.req_ptr = (uint64_t)pa; ++ send_data_req_64bit.req_len = buf_size; ++ send_data_req_64bit.rsp_ptr = (uint64_t)pa; ++ send_data_req_64bit.rsp_len = buf_size; ++ send_data_req_64bit.sglistinfo_ptr = (uint64_t)pa; ++ send_data_req_64bit.sglistinfo_len = buf_size; ++ cmd_buf = (void *)&send_data_req_64bit; ++ cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); ++ } ++ ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, ++ cmd_buf, cmd_len, ++ &resp, sizeof(resp)); ++/* ++ * If this cmd exists and whitelist is supported, scm_call return -2 (scm ++ * driver remap it to -EINVAL) and resp.result 0xFFFFFFED(-19); Otherwise, ++ * scm_call return -1 (remap to -EIO). ++ */ ++ if (ret == -EIO) { ++ qseecom.whitelist_support = false; ++ ret = 0; ++ } else if (ret == -EINVAL && ++ resp.result == QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD) { ++ qseecom.whitelist_support = true; ++ ret = 0; ++ } else { ++ pr_err("Failed to check whitelist: ret = %d, result = 0x%x\n", ++ ret, resp.result); ++ } ++ kfree(buf); ++ return ret; ++} ++ + static int qseecom_probe(struct platform_device *pdev) + { + int rc; +@@ -6762,6 +7041,7 @@ static int qseecom_probe(struct platform_device *pdev) + + qseecom.app_block_ref_cnt = 0; + init_waitqueue_head(&qseecom.app_block_wq); ++ qseecom.whitelist_support = true; + + rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV); + if (rc < 0) { +@@ -7056,6 +7336,14 @@ static int qseecom_probe(struct platform_device *pdev) + qseecom.qsee_perf_client = msm_bus_scale_register_client( + qseecom_platform_support); + ++ rc = qseecom_check_whitelist_feature(); ++ if (rc) { ++ rc = -EINVAL; ++ goto exit_destroy_ion_client; ++ } ++ pr_warn("qseecom.whitelist_support = %d\n", ++ qseecom.whitelist_support); ++ + if (!qseecom.qsee_perf_client) + pr_err("Unable to register bus client\n"); + return 0; +diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h +index ad135e8..50b10f9 100644 +--- a/include/soc/qcom/qseecomi.h ++++ b/include/soc/qcom/qseecomi.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2016, The 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 +@@ -18,6 +18,7 @@ + + #define QSEECOM_KEY_ID_SIZE 32 + ++#define QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD -19 /*0xFFFFFFED*/ + #define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63 + #define QSEOS_RESULT_FAIL_KS_OP -64 + #define QSEOS_RESULT_FAIL_KEY_ID_EXISTS -65 +@@ -74,6 +75,9 @@ enum qseecom_qceos_cmd_id { + QSEOS_FSM_IKE_CMD_SIGN = 0x200, + QSEOS_FSM_IKE_CMD_PROV_KEY = 0x201, + QSEOS_FSM_IKE_CMD_ENCRYPT_PRIVATE_KEY = 0x202, ++ QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST = 0x1C, ++ QSEOS_TEE_OPEN_SESSION_WHITELIST = 0x1D, ++ QSEOS_TEE_INVOKE_COMMAND_WHITELIST = 0x1E, + QSEOS_FSM_OEM_FUSE_WRITE_ROW = 0x301, + QSEOS_FSM_OEM_FUSE_READ_ROW = 0x302, + QSEOS_CMD_MAX = 0xEFFFFFFF +@@ -175,6 +179,8 @@ __packed struct qseecom_client_send_data_ireq { + uint32_t req_len; + uint32_t rsp_ptr;/* First 4 bytes should be the return status */ + uint32_t rsp_len; ++ uint32_t sglistinfo_ptr; ++ uint32_t sglistinfo_len; + }; + + __packed struct qseecom_client_send_data_64bit_ireq { +@@ -184,6 +190,8 @@ __packed struct qseecom_client_send_data_64bit_ireq { + uint32_t req_len; + uint64_t rsp_ptr; + uint32_t rsp_len; ++ uint64_t sglistinfo_ptr; ++ uint32_t sglistinfo_len; + }; + + __packed struct qseecom_reg_log_buf_ireq { +@@ -286,6 +294,8 @@ __packed struct qseecom_qteec_ireq { + uint32_t req_len; + uint32_t resp_ptr; + uint32_t resp_len; ++ uint32_t sglistinfo_ptr; ++ uint32_t sglistinfo_len; + }; + + __packed struct qseecom_qteec_64bit_ireq { +@@ -295,6 +305,8 @@ __packed struct qseecom_qteec_64bit_ireq { + uint32_t req_len; + uint64_t resp_ptr; + uint32_t resp_len; ++ uint64_t sglistinfo_ptr; ++ uint32_t sglistinfo_len; + }; + + __packed struct qseecom_client_send_fsm_key_req { +@@ -634,4 +646,37 @@ __packed struct qseecom_client_send_fsm_key_req { + #define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL) + ++#define TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID \ ++ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ ++ TZ_SVC_APP_ID_PLACEHOLDER, 0x06) ++ ++#define TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID_PARAM_ID \ ++ TZ_SYSCALL_CREATE_PARAM_ID_7( \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL) ++ ++#define TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID \ ++ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ ++ TZ_SVC_APP_ID_PLACEHOLDER, 0x07) ++ ++#define TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID_PARAM_ID \ ++ TZ_SYSCALL_CREATE_PARAM_ID_7( \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL) ++ ++#define TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID \ ++ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_TZ_APPS, \ ++ TZ_SVC_APP_ID_PLACEHOLDER, 0x09) ++ ++#define TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID_PARAM_ID \ ++ TZ_SYSCALL_CREATE_PARAM_ID_7( \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ ++ TZ_SYSCALL_PARAM_TYPE_VAL) ++ + #endif /* __QSEECOMI_H_ */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5349/1.patch b/Patches/Linux_CVEs/CVE-2016-5349/1.patch new file mode 100644 index 00000000..e33e19fc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5349/1.patch @@ -0,0 +1,630 @@ +From 9bd398661cae758ffc557adc7de74ba32654e1f9 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Fri, 2 Sep 2016 22:09:23 -0700 +Subject: qseecom: whitelist support for kernel client and listener + +-- Add whitelist support for listener to send modified resp to TZ; +-- support whitelist for kernel client; +-- Change the method to check whitelist feature. + +Change-Id: I0030b0008d6224cda3fdc1f80308a7e9bcfe4405 +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 322 +++++++++++++++++++++++++------------------- + include/soc/qcom/qseecomi.h | 19 +++ + 2 files changed, 206 insertions(+), 135 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 061bc99..35f0b94 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -131,6 +131,35 @@ static DEFINE_MUTEX(qsee_bw_mutex); + static DEFINE_MUTEX(app_access_lock); + static DEFINE_MUTEX(clk_access_lock); + ++struct sglist_info { ++ uint32_t indexAndFlags; ++ uint32_t sizeOrCount; ++}; ++ ++/* ++ * The 31th bit indicates only one or multiple physical address inside ++ * the request buffer. If it is set, the index locates a single physical addr ++ * inside the request buffer, and `sizeOrCount` is the size of the memory being ++ * shared at that physical address. ++ * Otherwise, the index locates an array of {start, len} pairs (a ++ * "scatter/gather list"), and `sizeOrCount` gives the number of entries in ++ * that array. ++ * ++ * The 30th bit indicates 64 or 32bit address; when it is set, physical addr ++ * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values. ++ * ++ * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer. ++ */ ++#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \ ++ ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff))) ++ ++#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD) ++ ++#define FEATURE_ID_WHITELIST 15 /*whitelist feature id*/ ++ ++#define MAKE_WHITELIST_VERSION(major, minor, patch) \ ++ (((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF)) ++ + struct qseecom_registered_listener_list { + struct list_head list; + struct qseecom_register_listener_req svc; +@@ -145,6 +174,8 @@ struct qseecom_registered_listener_list { + bool listener_in_use; + /* wq for thread blocked on this listener*/ + wait_queue_head_t listener_block_app_wq; ++ struct sglist_info sglistinfo_ptr[MAX_ION_FD]; ++ uint32_t sglist_cnt; + }; + + struct qseecom_registered_app_list { +@@ -268,30 +299,6 @@ struct qseecom_listener_handle { + + static struct qseecom_control qseecom; + +-struct sglist_info { +- uint32_t indexAndFlags; +- uint32_t sizeOrCount; +-}; +- +-/* +- * The 31th bit indicates only one or multiple physical address inside +- * the request buffer. If it is set, the index locates a single physical addr +- * inside the request buffer, and `sizeOrCount` is the size of the memory being +- * shared at that physical address. +- * Otherwise, the index locates an array of {start, len} pairs (a +- * "scatter/gather list"), and `sizeOrCount` gives the number of entries in +- * that array. +- * +- * The 30th bit indicates 64 or 32bit address; when it is set, physical addr +- * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values. +- * +- * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer. +- */ +-#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \ +- ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff))) +- +-#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD) +- + struct qseecom_dev_handle { + enum qseecom_client_handle_type type; + union { +@@ -305,8 +312,9 @@ struct qseecom_dev_handle { + bool perf_enabled; + bool fast_load_enabled; + enum qseecom_bandwidth_request_mode mode; +- struct sglist_info *sglistinfo_ptr; ++ struct sglist_info sglistinfo_ptr[MAX_ION_FD]; + uint32_t sglist_cnt; ++ bool use_legacy_cmd; + }; + + struct qseecom_key_id_usage_desc { +@@ -584,6 +592,34 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, + ret = scm_call2(smc_id, &desc); + break; + } ++ case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: { ++ struct qseecom_client_listener_data_irsp *req; ++ struct qseecom_client_listener_data_64bit_irsp *req_64; ++ ++ smc_id = ++ TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID; ++ desc.arginfo = ++ TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID; ++ if (qseecom.qsee_version < QSEE_VERSION_40) { ++ req = ++ (struct qseecom_client_listener_data_irsp *) ++ req_buf; ++ desc.args[0] = req->listener_id; ++ desc.args[1] = req->status; ++ desc.args[2] = req->sglistinfo_ptr; ++ desc.args[3] = req->sglistinfo_len; ++ } else { ++ req_64 = ++ (struct qseecom_client_listener_data_64bit_irsp *) ++ req_buf; ++ desc.args[0] = req_64->listener_id; ++ desc.args[1] = req_64->status; ++ desc.args[2] = req_64->sglistinfo_ptr; ++ desc.args[3] = req_64->sglistinfo_len; ++ } ++ ret = scm_call2(smc_id, &desc); ++ break; ++ } + case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: { + struct qseecom_load_app_ireq *req; + struct qseecom_load_app_64bit_ireq *req_64bit; +@@ -1124,7 +1160,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, + return -EBUSY; + } + +- new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); ++ new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); + if (!new_entry) { + pr_err("kmalloc failed\n"); + return -ENOMEM; +@@ -1585,6 +1621,16 @@ static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data, + return ret; + } + ++static void __qseecom_clean_listener_sglistinfo( ++ struct qseecom_registered_listener_list *ptr_svc) ++{ ++ if (ptr_svc->sglist_cnt) { ++ memset(ptr_svc->sglistinfo_ptr, 0, ++ SGLISTINFO_TABLE_SIZE); ++ ptr_svc->sglist_cnt = 0; ++ } ++} ++ + static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, + struct qseecom_command_scm_resp *resp) + { +@@ -1593,9 +1639,14 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, + uint32_t lstnr; + unsigned long flags; + struct qseecom_client_listener_data_irsp send_data_rsp; ++ struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit; + struct qseecom_registered_listener_list *ptr_svc = NULL; + sigset_t new_sigset; + sigset_t old_sigset; ++ uint32_t status; ++ void *cmd_buf = NULL; ++ size_t cmd_len; ++ struct sglist_info *table = NULL; + + while (resp->result == QSEOS_RESULT_INCOMPLETE) { + lstnr = resp->data; +@@ -1669,15 +1720,42 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, + pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", + data->client.app_id, lstnr, ret); + rc = -ENODEV; +- send_data_rsp.status = QSEOS_RESULT_FAILURE; ++ status = QSEOS_RESULT_FAILURE; + } else { +- send_data_rsp.status = QSEOS_RESULT_SUCCESS; ++ status = QSEOS_RESULT_SUCCESS; + } + + qseecom.send_resp_flag = 0; + ptr_svc->send_resp_flag = 0; +- send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; +- send_data_rsp.listener_id = lstnr; ++ table = ptr_svc->sglistinfo_ptr; ++ if (qseecom.qsee_version < QSEE_VERSION_40) { ++ send_data_rsp.listener_id = lstnr; ++ send_data_rsp.status = status; ++ send_data_rsp.sglistinfo_ptr = ++ (uint32_t)virt_to_phys(table); ++ send_data_rsp.sglistinfo_len = ++ SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); ++ cmd_buf = (void *)&send_data_rsp; ++ cmd_len = sizeof(send_data_rsp); ++ } else { ++ send_data_rsp_64bit.listener_id = lstnr; ++ send_data_rsp_64bit.status = status; ++ send_data_rsp_64bit.sglistinfo_ptr = ++ virt_to_phys(table); ++ send_data_rsp_64bit.sglistinfo_len = ++ SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); ++ cmd_buf = (void *)&send_data_rsp_64bit; ++ cmd_len = sizeof(send_data_rsp_64bit); ++ } ++ if (qseecom.whitelist_support == false) ++ *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND; ++ else ++ *(uint32_t *)cmd_buf = ++ QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; + if (ptr_svc) + msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, + ptr_svc->sb_virt, ptr_svc->sb_length, +@@ -1687,10 +1765,9 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, + __qseecom_enable_clk(CLK_QSEE); + + ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, +- (const void *)&send_data_rsp, +- sizeof(send_data_rsp), resp, +- sizeof(*resp)); ++ cmd_buf, cmd_len, resp, sizeof(*resp)); + ptr_svc->listener_in_use = false; ++ __qseecom_clean_listener_sglistinfo(ptr_svc); + if (ret) { + pr_err("scm_call() failed with err: %d (app_id = %d)\n", + ret, data->client.app_id); +@@ -1818,9 +1895,14 @@ static int __qseecom_reentrancy_process_incomplete_cmd( + uint32_t lstnr = 0; + unsigned long flags; + struct qseecom_client_listener_data_irsp send_data_rsp; ++ struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit; + struct qseecom_registered_listener_list *ptr_svc = NULL; + sigset_t new_sigset; + sigset_t old_sigset; ++ uint32_t status; ++ void *cmd_buf = NULL; ++ size_t cmd_len; ++ struct sglist_info *table = NULL; + + while (ret == 0 && rc == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) { + lstnr = resp->data; +@@ -1883,13 +1965,38 @@ static int __qseecom_reentrancy_process_incomplete_cmd( + pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", + data->client.app_id, lstnr, ret); + rc = -ENODEV; +- send_data_rsp.status = QSEOS_RESULT_FAILURE; ++ status = QSEOS_RESULT_FAILURE; + } else { +- send_data_rsp.status = QSEOS_RESULT_SUCCESS; ++ status = QSEOS_RESULT_SUCCESS; + } +- +- send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; +- send_data_rsp.listener_id = lstnr; ++ table = ptr_svc->sglistinfo_ptr; ++ if (qseecom.qsee_version < QSEE_VERSION_40) { ++ send_data_rsp.listener_id = lstnr; ++ send_data_rsp.status = status; ++ send_data_rsp.sglistinfo_ptr = ++ (uint32_t)virt_to_phys(table); ++ send_data_rsp.sglistinfo_len = SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); ++ cmd_buf = (void *)&send_data_rsp; ++ cmd_len = sizeof(send_data_rsp); ++ } else { ++ send_data_rsp_64bit.listener_id = lstnr; ++ send_data_rsp_64bit.status = status; ++ send_data_rsp_64bit.sglistinfo_ptr = ++ virt_to_phys(table); ++ send_data_rsp_64bit.sglistinfo_len = ++ SGLISTINFO_TABLE_SIZE; ++ dmac_flush_range((void *)table, ++ (void *)table + SGLISTINFO_TABLE_SIZE); ++ cmd_buf = (void *)&send_data_rsp_64bit; ++ cmd_len = sizeof(send_data_rsp_64bit); ++ } ++ if (qseecom.whitelist_support == false) ++ *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND; ++ else ++ *(uint32_t *)cmd_buf = ++ QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST; + if (ptr_svc) + msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle, + ptr_svc->sb_virt, ptr_svc->sb_length, +@@ -1899,11 +2006,9 @@ static int __qseecom_reentrancy_process_incomplete_cmd( + __qseecom_enable_clk(CLK_QSEE); + + ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, +- (const void *)&send_data_rsp, +- sizeof(send_data_rsp), resp, +- sizeof(*resp)); +- ++ cmd_buf, cmd_len, resp, sizeof(*resp)); + ptr_svc->listener_in_use = false; ++ __qseecom_clean_listener_sglistinfo(ptr_svc); + wake_up_interruptible(&ptr_svc->listener_block_app_wq); + + if (ret) { +@@ -2901,7 +3006,7 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, + cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); + } + +- if (qseecom.whitelist_support == false) ++ if (qseecom.whitelist_support == false || data->use_legacy_cmd == true) + *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND; + else + *(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; +@@ -3006,6 +3111,8 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, + struct qseecom_send_modfd_cmd_req *req = NULL; + struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL; + struct qseecom_registered_listener_list *this_lstnr = NULL; ++ uint32_t offset; ++ struct sg_table *sg_ptr; + + if ((data->type != QSEECOM_LISTENER_SERVICE) && + (data->type != QSEECOM_CLIENT_APP)) +@@ -3027,7 +3134,6 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, + } + + for (i = 0; i < MAX_ION_FD; i++) { +- struct sg_table *sg_ptr = NULL; + if ((data->type != QSEECOM_LISTENER_SERVICE) && + (req->ifd_data[i].fd > 0)) { + ihandle = ion_import_dma_buf(qseecom.ion_clnt, +@@ -3169,14 +3275,25 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, + ihandle, NULL, len, + ION_IOC_CLEAN_INV_CACHES); + if (data->type == QSEECOM_CLIENT_APP) { ++ offset = req->ifd_data[i].cmd_buf_offset; + data->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( +- (sg_ptr->nents == 1), 0, +- req->ifd_data[i].cmd_buf_offset); ++ (sg_ptr->nents == 1), 0, offset); + data->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + data->sglist_cnt = i + 1; ++ } else { ++ offset = (lstnr_resp->ifd_data[i].cmd_buf_offset ++ + (uintptr_t)lstnr_resp->resp_buf_ptr - ++ (uintptr_t)this_lstnr->sb_virt); ++ this_lstnr->sglistinfo_ptr[i].indexAndFlags = ++ SGLISTINFO_SET_INDEX_FLAG( ++ (sg_ptr->nents == 1), 0, offset); ++ this_lstnr->sglistinfo_ptr[i].sizeOrCount = ++ (sg_ptr->nents == 1) ? ++ sg->length : sg_ptr->nents; ++ this_lstnr->sglist_cnt = i + 1; + } + } + /* Deallocate the handle */ +@@ -3249,6 +3366,8 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, + struct qseecom_send_modfd_cmd_req *req = NULL; + struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL; + struct qseecom_registered_listener_list *this_lstnr = NULL; ++ uint32_t offset; ++ struct sg_table *sg_ptr; + + if ((data->type != QSEECOM_LISTENER_SERVICE) && + (data->type != QSEECOM_CLIENT_APP)) +@@ -3270,7 +3389,6 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, + } + + for (i = 0; i < MAX_ION_FD; i++) { +- struct sg_table *sg_ptr = NULL; + if ((data->type != QSEECOM_LISTENER_SERVICE) && + (req->ifd_data[i].fd > 0)) { + ihandle = ion_import_dma_buf(qseecom.ion_clnt, +@@ -3387,14 +3505,25 @@ cleanup: + ihandle, NULL, len, + ION_IOC_CLEAN_INV_CACHES); + if (data->type == QSEECOM_CLIENT_APP) { ++ offset = req->ifd_data[i].cmd_buf_offset; + data->sglistinfo_ptr[i].indexAndFlags = + SGLISTINFO_SET_INDEX_FLAG( +- (sg_ptr->nents == 1), 1, +- req->ifd_data[i].cmd_buf_offset); ++ (sg_ptr->nents == 1), 1, offset); + data->sglistinfo_ptr[i].sizeOrCount = + (sg_ptr->nents == 1) ? + sg->length : sg_ptr->nents; + data->sglist_cnt = i + 1; ++ } else { ++ offset = (lstnr_resp->ifd_data[i].cmd_buf_offset ++ + (uintptr_t)lstnr_resp->resp_buf_ptr - ++ (uintptr_t)this_lstnr->sb_virt); ++ this_lstnr->sglistinfo_ptr[i].indexAndFlags = ++ SGLISTINFO_SET_INDEX_FLAG( ++ (sg_ptr->nents == 1), 1, offset); ++ this_lstnr->sglistinfo_ptr[i].sizeOrCount = ++ (sg_ptr->nents == 1) ? ++ sg->length : sg_ptr->nents; ++ this_lstnr->sglist_cnt = i + 1; + } + } + /* Deallocate the handle */ +@@ -4091,21 +4220,12 @@ int qseecom_start_app(struct qseecom_handle **handle, + data->client.user_virt_sb_base = 0; + data->client.ihandle = NULL; + +- /* Allocate sglistinfo buffer for kernel client */ +- data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); +- if (!(data->sglistinfo_ptr)) { +- kfree(data); +- kfree(*handle); +- *handle = NULL; +- return -ENOMEM; +- } + init_waitqueue_head(&data->abort_wq); + + data->client.ihandle = ion_alloc(qseecom.ion_clnt, size, 4096, + ION_HEAP(ION_QSECOM_HEAP_ID), 0); + if (IS_ERR_OR_NULL(data->client.ihandle)) { + pr_err("Ion client could not retrieve the handle\n"); +- kfree(data->sglistinfo_ptr); + kfree(data); + kfree(*handle); + *handle = NULL; +@@ -4203,7 +4323,6 @@ int qseecom_start_app(struct qseecom_handle **handle, + return 0; + + err: +- kfree(data->sglistinfo_ptr); + kfree(data); + kfree(*handle); + *handle = NULL; +@@ -4251,7 +4370,6 @@ int qseecom_shutdown_app(struct qseecom_handle **handle) + + mutex_unlock(&app_access_lock); + if (ret == 0) { +- kzfree(data->sglistinfo_ptr); + kzfree(data); + kzfree(*handle); + kzfree(kclient); +@@ -4317,8 +4435,11 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, + } + perf_enabled = true; + } ++ if (!strcmp(data->client.app_name, "securemm")) ++ data->use_legacy_cmd = true; + + ret = __qseecom_send_cmd(data, &req); ++ data->use_legacy_cmd = false; + if (qseecom.support_bus_scaling) + __qseecom_add_bw_scale_down_timer( + QSEECOM_SEND_CMD_CRYPTO_TIMEOUT); +@@ -6990,6 +7111,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + wake_up_all(&data->abort_wq); + if (ret) + pr_err("failed qseecom_send_mod_resp: %d\n", ret); ++ __qseecom_clean_data_sglistinfo(data); + break; + } + case QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ: { +@@ -7139,12 +7261,6 @@ static int qseecom_open(struct inode *inode, struct file *file) + data->mode = INACTIVE; + init_waitqueue_head(&data->abort_wq); + atomic_set(&data->ioctl_count, 0); +- +- data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); +- if (!(data->sglistinfo_ptr)) { +- kzfree(data); +- return -ENOMEM; +- } + return ret; + } + +@@ -7199,7 +7315,6 @@ static int qseecom_release(struct inode *inode, struct file *file) + if (data->perf_enabled == true) + qsee_disable_clock_vote(data, CLK_DFAB); + } +- kfree(data->sglistinfo_ptr); + kfree(data); + + return ret; +@@ -7948,73 +8063,14 @@ out: + } + + /* +- * Check if whitelist feature is supported by making a test scm_call +- * to send a whitelist command to an invalid app ID 0 ++ * Check whitelist feature, and if TZ feature version is < 1.0.0, ++ * then whitelist feature is not supported. + */ + static int qseecom_check_whitelist_feature(void) + { +- struct qseecom_client_send_data_ireq send_data_req = {0}; +- struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0}; +- struct qseecom_command_scm_resp resp; +- uint32_t buf_size = 128; +- void *buf = NULL; +- void *cmd_buf = NULL; +- size_t cmd_len; +- int ret = 0; +- phys_addr_t pa; ++ int version = scm_get_feat_version(FEATURE_ID_WHITELIST); + +- buf = kzalloc(buf_size, GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- pa = virt_to_phys(buf); +- if (qseecom.qsee_version < QSEE_VERSION_40) { +- send_data_req.qsee_cmd_id = +- QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; +- send_data_req.app_id = 0; +- send_data_req.req_ptr = (uint32_t)pa; +- send_data_req.req_len = buf_size; +- send_data_req.rsp_ptr = (uint32_t)pa; +- send_data_req.rsp_len = buf_size; +- send_data_req.sglistinfo_ptr = (uint32_t)pa; +- send_data_req.sglistinfo_len = buf_size; +- cmd_buf = (void *)&send_data_req; +- cmd_len = sizeof(struct qseecom_client_send_data_ireq); +- } else { +- send_data_req_64bit.qsee_cmd_id = +- QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST; +- send_data_req_64bit.app_id = 0; +- send_data_req_64bit.req_ptr = (uint64_t)pa; +- send_data_req_64bit.req_len = buf_size; +- send_data_req_64bit.rsp_ptr = (uint64_t)pa; +- send_data_req_64bit.rsp_len = buf_size; +- send_data_req_64bit.sglistinfo_ptr = (uint64_t)pa; +- send_data_req_64bit.sglistinfo_len = buf_size; +- cmd_buf = (void *)&send_data_req_64bit; +- cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq); +- } +- ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, +- cmd_buf, cmd_len, +- &resp, sizeof(resp)); +-/* +- * If this cmd exists and whitelist is supported, scm_call return -2 (scm +- * driver remap it to -EINVAL) and resp.result 0xFFFFFFED(-19); Otherwise, +- * scm_call return -1 (remap to -EIO). +- */ +- if (ret == -EIO) { +- qseecom.whitelist_support = false; +- ret = 0; +- } else if (ret == -EINVAL && +- resp.result == QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD) { +- qseecom.whitelist_support = true; +- ret = 0; +- } else { +- pr_info("Check whitelist with ret = %d, result = 0x%x\n", +- ret, resp.result); +- qseecom.whitelist_support = false; +- ret = 0; +- } +- kfree(buf); +- return ret; ++ return version >= MAKE_WHITELIST_VERSION(1, 0, 0); + } + + static int qseecom_probe(struct platform_device *pdev) +@@ -8265,11 +8321,7 @@ static int qseecom_probe(struct platform_device *pdev) + qseecom.qsee_perf_client = msm_bus_scale_register_client( + qseecom_platform_support); + +- rc = qseecom_check_whitelist_feature(); +- if (rc) { +- rc = -EINVAL; +- goto exit_destroy_ion_client; +- } ++ qseecom.whitelist_support = qseecom_check_whitelist_feature(); + pr_warn("qseecom.whitelist_support = %d\n", + qseecom.whitelist_support); + +diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h +index b0a8d67..e33fd9f 100644 +--- a/include/soc/qcom/qseecomi.h ++++ b/include/soc/qcom/qseecomi.h +@@ -68,6 +68,7 @@ enum qseecom_qceos_cmd_id { + QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST = 0x1C, + QSEOS_TEE_OPEN_SESSION_WHITELIST = 0x1D, + QSEOS_TEE_INVOKE_COMMAND_WHITELIST = 0x1E, ++ QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST = 0x1F, + QSEOS_FSM_LTEOTA_REQ_CMD = 0x109, + QSEOS_FSM_LTEOTA_REQ_RSP_CMD = 0x110, + QSEOS_FSM_IKE_REQ_CMD = 0x203, +@@ -217,6 +218,16 @@ __packed struct qseecom_client_listener_data_irsp { + uint32_t qsee_cmd_id; + uint32_t listener_id; + uint32_t status; ++ uint32_t sglistinfo_ptr; ++ uint32_t sglistinfo_len; ++}; ++ ++__packed struct qseecom_client_listener_data_64bit_irsp { ++ uint32_t qsee_cmd_id; ++ uint32_t listener_id; ++ uint32_t status; ++ uint64_t sglistinfo_ptr; ++ uint32_t sglistinfo_len; + }; + + /* +@@ -703,4 +714,12 @@ __packed struct qseecom_continue_blocked_request_ireq { + TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ + TZ_SYSCALL_PARAM_TYPE_VAL) + ++#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID \ ++ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x05) ++ ++#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID \ ++ TZ_SYSCALL_CREATE_PARAM_ID_4( \ ++ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \ ++ TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL) ++ + #endif /* __QSEECOMI_H_ */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5349/2.patch b/Patches/Linux_CVEs/CVE-2016-5349/2.patch new file mode 100644 index 00000000..094b7177 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5349/2.patch @@ -0,0 +1,47 @@ +From e3d969000fb60ecb9bc01667fa89957f67763514 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Wed, 7 Sep 2016 16:22:11 +0530 +Subject: qseecom: Change whitelist_support flag to false if TZ failed to check + +The whitelist status is set default as true though TZ failed to check, +which in turn causing the send_command fail by passing whitelist commnd id. +So updating the support status flag to false when TZ fails to check. + +Change-Id: I78a7600506b4d2457bb1c38f8a39888a9cf9467c +Signed-off-by: Mallikarjuna Reddy Amireddy +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 543eff3..a0d27d6 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -6838,8 +6838,10 @@ static int qseecom_open(struct inode *inode, struct file *file) + atomic_set(&data->ioctl_count, 0); + + data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); +- if (!(data->sglistinfo_ptr)) ++ if (!(data->sglistinfo_ptr)) { ++ kzfree(data); + return -ENOMEM; ++ } + return ret; + } + +@@ -7096,8 +7098,10 @@ static int qseecom_check_whitelist_feature(void) + qseecom.whitelist_support = true; + ret = 0; + } else { +- pr_err("Failed to check whitelist: ret = %d, result = 0x%x\n", ++ pr_info("Check whitelist with ret = %d, result = 0x%x\n", + ret, resp.result); ++ qseecom.whitelist_support = false; ++ ret = 0; + } + kfree(buf); + return ret; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5349/3.patch b/Patches/Linux_CVEs/CVE-2016-5349/3.patch new file mode 100644 index 00000000..052f085f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5349/3.patch @@ -0,0 +1,61 @@ +From 03853a58952834ac3e1e3007c9c680dd4c001a2f Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Thu, 1 Sep 2016 10:20:50 -0700 +Subject: qseecom: allocate sglistinfo buffer for kernel clients + +To support whitelist feature, sglistinfo table should also +be allocated from qseecom kernel APIs used by kernel client. +Besides, initialize sg in __qseecom_update_cmd_buf_64 to +address a static analysis warning. + +Change-Id: I1f1967fd9e95444cca728f09e3e8f4914b2abb95 +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index aa7c8ad..59545f4 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -3845,12 +3845,21 @@ int qseecom_start_app(struct qseecom_handle **handle, + data->client.user_virt_sb_base = 0; + data->client.ihandle = NULL; + ++ /* Allocate sglistinfo buffer for kernel client */ ++ data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL); ++ if (!(data->sglistinfo_ptr)) { ++ kfree(data); ++ kfree(*handle); ++ *handle = NULL; ++ return -ENOMEM; ++ } + init_waitqueue_head(&data->abort_wq); + + data->client.ihandle = ion_alloc(qseecom.ion_clnt, size, 4096, + ION_HEAP(ION_QSECOM_HEAP_ID), 0); + if (IS_ERR_OR_NULL(data->client.ihandle)) { + pr_err("Ion client could not retrieve the handle\n"); ++ kfree(data->sglistinfo_ptr); + kfree(data); + kfree(*handle); + *handle = NULL; +@@ -3948,6 +3957,7 @@ int qseecom_start_app(struct qseecom_handle **handle, + return 0; + + err: ++ kfree(data->sglistinfo_ptr); + kfree(data); + kfree(*handle); + *handle = NULL; +@@ -3989,6 +3999,7 @@ int qseecom_shutdown_app(struct qseecom_handle **handle) + + mutex_unlock(&app_access_lock); + if (ret == 0) { ++ kzfree(data->sglistinfo_ptr); + kzfree(data); + kzfree(*handle); + kzfree(kclient); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5829/0.patch b/Patches/Linux_CVEs/CVE-2016-5829/0.patch new file mode 100644 index 00000000..27ecb6a7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5829/0.patch @@ -0,0 +1,55 @@ +From af37375834fe1dd7a7a08c6042664ffc2a1a3beb Mon Sep 17 00:00:00 2001 +From: Sriharsha Allenki +Date: Thu, 22 Dec 2016 14:57:44 +0530 +Subject: hid: usbhid: Changes to prevent buffer overflow + +Moved some value checks to right positions to prevent +buffer flow, which may be possible before. Previously +these value checks are in an else statement which may +not be executed. + +Change-Id: I02dbecd074183581a6bdae6377097bc004bd3d3c +CRs-fixed: 1102936 +Signed-off-by: Sriharsha Allenki +--- + drivers/hid/usbhid/hiddev.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +(limited to 'drivers/hid/usbhid/hiddev.c') + +diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c +index 2f1ddca..602f163 100644 +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -510,18 +510,19 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, + goto inval; + + field = report->field[uref->field_index]; ++ } + +- if (cmd == HIDIOCGCOLLECTIONINDEX) { +- if (uref->usage_index >= field->maxusage) +- goto inval; +- } else if (uref->usage_index >= field->report_count) ++ if (cmd == HIDIOCGCOLLECTIONINDEX) { ++ if (uref->usage_index >= field->maxusage) + goto inval; ++ } else if (uref->usage_index >= field->report_count) ++ goto inval; + +- else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && +- (uref_multi->num_values > HID_MAX_MULTI_USAGES || +- uref->usage_index + uref_multi->num_values > field->report_count)) +- goto inval; +- } ++ else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && ++ (uref_multi->num_values > HID_MAX_MULTI_USAGES || ++ uref->usage_index + uref_multi->num_values > ++ field->report_count)) ++ goto inval; + + switch (cmd) { + case HIDIOCGUSAGE: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5853/0.patch b/Patches/Linux_CVEs/CVE-2016-5853/0.patch new file mode 100644 index 00000000..633b04f9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5853/0.patch @@ -0,0 +1,35 @@ +From a8f3b894de319718aecfc2ce9c691514696805be Mon Sep 17 00:00:00 2001 +From: kunleiz +Date: Tue, 27 Dec 2016 16:15:51 +0800 +Subject: ASoC: msm: qdsp6v2: DAP: Add check to validate param length + +Return an error code to ensure length value is valid. + +CRs-fixed: 1102987 +Change-Id: I6a679d08342d1da58c20b5c3d4e436dd335764ae +Signed-off-by: kunleiz +--- + sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +index 2441cab..ca6f70f 100644 +--- a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2017, The 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 + * only version 2 as published by the Free Software Foundation. +@@ -1642,6 +1642,7 @@ static int msm_ds2_dap_param_visualizer_control_get(u32 cmd, void *arg) + ret = 0; + dolby_data->length = 0; + pr_err("%s Incorrect VCNB length", __func__); ++ return -EINVAL; + } + + params_length = (2*length + DOLBY_VIS_PARAM_HEADER_SIZE) * +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5854/0.patch b/Patches/Linux_CVEs/CVE-2016-5854/0.patch new file mode 100644 index 00000000..959b62e3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5854/0.patch @@ -0,0 +1,35 @@ +From 28d23d4d7999f683b27b6e0c489635265b67a4c9 Mon Sep 17 00:00:00 2001 +From: Amir Samuelov +Date: Sat, 26 Nov 2016 18:44:06 +0200 +Subject: spcom: check size before calling copy_to_user() + +Calling copy_to_user(to, from, size) with negative value +might cause heap overflow since size is unsigned parameter +and negative value is cast to big unsigned value. + +CRs-Fixed: 1092683 +Change-Id: I9b4a0710aa33942de2976f7ee158a8025dd6a20e +Signed-off-by: Amir Samuelov +--- + drivers/soc/qcom/spcom.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c +index fcdcf0b..7cb538b 100644 +--- a/drivers/soc/qcom/spcom.c ++++ b/drivers/soc/qcom/spcom.c +@@ -2125,6 +2125,11 @@ static ssize_t spcom_device_read(struct file *filp, char __user *user_buff, + return -ENOMEM; + + actual_size = spcom_handle_read(ch, buf, size); ++ if ((actual_size <= 0) || (actual_size > size)) { ++ pr_err("invalid actual_size [%d].\n", actual_size); ++ kfree(buf); ++ return -EFAULT; ++ } + + ret = copy_to_user(user_buff, buf, actual_size); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5855/0.patch b/Patches/Linux_CVEs/CVE-2016-5855/0.patch new file mode 100644 index 00000000..5f744ed8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5855/0.patch @@ -0,0 +1,57 @@ +From a5edb54e93ba85719091fe2bc426d75fa7059834 Mon Sep 17 00:00:00 2001 +From: Amir Samuelov +Date: Tue, 29 Nov 2016 10:58:54 +0200 +Subject: spcom: check user space command size + +The user space spcomlib provides command buffer +for various commands. +Verify that the command buffer size matches the expected +command struct size. + +CRs-Fixed: 1094143 +Change-Id: If3ead54bd03368fa9338921e299b2ad8fb078297 +Signed-off-by: Amir Samuelov +--- + drivers/soc/qcom/spcom.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c +index 0c5f3b8..ebb6b13 100644 +--- a/drivers/soc/qcom/spcom.c ++++ b/drivers/soc/qcom/spcom.c +@@ -1539,13 +1539,18 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch, + struct ion_handle *ion_handle; + int i; + ++ if (size != sizeof(*cmd)) { ++ pr_err("cmd size [%d] , expected [%d].\n", ++ (int) size, (int) sizeof(*cmd)); ++ return -EINVAL; ++ } ++ + /* Check ION client */ + if (spcom_dev->ion_client == NULL) { + pr_err("invalid ion client.\n"); + return -ENODEV; + } + +- + /* Get ION handle from fd - this increments the ref count */ + ion_handle = ion_import_dma_buf(spcom_dev->ion_client, fd); + if (ion_handle == NULL) { +@@ -1591,6 +1596,12 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch, + struct ion_client *ion_client = spcom_dev->ion_client; + int i; + ++ if (size != sizeof(*cmd)) { ++ pr_err("cmd size [%d] , expected [%d].\n", ++ (int) size, (int) sizeof(*cmd)); ++ return -EINVAL; ++ } ++ + /* Check ION client */ + if (ion_client == NULL) { + pr_err("fail to create ion client.\n"); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5856/0.patch b/Patches/Linux_CVEs/CVE-2016-5856/0.patch new file mode 100644 index 00000000..0a7dd488 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5856/0.patch @@ -0,0 +1,57 @@ +From 0c0622914ba53cdcb6e79e85f64bfdf7762c0368 Mon Sep 17 00:00:00 2001 +From: Amir Samuelov +Date: Tue, 6 Dec 2016 16:42:14 +0200 +Subject: spcom: check buf_size validity for user send command + +Check command buf size before allocating kernel buffer. + +CRs-Fixed: 1094078 +Change-Id: Ib03cd8c79966ff35863c1bde99089cac018ab45c +Signed-off-by: Amir Samuelov +--- + drivers/soc/qcom/spcom.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c +index 0c5f3b8..19388f1 100644 +--- a/drivers/soc/qcom/spcom.c ++++ b/drivers/soc/qcom/spcom.c +@@ -1333,6 +1333,16 @@ static int spcom_handle_send_command(struct spcom_channel *ch, + + pr_debug("send req/resp ch [%s] size [%d] .\n", ch->name, size); + ++ /* ++ * check that cmd buf size is at least struct size, ++ * to allow access to struct fields. ++ */ ++ if (size < sizeof(*cmd)) { ++ pr_err("ch [%s] invalid cmd buf.\n", ++ ch->name); ++ return -EINVAL; ++ } ++ + /* Check if remote side connect */ + if (!spcom_is_channel_connected(ch)) { + pr_err("ch [%s] remote side not connect.\n", ch->name); +@@ -1344,6 +1354,18 @@ static int spcom_handle_send_command(struct spcom_channel *ch, + buf_size = cmd->buf_size; + timeout_msec = cmd->timeout_msec; + ++ /* Check param validity */ ++ if (buf_size > SPCOM_MAX_RESPONSE_SIZE) { ++ pr_err("ch [%s] invalid buf size [%d].\n", ++ ch->name, buf_size); ++ return -EINVAL; ++ } ++ if (size != sizeof(*cmd) + buf_size) { ++ pr_err("ch [%s] invalid cmd size [%d].\n", ++ ch->name, size); ++ return -EINVAL; ++ } ++ + /* Allocate Buffers*/ + tx_buf_size = sizeof(*hdr) + buf_size; + tx_buf = kzalloc(tx_buf_size, GFP_KERNEL); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5857/0.patch b/Patches/Linux_CVEs/CVE-2016-5857/0.patch new file mode 100644 index 00000000..1022f527 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5857/0.patch @@ -0,0 +1,83 @@ +From d9d2c405d46ca27b25ed55a8dbd02bd1e633e2d5 Mon Sep 17 00:00:00 2001 +From: Amir Samuelov +Date: Tue, 6 Dec 2016 18:18:16 +0200 +Subject: spcom: check buf size for send modified command + +Check buffer size validity before allocating kernel buffer. + +CRs-Fixed: 1094140 +Change-Id: I8c280b60f316d7bae87644104d18aa7df4af9efe +Signed-off-by: Amir Samuelov +--- + drivers/soc/qcom/spcom.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c +index 0c5f3b8..48f1157 100644 +--- a/drivers/soc/qcom/spcom.c ++++ b/drivers/soc/qcom/spcom.c +@@ -1407,6 +1407,11 @@ static int modify_ion_addr(void *buf, + return -ENODEV; + } + ++ if (buf_size < sizeof(uint64_t)) { ++ pr_err("buf size too small [%d].\n", buf_size); ++ return -ENODEV; ++ } ++ + if (buf_offset > buf_size - sizeof(uint64_t)) { + pr_err("invalid buf_offset [%d].\n", buf_offset); + return -ENODEV; +@@ -1469,6 +1474,16 @@ static int spcom_handle_send_modified_command(struct spcom_channel *ch, + + pr_debug("send req/resp ch [%s] size [%d] .\n", ch->name, size); + ++ /* ++ * check that cmd buf size is at least struct size, ++ * to allow access to struct fields. ++ */ ++ if (size < sizeof(*cmd)) { ++ pr_err("ch [%s] invalid cmd buf.\n", ++ ch->name); ++ return -EINVAL; ++ } ++ + /* Check if remote side connect */ + if (!spcom_is_channel_connected(ch)) { + pr_err("ch [%s] remote side not connect.\n", ch->name); +@@ -1481,6 +1496,18 @@ static int spcom_handle_send_modified_command(struct spcom_channel *ch, + timeout_msec = cmd->timeout_msec; + memcpy(ion_info, cmd->ion_info, sizeof(ion_info)); + ++ /* Check param validity */ ++ if (buf_size > SPCOM_MAX_RESPONSE_SIZE) { ++ pr_err("ch [%s] invalid buf size [%d].\n", ++ ch->name, buf_size); ++ return -EINVAL; ++ } ++ if (size != sizeof(*cmd) + buf_size) { ++ pr_err("ch [%s] invalid cmd size [%d].\n", ++ ch->name, size); ++ return -EINVAL; ++ } ++ + /* Allocate Buffers*/ + tx_buf_size = sizeof(*hdr) + buf_size; + tx_buf = kzalloc(tx_buf_size, GFP_KERNEL); +@@ -1746,6 +1773,13 @@ static int spcom_handle_read_req_resp(struct spcom_channel *ch, + return -ENOTCONN; + } + ++ /* Check param validity */ ++ if (size > SPCOM_MAX_RESPONSE_SIZE) { ++ pr_err("ch [%s] inavlid size [%d].\n", ++ ch->name, size); ++ return -EINVAL; ++ } ++ + /* Allocate Buffers*/ + rx_buf_size = sizeof(*hdr) + size; + rx_buf = kzalloc(rx_buf_size, GFP_KERNEL); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5858/0.patch b/Patches/Linux_CVEs/CVE-2016-5858/0.patch new file mode 100644 index 00000000..d2eacb6f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5858/0.patch @@ -0,0 +1,38 @@ +From 3154eb1d263b9c3eab2c9fa8ebe498390bf5d711 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Mani +Date: Wed, 7 Dec 2016 18:19:31 -0800 +Subject: ASoC: wcd9320: Fix out of bounds for mad input value + +Add check in taiko_mad_input_put function to +return error on out of bounds access using +mad input value + +CRs-fixed: 1096799 +Change-Id: I75ce9e881cf05a50e874a555b2f8bd3286cdaed4 +Signed-off-by: Karthikeyan Mani +--- + sound/soc/codecs/wcd9320.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c +index cb91030..ff199c14e 100644 +--- a/sound/soc/codecs/wcd9320.c ++++ b/sound/soc/codecs/wcd9320.c +@@ -1208,6 +1208,14 @@ static int taiko_mad_input_put(struct snd_kcontrol *kcontrol, + + taiko_mad_input = ucontrol->value.integer.value[0]; + ++ if (taiko_mad_input >= ARRAY_SIZE(taiko_conn_mad_text)) { ++ dev_err(codec->dev, ++ "%s: taiko_mad_input = %d out of bounds\n", ++ __func__, taiko_mad_input); ++ return -EINVAL; ++ } ++ ++ + micb_4_int_reg = taiko->resmgr.reg_addr->micb_4_int_rbias; + pr_debug("%s: taiko_mad_input = %s\n", __func__, + taiko_conn_mad_text[taiko_mad_input]); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5858/1.patch b/Patches/Linux_CVEs/CVE-2016-5858/1.patch new file mode 100644 index 00000000..c7cbeb9e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5858/1.patch @@ -0,0 +1,37 @@ +From afc5bea71bc8f251dad1104568383019f4923af6 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Mani +Date: Wed, 14 Dec 2016 11:33:18 -0800 +Subject: ASoC: wcd9330: Fix out of bounds for mad input value + +Add check in tomtom_mad_input_put function to +return error on out of bounds access using +mad input value + +CRs-fixed: 1096799 +Change-Id: I16f8627b29c7b14a8dc0433b21aa21bf96e98905 +Signed-off-by: Karthikeyan Mani +--- + sound/soc/codecs/wcd9330.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/soc/codecs/wcd9330.c b/sound/soc/codecs/wcd9330.c +index 22f3f85..7fb1096 100644 +--- a/sound/soc/codecs/wcd9330.c ++++ b/sound/soc/codecs/wcd9330.c +@@ -1377,6 +1377,13 @@ static int tomtom_mad_input_put(struct snd_kcontrol *kcontrol, + tomtom_mad_input = ucontrol->value.integer.value[0]; + micb_4_int_reg = tomtom->resmgr.reg_addr->micb_4_int_rbias; + ++ if (tomtom_mad_input >= ARRAY_SIZE(tomtom_conn_mad_text)) { ++ dev_err(codec->dev, ++ "%s: tomtom_mad_input = %d out of bounds\n", ++ __func__, tomtom_mad_input); ++ return -EINVAL; ++ } ++ + pr_debug("%s: tomtom_mad_input = %s\n", __func__, + tomtom_conn_mad_text[tomtom_mad_input]); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5859/0.patch b/Patches/Linux_CVEs/CVE-2016-5859/0.patch new file mode 100644 index 00000000..cc19637b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5859/0.patch @@ -0,0 +1,51 @@ +From 97fdb441a9fb330a76245e473bc1a2155c809ebe Mon Sep 17 00:00:00 2001 +From: Sharad Sangle +Date: Tue, 13 Dec 2016 14:35:39 +0530 +Subject: ASoC: msm: qdsp6v2: DAP: Add check to validate param length + +To avoid buffer overflow, validate input length used to +fetch visualizer data. + +CRs-fixed: 1096672 +Change-Id: I224bc2f20d94182713c565972fb0bd52cad6f3fd +Signed-off-by: Sharad Sangle +--- + sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +index bb0f890..5866e46 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2014, 2016, The 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 + * only version 2 as published by the Free Software Foundation. +@@ -18,6 +18,10 @@ + + #include "msm-dolby-dap-config.h" + ++#ifndef DOLBY_PARAM_VCNB_MAX_LENGTH ++#define DOLBY_PARAM_VCNB_MAX_LENGTH 40 ++#endif ++ + /* dolby endp based parameters */ + struct dolby_dap_endp_params_s { + int device; +@@ -896,6 +900,11 @@ int msm_dolby_dap_param_visualizer_control_get(struct snd_kcontrol *kcontrol, + uint32_t param_payload_len = + DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t); + int port_id, copp_idx, idx; ++ if (length > DOLBY_PARAM_VCNB_MAX_LENGTH || length <= 0) { ++ pr_err("%s Incorrect VCNB length", __func__); ++ ucontrol->value.integer.value[0] = 0; ++ return -EINVAL; ++ } + for (idx = 0; idx < AFE_MAX_PORTS; idx++) { + port_id = dolby_dap_params_states.port_id[idx]; + copp_idx = dolby_dap_params_states.copp_idx[idx]; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5860/0.patch b/Patches/Linux_CVEs/CVE-2016-5860/0.patch new file mode 100644 index 00000000..c005480c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5860/0.patch @@ -0,0 +1,36 @@ +From 9f91ae0d7203714fc39ae78e1f1c4fd71ed40498 Mon Sep 17 00:00:00 2001 +From: Karthik Reddy Katta +Date: Wed, 28 Dec 2016 11:24:33 +0530 +Subject: drivers: soc: qcom: Add overflow check for sound model size + +Overflow check is added for sound model size to prevent +heap overflow while allocating memory for sound model data. + +CRs-Fixed: 1100682 +Change-Id: Id38523a5e79028c692670e84d5fe924a855a5a10 +Signed-off-by: Karthik Reddy Katta +--- + sound/soc/msm/msm-cpe-lsm.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c +index ef4c9b0..5b90cc1 100644 +--- a/sound/soc/msm/msm-cpe-lsm.c ++++ b/sound/soc/msm/msm-cpe-lsm.c +@@ -1878,6 +1878,13 @@ static int msm_cpe_lsm_reg_model(struct snd_pcm_substream *substream, + + lsm_ops->lsm_get_snd_model_offset(cpe->core_handle, + session, &offset); ++ /* Check if 'p_info->param_size + offset' crosses U32_MAX. */ ++ if (p_info->param_size > U32_MAX - offset) { ++ dev_err(rtd->dev, ++ "%s: Invalid param_size %d\n", ++ __func__, p_info->param_size); ++ return -EINVAL; ++ } + session->snd_model_size = p_info->param_size + offset; + + session->snd_model_data = vzalloc(session->snd_model_size); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5861/0.patch b/Patches/Linux_CVEs/CVE-2016-5861/0.patch new file mode 100644 index 00000000..b764d960 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5861/0.patch @@ -0,0 +1,40 @@ +From cf3c97b8b6165f13810e530068fbf94b07f1f77d Mon Sep 17 00:00:00 2001 +From: Ping Li +Date: Tue, 3 Jan 2017 11:48:06 -0800 +Subject: msm: mdss: Add sanity check for Gamut LUT size + +The Gamut LUT size passed from user space needs to go through +a sanity check to avoid heap overflow. This patch adds the missing +sanity check in the Gamut LUT config write path. + +Change-Id: I365938e06dbc6ca01961c9be01db10a5a9c863e4 +Signed-off-by: Ping Li +--- + drivers/video/fbdev/msm/mdss_mdp_pp.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c +index 30dd3c8..951beae 100644 +--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c ++++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -4827,6 +4827,11 @@ gamut_clk_off: + goto gamut_set_dirty; + } + } ++ if (pp_gm_has_invalid_lut_size(config)) { ++ pr_debug("invalid lut size for gamut\n"); ++ ret = -EINVAL; ++ goto gamut_config_exit; ++ } + local_cfg = *config; + tbl_off = mdss_pp_res->gamut_tbl[disp_num]; + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5861/1.patch b/Patches/Linux_CVEs/CVE-2016-5861/1.patch new file mode 100644 index 00000000..ae7652aa --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5861/1.patch @@ -0,0 +1,34 @@ +From 17b37501db36fb1723e31ea17961b66df7432fc7 Mon Sep 17 00:00:00 2001 +From: Ping Li +Date: Tue, 3 Jan 2017 13:19:32 -0800 +Subject: msm: mdss: Add sanity check for Gamut LUT size + +The Gamut LUT size passed from user space needs to go through +a sanity check to avoid heap overflow. This patch adds the missing +sanity check in the Gamut LUT config write path. + +Change-Id: I365938e06dbc6ca01961c9be01db10a5a9c863e4 +Signed-off-by: Ping Li +--- + drivers/video/msm/mdss/mdss_mdp_pp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c +index 3960595..029fad1 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_pp.c ++++ b/drivers/video/msm/mdss/mdss_mdp_pp.c +@@ -4671,6 +4671,11 @@ gamut_clk_off: + goto gamut_set_dirty; + } + } ++ if (pp_gm_has_invalid_lut_size(config)) { ++ pr_err("invalid lut size for gamut\n"); ++ ret = -EINVAL; ++ goto gamut_config_exit; ++ } + local_cfg = *config; + tbl_off = mdss_pp_res->gamut_tbl[disp_num]; + for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5861/2.patch b/Patches/Linux_CVEs/CVE-2016-5861/2.patch new file mode 100644 index 00000000..912d44a7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5861/2.patch @@ -0,0 +1,78 @@ +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/Linux_CVEs/CVE-2016-5862/0.patch b/Patches/Linux_CVEs/CVE-2016-5862/0.patch new file mode 100644 index 00000000..cfff207a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5862/0.patch @@ -0,0 +1,31 @@ +From 4199451e83729a3add781eeafaee32994ff65b04 Mon Sep 17 00:00:00 2001 +From: Aditya Bavanari +Date: Thu, 22 Dec 2016 16:41:27 +0530 +Subject: ASoC: msm8996: Fix kernel crash in "Speaker Function" mixer control + +Use snd_soc_kcontrol_codec instead of snd_kcontrol_chip +to obtain the codec information from the kcontrol. + +CRs-Fixed: 1099607 +Change-Id: Iba3004c2745e5f0bbe778e44c803826351b3b939 +Signed-off-by: Aditya Bavanari +--- + sound/soc/msm/msm8996.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/msm/msm8996.c b/sound/soc/msm/msm8996.c +index 84d4ede..4eafd32 100644 +--- a/sound/soc/msm/msm8996.c ++++ b/sound/soc/msm/msm8996.c +@@ -351,7 +351,7 @@ static int msm8996_get_spk(struct snd_kcontrol *kcontrol, + static int msm8996_set_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { +- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + + pr_debug("%s() ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5863/0.patch b/Patches/Linux_CVEs/CVE-2016-5863/0.patch new file mode 100644 index 00000000..53e70f2e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5863/0.patch @@ -0,0 +1,53 @@ +From daf0acd54a6a80de227baef9a06285e4aa5f8c93 Mon Sep 17 00:00:00 2001 +From: Sriharsha Allenki +Date: Thu, 22 Dec 2016 14:57:44 +0530 +Subject: hid: usbhid: Changes to prevent buffer overflow + +Moved some value checks to right positions to prevent +buffer flow, which may be possible before. Previously +these value checks are in an else statement which may +not be executed. + +Change-Id: I02dbecd074183581a6bdae6377097bc004bd3d3c +CRs-fixed: 1102936 +Signed-off-by: Sriharsha Allenki +--- + drivers/hid/usbhid/hiddev.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c +index 2f1ddca..602f163 100644 +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -510,18 +510,19 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, + goto inval; + + field = report->field[uref->field_index]; ++ } + +- if (cmd == HIDIOCGCOLLECTIONINDEX) { +- if (uref->usage_index >= field->maxusage) +- goto inval; +- } else if (uref->usage_index >= field->report_count) ++ if (cmd == HIDIOCGCOLLECTIONINDEX) { ++ if (uref->usage_index >= field->maxusage) + goto inval; ++ } else if (uref->usage_index >= field->report_count) ++ goto inval; + +- else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && +- (uref_multi->num_values > HID_MAX_MULTI_USAGES || +- uref->usage_index + uref_multi->num_values > field->report_count)) +- goto inval; +- } ++ else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && ++ (uref_multi->num_values > HID_MAX_MULTI_USAGES || ++ uref->usage_index + uref_multi->num_values > ++ field->report_count)) ++ goto inval; + + switch (cmd) { + case HIDIOCGUSAGE: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5864/0.patch b/Patches/Linux_CVEs/CVE-2016-5864/0.patch new file mode 100644 index 00000000..b8fbce6c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5864/0.patch @@ -0,0 +1,132 @@ +From cbc21ceb69cb7bca0643423a7ca982abce3ce50a Mon Sep 17 00:00:00 2001 +From: Vidyakumar Athota +Date: Wed, 4 Jan 2017 13:32:50 -0800 +Subject: soc: qcom: check userspace buffer size in write() + +Add checks to make sure userspace buffer is valid before +it is used. Add upper limit for glink channels and number +of intents allowed. + +Change-Id: I9b8f2e47aada7922ba22cbb010176bf36a9d6288 +Signed-off-by: Vidyakumar Athota +--- + drivers/soc/qcom/wcd-dsp-glink.c | 51 ++++++++++++++++++++++++++++++++-------- + 1 file changed, 41 insertions(+), 10 deletions(-) + +diff --git a/drivers/soc/qcom/wcd-dsp-glink.c b/drivers/soc/qcom/wcd-dsp-glink.c +index 27e66dc..1ceded4 100644 +--- a/drivers/soc/qcom/wcd-dsp-glink.c ++++ b/drivers/soc/qcom/wcd-dsp-glink.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2016-2017, The 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 +@@ -25,8 +25,10 @@ + #include "sound/wcd-dsp-glink.h" + + #define WDSP_GLINK_DRIVER_NAME "wcd-dsp-glink" +-#define WDSP_MAX_WRITE_SIZE (512 * 1024) ++#define WDSP_MAX_WRITE_SIZE (256 * 1024) + #define WDSP_MAX_READ_SIZE (4 * 1024) ++#define WDSP_MAX_NO_OF_INTENTS (20) ++#define WDSP_MAX_NO_OF_CHANNELS (10) + + #define MINOR_NUMBER_COUNT 1 + #define WDSP_EDGE "wdsp" +@@ -532,15 +534,30 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv, + payload = (u8 *)pkt->payload; + no_of_channels = pkt->no_of_channels; + ++ if (no_of_channels > WDSP_MAX_NO_OF_CHANNELS) { ++ dev_info(wpriv->dev, "%s: no_of_channels = %d are limited to %d\n", ++ __func__, no_of_channels, WDSP_MAX_NO_OF_CHANNELS); ++ no_of_channels = WDSP_MAX_NO_OF_CHANNELS; ++ } + ch = kcalloc(no_of_channels, sizeof(struct wdsp_glink_ch *), + GFP_KERNEL); + if (!ch) { + ret = -ENOMEM; + goto done; + } ++ wpriv->ch = ch; ++ wpriv->no_of_channels = no_of_channels; + + for (i = 0; i < no_of_channels; i++) { + ch_cfg = (struct wdsp_glink_ch_cfg *)payload; ++ ++ if (ch_cfg->no_of_intents > WDSP_MAX_NO_OF_INTENTS) { ++ dev_err(wpriv->dev, "%s: Invalid no_of_intents = %d\n", ++ __func__, ch_cfg->no_of_intents); ++ ret = -EINVAL; ++ goto err_ch_mem; ++ } ++ + ch_cfg_size = sizeof(struct wdsp_glink_ch_cfg) + + (sizeof(u32) * ch_cfg->no_of_intents); + ch_size = sizeof(struct wdsp_glink_ch) + +@@ -564,8 +581,6 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv, + INIT_WORK(&ch[i]->lcl_ch_cls_wrk, wdsp_glink_lcl_ch_cls_wrk); + init_waitqueue_head(&ch[i]->ch_connect_wait); + } +- wpriv->ch = ch; +- wpriv->no_of_channels = no_of_channels; + + INIT_WORK(&wpriv->ch_open_cls_wrk, wdsp_glink_ch_open_cls_wrk); + +@@ -746,15 +761,17 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf, + goto done; + } + +- dev_dbg(wpriv->dev, "%s: count = %zd\n", __func__, count); +- +- if (count > WDSP_MAX_WRITE_SIZE) { +- dev_info(wpriv->dev, "%s: count = %zd is more than WDSP_MAX_WRITE_SIZE\n", ++ if ((count < sizeof(struct wdsp_write_pkt)) || ++ (count > WDSP_MAX_WRITE_SIZE)) { ++ dev_err(wpriv->dev, "%s: Invalid count = %zd\n", + __func__, count); +- count = WDSP_MAX_WRITE_SIZE; ++ ret = -EINVAL; ++ goto done; + } + +- tx_buf_size = count + sizeof(struct wdsp_glink_tx_buf); ++ dev_dbg(wpriv->dev, "%s: count = %zd\n", __func__, count); ++ ++ tx_buf_size = WDSP_MAX_WRITE_SIZE + sizeof(struct wdsp_glink_tx_buf); + tx_buf = kzalloc(tx_buf_size, GFP_KERNEL); + if (!tx_buf) { + ret = -ENOMEM; +@@ -772,6 +789,13 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf, + wpkt = (struct wdsp_write_pkt *)tx_buf->buf; + switch (wpkt->pkt_type) { + case WDSP_REG_PKT: ++ if (count <= (sizeof(struct wdsp_write_pkt) + ++ sizeof(struct wdsp_reg_pkt))) { ++ dev_err(wpriv->dev, "%s: Invalid reg pkt size = %zd\n", ++ __func__, count); ++ ret = -EINVAL; ++ goto free_buf; ++ } + ret = wdsp_glink_ch_info_init(wpriv, + (struct wdsp_reg_pkt *)wpkt->payload); + if (IS_ERR_VALUE(ret)) +@@ -794,6 +818,13 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf, + kfree(tx_buf); + break; + case WDSP_CMD_PKT: ++ if (count <= (sizeof(struct wdsp_write_pkt) + ++ sizeof(struct wdsp_cmd_pkt))) { ++ dev_err(wpriv->dev, "%s: Invalid cmd pkt size = %zd\n", ++ __func__, count); ++ ret = -EINVAL; ++ goto free_buf; ++ } + mutex_lock(&wpriv->glink_mutex); + if (wpriv->glink_state.link_state == GLINK_LINK_STATE_DOWN) { + mutex_unlock(&wpriv->glink_mutex); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5867/0.patch b/Patches/Linux_CVEs/CVE-2016-5867/0.patch new file mode 100644 index 00000000..2d7611f0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5867/0.patch @@ -0,0 +1,51 @@ +From 065360da7147003aed8f59782b7652d565f56be5 Mon Sep 17 00:00:00 2001 +From: Sharad Sangle +Date: Mon, 19 Dec 2016 17:00:25 +0530 +Subject: ASoC: msm: qdsp6v2: DAP: Add check to validate param length + +To avoid buffer overflow, validate input length used to +set Dolby params. + +Change-Id: I3f9d6040f118f63b60c20c83b0d8cae638f4a530 +CRs-Fixed: 1095947 +Signed-off-by: Sharad Sangle +--- + sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +index 5866e46..d270b3d 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +@@ -681,7 +681,7 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { + int rc = 0, port_id, copp_idx; +- uint32_t idx, j; ++ uint32_t idx, j, current_offset; + uint32_t device = ucontrol->value.integer.value[0]; + uint32_t param_id = ucontrol->value.integer.value[1]; + uint32_t offset = ucontrol->value.integer.value[2]; +@@ -758,6 +758,19 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol, + default: { + /* cache the parameters */ + dolby_dap_params_modified[idx] += 1; ++ current_offset = dolby_dap_params_offset[idx] + offset; ++ if (current_offset >= TOTAL_LENGTH_DOLBY_PARAM) { ++ pr_err("%s: invalid offset %d at idx %d\n", ++ __func__, offset, idx); ++ return -EINVAL; ++ } ++ if ((0 == length) || (current_offset + length - 1 ++ < current_offset) || (current_offset + length ++ > TOTAL_LENGTH_DOLBY_PARAM)) { ++ pr_err("%s: invalid length %d at idx %d\n", ++ __func__, length, idx); ++ return -EINVAL; ++ } + dolby_dap_params_length[idx] = length; + pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n", + __func__, device, param_id, offset, length); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5868/0.patch b/Patches/Linux_CVEs/CVE-2016-5868/0.patch new file mode 100644 index 00000000..fc860b4f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5868/0.patch @@ -0,0 +1,525 @@ +From fbb765a3f813f5cc85ddab21487fd65f24bf6a8c Mon Sep 17 00:00:00 2001 +From: Ghanim Fodi +Date: Tue, 27 Dec 2016 13:32:35 +0200 +Subject: msm: rndis_ipa: Remove rndis_ipa loopback functionality + +Rndis_ipa loopback functionality at rndis_ipa driver +is a debug functionality that is not used. + +Change-Id: Ibbcb26d3871cffeb46b028efcf4d428e88eb9e10 +CRs-fixed: 1104431 +Signed-off-by: Ghanim Fodi +--- + drivers/net/ethernet/msm/rndis_ipa.c | 432 +---------------------------------- + 1 file changed, 1 insertion(+), 431 deletions(-) + +diff --git a/drivers/net/ethernet/msm/rndis_ipa.c b/drivers/net/ethernet/msm/rndis_ipa.c +index 15cfb1d..62e72ca 100644 +--- a/drivers/net/ethernet/msm/rndis_ipa.c ++++ b/drivers/net/ethernet/msm/rndis_ipa.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2017, The 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 +@@ -135,29 +135,6 @@ enum rndis_ipa_operation { + RNDIS_IPA_DEBUG("Driver state: %s\n",\ + rndis_ipa_state_string(ctx->state)); + +-/** +- * struct rndis_loopback_pipe - hold all information needed for +- * pipe loopback logic +- */ +-struct rndis_loopback_pipe { +- struct sps_pipe *ipa_sps; +- struct ipa_sps_params ipa_sps_connect; +- struct ipa_connect_params ipa_connect_params; +- +- struct sps_pipe *dma_sps; +- struct sps_connect dma_connect; +- +- struct sps_alloc_dma_chan dst_alloc; +- struct sps_dma_chan ipa_sps_channel; +- enum sps_mode mode; +- u32 ipa_peer_bam_hdl; +- u32 peer_pipe_index; +- u32 ipa_drv_ep_hdl; +- u32 ipa_pipe_index; +- enum ipa_client_type ipa_client; +- ipa_notify_cb ipa_callback; +- struct ipa_ep_cfg *ipa_ep_cfg; +-}; + + /** + * struct rndis_ipa_dev - main driver context parameters +@@ -172,13 +149,9 @@ struct rndis_loopback_pipe { + * @rx_dump_enable: dump all Rx packets + * @icmp_filter: allow all ICMP packet to pass through the filters + * @rm_enable: flag that enable/disable Resource manager request prior to Tx +- * @loopback_enable: flag that enable/disable USB stub loopback + * @deaggregation_enable: enable/disable IPA HW deaggregation logic + * @during_xmit_error: flags that indicate that the driver is in a middle + * of error handling in Tx path +- * @usb_to_ipa_loopback_pipe: usb to ipa (Rx) pipe representation for loopback +- * @ipa_to_usb_loopback_pipe: ipa to usb (Tx) pipe representation for loopback +- * @bam_dma_hdl: handle representing bam-dma, used for loopback logic + * @directory: holds all debug flags used by the driver to allow cleanup + * for driver unload + * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table +@@ -208,12 +181,8 @@ struct rndis_ipa_dev { + bool rx_dump_enable; + bool icmp_filter; + bool rm_enable; +- bool loopback_enable; + bool deaggregation_enable; + bool during_xmit_error; +- struct rndis_loopback_pipe usb_to_ipa_loopback_pipe; +- struct rndis_loopback_pipe ipa_to_usb_loopback_pipe; +- u32 bam_dma_hdl; + struct dentry *directory; + uint32_t eth_ipv4_hdr_hdl; + uint32_t eth_ipv6_hdr_hdl; +@@ -277,31 +246,12 @@ static int resource_request(struct rndis_ipa_dev *rndis_ipa_ctx); + static void resource_release(struct rndis_ipa_dev *rndis_ipa_ctx); + static netdev_tx_t rndis_ipa_start_xmit(struct sk_buff *skb, + struct net_device *net); +-static int rndis_ipa_loopback_pipe_create( +- struct rndis_ipa_dev *rndis_ipa_ctx, +- struct rndis_loopback_pipe *loopback_pipe); +-static void rndis_ipa_destroy_loopback_pipe( +- struct rndis_loopback_pipe *loopback_pipe); +-static int rndis_ipa_create_loopback(struct rndis_ipa_dev *rndis_ipa_ctx); +-static void rndis_ipa_destroy_loopback(struct rndis_ipa_dev *rndis_ipa_ctx); +-static int rndis_ipa_setup_loopback(bool enable, +- struct rndis_ipa_dev *rndis_ipa_ctx); +-static int rndis_ipa_debugfs_loopback_open(struct inode *inode, +- struct file *file); + static int rndis_ipa_debugfs_atomic_open(struct inode *inode, + struct file *file); + static int rndis_ipa_debugfs_aggr_open(struct inode *inode, + struct file *file); + static ssize_t rndis_ipa_debugfs_aggr_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos); +-static ssize_t rndis_ipa_debugfs_loopback_write(struct file *file, +- const char __user *buf, size_t count, loff_t *ppos); +-static ssize_t rndis_ipa_debugfs_enable_write(struct file *file, +- const char __user *buf, size_t count, loff_t *ppos); +-static ssize_t rndis_ipa_debugfs_enable_read(struct file *file, +- char __user *ubuf, size_t count, loff_t *ppos); +-static ssize_t rndis_ipa_debugfs_loopback_read(struct file *file, +- char __user *ubuf, size_t count, loff_t *ppos); + static ssize_t rndis_ipa_debugfs_atomic_read(struct file *file, + char __user *ubuf, size_t count, loff_t *ppos); + static void rndis_ipa_dump_skb(struct sk_buff *skb); +@@ -336,12 +286,6 @@ const struct file_operations rndis_ipa_debugfs_atomic_ops = { + .read = rndis_ipa_debugfs_atomic_read, + }; + +-const struct file_operations rndis_ipa_loopback_ops = { +- .open = rndis_ipa_debugfs_loopback_open, +- .read = rndis_ipa_debugfs_loopback_read, +- .write = rndis_ipa_debugfs_loopback_write, +-}; +- + const struct file_operations rndis_ipa_aggr_ops = { + .open = rndis_ipa_debugfs_aggr_open, + .write = rndis_ipa_debugfs_aggr_write, +@@ -2195,14 +2139,6 @@ static int rndis_ipa_debugfs_init(struct rndis_ipa_dev *rndis_ipa_ctx) + goto fail_file; + } + +- file = debugfs_create_file("loopback_enable", flags_read_write, +- rndis_ipa_ctx->directory, +- rndis_ipa_ctx, &rndis_ipa_loopback_ops); +- if (!file) { +- RNDIS_IPA_ERROR("could not create outstanding file\n"); +- goto fail_file; +- } +- + file = debugfs_create_u8("state", flags_read_only, + rndis_ipa_ctx->directory, (u8 *)&rndis_ipa_ctx->state); + if (!file) { +@@ -2358,59 +2294,6 @@ static ssize_t rndis_ipa_debugfs_aggr_write(struct file *file, + return count; + } + +-static int rndis_ipa_debugfs_loopback_open(struct inode *inode, +- struct file *file) +-{ +- struct rndis_ipa_dev *rndis_ipa_ctx = inode->i_private; +- file->private_data = rndis_ipa_ctx; +- +- return 0; +-} +- +-static ssize_t rndis_ipa_debugfs_loopback_read(struct file *file, +- char __user *ubuf, size_t count, loff_t *ppos) +-{ +- int cnt; +- struct rndis_ipa_dev *rndis_ipa_ctx = file->private_data; +- +- file->private_data = &rndis_ipa_ctx->loopback_enable; +- +- cnt = rndis_ipa_debugfs_enable_read(file, +- ubuf, count, ppos); +- +- return cnt; +-} +- +-static ssize_t rndis_ipa_debugfs_loopback_write(struct file *file, +- const char __user *buf, size_t count, loff_t *ppos) +-{ +- int retval; +- int cnt; +- struct rndis_ipa_dev *rndis_ipa_ctx = file->private_data; +- bool old_state = rndis_ipa_ctx->loopback_enable; +- +- file->private_data = &rndis_ipa_ctx->loopback_enable; +- +- cnt = rndis_ipa_debugfs_enable_write(file, +- buf, count, ppos); +- +- RNDIS_IPA_DEBUG("loopback_enable was set to:%d->%d\n", +- old_state, rndis_ipa_ctx->loopback_enable); +- +- if (old_state == rndis_ipa_ctx->loopback_enable) { +- RNDIS_IPA_ERROR("NOP - same state\n"); +- return cnt; +- } +- +- retval = rndis_ipa_setup_loopback( +- rndis_ipa_ctx->loopback_enable, +- rndis_ipa_ctx); +- if (retval) +- rndis_ipa_ctx->loopback_enable = old_state; +- +- return cnt; +-} +- + static int rndis_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) + { + struct rndis_ipa_dev *rndis_ipa_ctx = inode->i_private; +@@ -2441,319 +2324,6 @@ static ssize_t rndis_ipa_debugfs_atomic_read(struct file *file, + return simple_read_from_buffer(ubuf, count, ppos, atomic_str, nbytes); + } + +-static ssize_t rndis_ipa_debugfs_enable_read(struct file *file, +- char __user *ubuf, size_t count, loff_t *ppos) +-{ +- int nbytes; +- int size = 0; +- int ret; +- loff_t pos; +- u8 enable_str[sizeof(char)*3] = {0}; +- bool *enable = file->private_data; +- pos = *ppos; +- nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); +- ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); +- if (ret < 0) { +- RNDIS_IPA_ERROR("simple_read_from_buffer problem\n"); +- return ret; +- } +- size += ret; +- count -= nbytes; +- *ppos = pos + size; +- return size; +-} +- +-static ssize_t rndis_ipa_debugfs_enable_write(struct file *file, +- const char __user *buf, size_t count, loff_t *ppos) +-{ +- unsigned long missing; +- char input; +- bool *enable = file->private_data; +- if (count != sizeof(input) + 1) { +- RNDIS_IPA_ERROR("wrong input length(%zd)\n", count); +- return -EINVAL; +- } +- if (!buf) { +- RNDIS_IPA_ERROR("Bad argument\n"); +- return -EINVAL; +- } +- missing = copy_from_user(&input, buf, 1); +- if (missing) +- return -EFAULT; +- RNDIS_IPA_DEBUG("input received %c\n", input); +- *enable = input - '0'; +- RNDIS_IPA_DEBUG("value was set to %d\n", *enable); +- return count; +-} +- +-/** +- * Connects IPA->BAMDMA +- * This shall simulate the path from IPA to USB +- * Allowing the driver TX path +- */ +-static int rndis_ipa_loopback_pipe_create( +- struct rndis_ipa_dev *rndis_ipa_ctx, +- struct rndis_loopback_pipe *loopback_pipe) +-{ +- int retval; +- +- RNDIS_IPA_LOG_ENTRY(); +- +- /* SPS pipe has two side handshake +- * This is the first handshake of IPA->BAMDMA, +- * This is the IPA side +- */ +- loopback_pipe->ipa_connect_params.client = loopback_pipe->ipa_client; +- loopback_pipe->ipa_connect_params.client_bam_hdl = +- rndis_ipa_ctx->bam_dma_hdl; +- loopback_pipe->ipa_connect_params.client_ep_idx = +- loopback_pipe->peer_pipe_index; +- loopback_pipe->ipa_connect_params.desc_fifo_sz = BAM_DMA_DESC_FIFO_SIZE; +- loopback_pipe->ipa_connect_params.data_fifo_sz = BAM_DMA_DATA_FIFO_SIZE; +- loopback_pipe->ipa_connect_params.notify = loopback_pipe->ipa_callback; +- loopback_pipe->ipa_connect_params.priv = rndis_ipa_ctx; +- loopback_pipe->ipa_connect_params.ipa_ep_cfg = +- *(loopback_pipe->ipa_ep_cfg); +- +- /* loopback_pipe->ipa_sps_connect is out param */ +- retval = ipa_connect(&loopback_pipe->ipa_connect_params, +- &loopback_pipe->ipa_sps_connect, +- &loopback_pipe->ipa_drv_ep_hdl); +- if (retval) { +- RNDIS_IPA_ERROR("ipa_connect() fail (%d)", retval); +- return retval; +- } +- RNDIS_IPA_DEBUG("ipa_connect() succeeded, ipa_drv_ep_hdl=%d", +- loopback_pipe->ipa_drv_ep_hdl); +- +- /* SPS pipe has two side handshake +- * This is the second handshake of IPA->BAMDMA, +- * This is the BAMDMA side +- */ +- loopback_pipe->dma_sps = sps_alloc_endpoint(); +- if (!loopback_pipe->dma_sps) { +- RNDIS_IPA_ERROR("sps_alloc_endpoint() failed "); +- retval = -ENOMEM; +- goto fail_sps_alloc; +- } +- +- retval = sps_get_config(loopback_pipe->dma_sps, +- &loopback_pipe->dma_connect); +- if (retval) { +- RNDIS_IPA_ERROR("sps_get_config() failed (%d)", retval); +- goto fail_get_cfg; +- } +- +- /* Start setting the non IPA ep for SPS driver*/ +- loopback_pipe->dma_connect.mode = loopback_pipe->mode; +- +- /* SPS_MODE_DEST: DMA end point is the dest (consumer) IPA->DMA */ +- if (loopback_pipe->mode == SPS_MODE_DEST) { +- +- loopback_pipe->dma_connect.source = +- loopback_pipe->ipa_sps_connect.ipa_bam_hdl; +- loopback_pipe->dma_connect.src_pipe_index = +- loopback_pipe->ipa_sps_connect.ipa_ep_idx; +- loopback_pipe->dma_connect.destination = +- rndis_ipa_ctx->bam_dma_hdl; +- loopback_pipe->dma_connect.dest_pipe_index = +- loopback_pipe->peer_pipe_index; +- +- /* SPS_MODE_SRC: DMA end point is the source (producer) DMA->IPA */ +- } else { +- +- loopback_pipe->dma_connect.source = +- rndis_ipa_ctx->bam_dma_hdl; +- loopback_pipe->dma_connect.src_pipe_index = +- loopback_pipe->peer_pipe_index; +- loopback_pipe->dma_connect.destination = +- loopback_pipe->ipa_sps_connect.ipa_bam_hdl; +- loopback_pipe->dma_connect.dest_pipe_index = +- loopback_pipe->ipa_sps_connect.ipa_ep_idx; +- +- } +- +- loopback_pipe->dma_connect.desc = loopback_pipe->ipa_sps_connect.desc; +- loopback_pipe->dma_connect.data = loopback_pipe->ipa_sps_connect.data; +- loopback_pipe->dma_connect.event_thresh = 0x10; +- /* BAM-to-BAM */ +- loopback_pipe->dma_connect.options = SPS_O_AUTO_ENABLE; +- +- RNDIS_IPA_DEBUG("doing sps_connect() with - "); +- RNDIS_IPA_DEBUG("src bam_hdl:0x%lx, src_pipe#:%d", +- loopback_pipe->dma_connect.source, +- loopback_pipe->dma_connect.src_pipe_index); +- RNDIS_IPA_DEBUG("dst bam_hdl:0x%lx, dst_pipe#:%d", +- loopback_pipe->dma_connect.destination, +- loopback_pipe->dma_connect.dest_pipe_index); +- +- retval = sps_connect(loopback_pipe->dma_sps, +- &loopback_pipe->dma_connect); +- if (retval) { +- RNDIS_IPA_ERROR("sps_connect() fail for BAMDMA side (%d)", +- retval); +- goto fail_sps_connect; +- } +- +- RNDIS_IPA_LOG_EXIT(); +- +- return 0; +- +-fail_sps_connect: +-fail_get_cfg: +- sps_free_endpoint(loopback_pipe->dma_sps); +-fail_sps_alloc: +- ipa_disconnect(loopback_pipe->ipa_drv_ep_hdl); +- return retval; +-} +- +-static void rndis_ipa_destroy_loopback_pipe( +- struct rndis_loopback_pipe *loopback_pipe) +-{ +- sps_disconnect(loopback_pipe->dma_sps); +- sps_free_endpoint(loopback_pipe->dma_sps); +-} +- +-/** +- * rndis_ipa_create_loopback() - create a BAM-DMA loopback +- * in order to replace the USB core +- */ +-static int rndis_ipa_create_loopback(struct rndis_ipa_dev *rndis_ipa_ctx) +-{ +- /* The BAM handle should be use as +- * source/destination in the sps_connect() +- */ +- int retval; +- +- RNDIS_IPA_LOG_ENTRY(); +- +- +- retval = sps_ctrl_bam_dma_clk(true); +- if (retval) { +- RNDIS_IPA_ERROR("fail on enabling BAM-DMA clocks"); +- return -ENODEV; +- } +- +- /* Get BAM handle instead of USB handle */ +- rndis_ipa_ctx->bam_dma_hdl = sps_dma_get_bam_handle(); +- if (!rndis_ipa_ctx->bam_dma_hdl) { +- RNDIS_IPA_ERROR("sps_dma_get_bam_handle() failed"); +- return -ENODEV; +- } +- RNDIS_IPA_DEBUG("sps_dma_get_bam_handle() succeeded (0x%x)", +- rndis_ipa_ctx->bam_dma_hdl); +- +- /* IPA<-BAMDMA, NetDev Rx path (BAMDMA is the USB stub) */ +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_client = +- IPA_CLIENT_USB_PROD; +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.peer_pipe_index = +- FROM_USB_TO_IPA_BAMDMA; +- /*DMA EP mode*/ +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.mode = SPS_MODE_SRC; +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_ep_cfg = +- &usb_to_ipa_ep_cfg_deaggr_en; +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_callback = +- rndis_ipa_packet_receive_notify; +- RNDIS_IPA_DEBUG("setting up IPA<-BAMDAM pipe (RNDIS_IPA RX path)"); +- retval = rndis_ipa_loopback_pipe_create(rndis_ipa_ctx, +- &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); +- if (retval) { +- RNDIS_IPA_ERROR("fail to close IPA->BAMDAM pipe"); +- goto fail_to_usb; +- } +- RNDIS_IPA_DEBUG("IPA->BAMDAM pipe successfully connected (TX path)"); +- +- /* IPA->BAMDMA, NetDev Tx path (BAMDMA is the USB stub)*/ +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_client = +- IPA_CLIENT_USB_CONS; +- /*DMA EP mode*/ +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.mode = SPS_MODE_DEST; +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_ep_cfg = &ipa_to_usb_ep_cfg; +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.peer_pipe_index = +- FROM_IPA_TO_USB_BAMDMA; +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_callback = +- rndis_ipa_tx_complete_notify; +- RNDIS_IPA_DEBUG("setting up IPA->BAMDAM pipe (RNDIS_IPA TX path)"); +- retval = rndis_ipa_loopback_pipe_create(rndis_ipa_ctx, +- &rndis_ipa_ctx->ipa_to_usb_loopback_pipe); +- if (retval) { +- RNDIS_IPA_ERROR("fail to close IPA<-BAMDAM pipe"); +- goto fail_from_usb; +- } +- RNDIS_IPA_DEBUG("IPA<-BAMDAM pipe successfully connected(RX path)"); +- +- RNDIS_IPA_LOG_EXIT(); +- +- return 0; +- +-fail_from_usb: +- rndis_ipa_destroy_loopback_pipe( +- &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); +-fail_to_usb: +- +- return retval; +-} +- +-static void rndis_ipa_destroy_loopback(struct rndis_ipa_dev *rndis_ipa_ctx) +-{ +- rndis_ipa_destroy_loopback_pipe( +- &rndis_ipa_ctx->ipa_to_usb_loopback_pipe); +- rndis_ipa_destroy_loopback_pipe( +- &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); +- sps_dma_free_bam_handle(rndis_ipa_ctx->bam_dma_hdl); +- if (sps_ctrl_bam_dma_clk(false)) +- RNDIS_IPA_ERROR("fail to disable BAM-DMA clocks"); +-} +- +-/** +- * rndis_ipa_setup_loopback() - create/destroy a loopback on IPA HW +- * (as USB pipes loopback) and notify RNDIS_IPA netdev for pipe connected +- * @enable: flag that determines if the loopback should be created or destroyed +- * @rndis_ipa_ctx: driver main context +- * +- * This function is the main loopback logic. +- * It shall create/destory the loopback by using BAM-DMA and notify +- * the netdev accordingly. +- */ +-static int rndis_ipa_setup_loopback(bool enable, +- struct rndis_ipa_dev *rndis_ipa_ctx) +-{ +- int retval; +- +- if (!enable) { +- rndis_ipa_destroy_loopback(rndis_ipa_ctx); +- RNDIS_IPA_DEBUG("loopback destroy done"); +- retval = rndis_ipa_pipe_disconnect_notify(rndis_ipa_ctx); +- if (retval) { +- RNDIS_IPA_ERROR("connect notify fail"); +- return -ENODEV; +- } +- return 0; +- } +- +- RNDIS_IPA_DEBUG("creating loopback (instead of USB core)"); +- retval = rndis_ipa_create_loopback(rndis_ipa_ctx); +- RNDIS_IPA_DEBUG("creating loopback- %s", (retval ? "FAIL" : "OK")); +- if (retval) { +- RNDIS_IPA_ERROR("Fail to connect loopback"); +- return -ENODEV; +- } +- retval = rndis_ipa_pipe_connect_notify( +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_drv_ep_hdl, +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_drv_ep_hdl, +- BAM_DMA_DATA_FIFO_SIZE, +- 15, +- BAM_DMA_DATA_FIFO_SIZE - rndis_ipa_ctx->net->mtu, +- rndis_ipa_ctx); +- if (retval) { +- RNDIS_IPA_ERROR("connect notify fail"); +- return -ENODEV; +- } +- +- return 0; +- +-} +- + static int rndis_ipa_init_module(void) + { + pr_info("RNDIS_IPA module is loaded."); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-5870/0.patch b/Patches/Linux_CVEs/CVE-2016-5870/0.patch new file mode 100644 index 00000000..c3039936 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-5870/0.patch @@ -0,0 +1,44 @@ +From 71fe5361cbef34e2d606b79e8936a910a3e95566 Mon Sep 17 00:00:00 2001 +From: Arun Kumar Neelakantam +Date: Wed, 21 Sep 2016 18:34:01 +0530 +Subject: net: ipc_router: fix NULL pointer de-reference issue + +Fail cases of accept() system call on AF_MSM_IPC socket family causes +NULL pointer de-reference of sock structure variable in release operation. + +Validate the sock structure pointer before using it in release operation. + +CRs-Fixed: 1068888 +Change-Id: I5637e52be59ea9504ea6ae317394bef0c28c7865 +Signed-off-by: Arun Kumar Neelakantam +--- + net/ipc_router/ipc_router_socket.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/net/ipc_router/ipc_router_socket.c b/net/ipc_router/ipc_router_socket.c +index 828797b..652531a 100644 +--- a/net/ipc_router/ipc_router_socket.c ++++ b/net/ipc_router/ipc_router_socket.c +@@ -555,10 +555,18 @@ static unsigned int msm_ipc_router_poll(struct file *file, + static int msm_ipc_router_close(struct socket *sock) + { + struct sock *sk = sock->sk; +- struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk); ++ struct msm_ipc_port *port_ptr; + int ret; + ++ if (!sk) ++ return -EINVAL; ++ + lock_sock(sk); ++ port_ptr = msm_ipc_sk_port(sk); ++ if (!port_ptr) { ++ release_sock(sk); ++ return -EINVAL; ++ } + ret = msm_ipc_router_close_port(port_ptr); + msm_ipc_unload_default_node(msm_ipc_sk(sk)->default_node_vote_info); + release_sock(sk); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6136/0.patch b/Patches/Linux_CVEs/CVE-2016-6136/0.patch new file mode 100644 index 00000000..7b6c5bcb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6136/0.patch @@ -0,0 +1,416 @@ +From 43761473c254b45883a64441dd0bc85a42f3645c Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Tue, 19 Jul 2016 17:42:57 -0400 +Subject: audit: fix a double fetch in audit_log_single_execve_arg() + +There is a double fetch problem in audit_log_single_execve_arg() +where we first check the execve(2) argumnets for any "bad" characters +which would require hex encoding and then re-fetch the arguments for +logging in the audit record[1]. Of course this leaves a window of +opportunity for an unsavory application to munge with the data. + +This patch reworks things by only fetching the argument data once[2] +into a buffer where it is scanned and logged into the audit +records(s). In addition to fixing the double fetch, this patch +improves on the original code in a few other ways: better handling +of large arguments which require encoding, stricter record length +checking, and some performance improvements (completely unverified, +but we got rid of some strlen() calls, that's got to be a good +thing). + +As part of the development of this patch, I've also created a basic +regression test for the audit-testsuite, the test can be tracked on +GitHub at the following link: + + * https://github.com/linux-audit/audit-testsuite/issues/25 + +[1] If you pay careful attention, there is actually a triple fetch +problem due to a strnlen_user() call at the top of the function. + +[2] This is a tiny white lie, we do make a call to strnlen_user() +prior to fetching the argument data. I don't like it, but due to the +way the audit record is structured we really have no choice unless we +copy the entire argument at once (which would require a rather +wasteful allocation). The good news is that with this patch the +kernel no longer relies on this strnlen_user() value for anything +beyond recording it in the log, we also update it with a trustworthy +value whenever possible. + +Reported-by: Pengfei Wang +Cc: +Signed-off-by: Paul Moore +--- + kernel/auditsc.c | 332 +++++++++++++++++++++++++++---------------------------- + 1 file changed, 164 insertions(+), 168 deletions(-) + +diff --git a/kernel/auditsc.c b/kernel/auditsc.c +index aa3feec..c65af21 100644 +--- a/kernel/auditsc.c ++++ b/kernel/auditsc.c +@@ -73,6 +73,7 @@ + #include + #include + #include ++#include + #include + + #include "audit.h" +@@ -82,7 +83,8 @@ + #define AUDITSC_SUCCESS 1 + #define AUDITSC_FAILURE 2 + +-/* no execve audit message should be longer than this (userspace limits) */ ++/* no execve audit message should be longer than this (userspace limits), ++ * see the note near the top of audit_log_execve_info() about this value */ + #define MAX_EXECVE_AUDIT_LEN 7500 + + /* max length to print of cmdline/proctitle value during audit */ +@@ -992,184 +994,178 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid, + return rc; + } + +-/* +- * to_send and len_sent accounting are very loose estimates. We aren't +- * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being +- * within about 500 bytes (next page boundary) +- * +- * why snprintf? an int is up to 12 digits long. if we just assumed when +- * logging that a[%d]= was going to be 16 characters long we would be wasting +- * space in every audit message. In one 7500 byte message we can log up to +- * about 1000 min size arguments. That comes down to about 50% waste of space +- * if we didn't do the snprintf to find out how long arg_num_len was. +- */ +-static int audit_log_single_execve_arg(struct audit_context *context, +- struct audit_buffer **ab, +- int arg_num, +- size_t *len_sent, +- const char __user *p, +- char *buf) ++static void audit_log_execve_info(struct audit_context *context, ++ struct audit_buffer **ab) + { +- char arg_num_len_buf[12]; +- const char __user *tmp_p = p; +- /* how many digits are in arg_num? 5 is the length of ' a=""' */ +- size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 5; +- size_t len, len_left, to_send; +- size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN; +- unsigned int i, has_cntl = 0, too_long = 0; +- int ret; +- +- /* strnlen_user includes the null we don't want to send */ +- len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1; +- +- /* +- * We just created this mm, if we can't find the strings +- * we just copied into it something is _very_ wrong. Similar +- * for strings that are too long, we should not have created +- * any. +- */ +- if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) { +- send_sig(SIGKILL, current, 0); +- return -1; ++ long len_max; ++ long len_rem; ++ long len_full; ++ long len_buf; ++ long len_abuf; ++ long len_tmp; ++ bool require_data; ++ bool encode; ++ unsigned int iter; ++ unsigned int arg; ++ char *buf_head; ++ char *buf; ++ const char __user *p = (const char __user *)current->mm->arg_start; ++ ++ /* NOTE: this buffer needs to be large enough to hold all the non-arg ++ * data we put in the audit record for this argument (see the ++ * code below) ... at this point in time 96 is plenty */ ++ char abuf[96]; ++ ++ /* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the ++ * current value of 7500 is not as important as the fact that it ++ * is less than 8k, a setting of 7500 gives us plenty of wiggle ++ * room if we go over a little bit in the logging below */ ++ WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500); ++ len_max = MAX_EXECVE_AUDIT_LEN; ++ ++ /* scratch buffer to hold the userspace args */ ++ buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); ++ if (!buf_head) { ++ audit_panic("out of memory for argv string"); ++ return; + } ++ buf = buf_head; + +- /* walk the whole argument looking for non-ascii chars */ ++ audit_log_format(*ab, "argc=%d", context->execve.argc); ++ ++ len_rem = len_max; ++ len_buf = 0; ++ len_full = 0; ++ require_data = true; ++ encode = false; ++ iter = 0; ++ arg = 0; + do { +- if (len_left > MAX_EXECVE_AUDIT_LEN) +- to_send = MAX_EXECVE_AUDIT_LEN; +- else +- to_send = len_left; +- ret = copy_from_user(buf, tmp_p, to_send); +- /* +- * There is no reason for this copy to be short. We just +- * copied them here, and the mm hasn't been exposed to user- +- * space yet. +- */ +- if (ret) { +- WARN_ON(1); +- send_sig(SIGKILL, current, 0); +- return -1; +- } +- buf[to_send] = '\0'; +- has_cntl = audit_string_contains_control(buf, to_send); +- if (has_cntl) { +- /* +- * hex messages get logged as 2 bytes, so we can only +- * send half as much in each message +- */ +- max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2; +- break; +- } +- len_left -= to_send; +- tmp_p += to_send; +- } while (len_left > 0); +- +- len_left = len; +- +- if (len > max_execve_audit_len) +- too_long = 1; +- +- /* rewalk the argument actually logging the message */ +- for (i = 0; len_left > 0; i++) { +- int room_left; +- +- if (len_left > max_execve_audit_len) +- to_send = max_execve_audit_len; +- else +- to_send = len_left; +- +- /* do we have space left to send this argument in this ab? */ +- room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent; +- if (has_cntl) +- room_left -= (to_send * 2); +- else +- room_left -= to_send; +- if (room_left < 0) { +- *len_sent = 0; +- audit_log_end(*ab); +- *ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE); +- if (!*ab) +- return 0; +- } ++ /* NOTE: we don't ever want to trust this value for anything ++ * serious, but the audit record format insists we ++ * provide an argument length for really long arguments, ++ * e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but ++ * to use strncpy_from_user() to obtain this value for ++ * recording in the log, although we don't use it ++ * anywhere here to avoid a double-fetch problem */ ++ if (len_full == 0) ++ len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1; ++ ++ /* read more data from userspace */ ++ if (require_data) { ++ /* can we make more room in the buffer? */ ++ if (buf != buf_head) { ++ memmove(buf_head, buf, len_buf); ++ buf = buf_head; ++ } ++ ++ /* fetch as much as we can of the argument */ ++ len_tmp = strncpy_from_user(&buf_head[len_buf], p, ++ len_max - len_buf); ++ if (len_tmp == -EFAULT) { ++ /* unable to copy from userspace */ ++ send_sig(SIGKILL, current, 0); ++ goto out; ++ } else if (len_tmp == (len_max - len_buf)) { ++ /* buffer is not large enough */ ++ require_data = true; ++ /* NOTE: if we are going to span multiple ++ * buffers force the encoding so we stand ++ * a chance at a sane len_full value and ++ * consistent record encoding */ ++ encode = true; ++ len_full = len_full * 2; ++ p += len_tmp; ++ } else { ++ require_data = false; ++ if (!encode) ++ encode = audit_string_contains_control( ++ buf, len_tmp); ++ /* try to use a trusted value for len_full */ ++ if (len_full < len_max) ++ len_full = (encode ? ++ len_tmp * 2 : len_tmp); ++ p += len_tmp + 1; ++ } ++ len_buf += len_tmp; ++ buf_head[len_buf] = '\0'; + +- /* +- * first record needs to say how long the original string was +- * so we can be sure nothing was lost. +- */ +- if ((i == 0) && (too_long)) +- audit_log_format(*ab, " a%d_len=%zu", arg_num, +- has_cntl ? 2*len : len); +- +- /* +- * normally arguments are small enough to fit and we already +- * filled buf above when we checked for control characters +- * so don't bother with another copy_from_user +- */ +- if (len >= max_execve_audit_len) +- ret = copy_from_user(buf, p, to_send); +- else +- ret = 0; +- if (ret) { +- WARN_ON(1); +- send_sig(SIGKILL, current, 0); +- return -1; ++ /* length of the buffer in the audit record? */ ++ len_abuf = (encode ? len_buf * 2 : len_buf + 2); + } +- buf[to_send] = '\0'; +- +- /* actually log it */ +- audit_log_format(*ab, " a%d", arg_num); +- if (too_long) +- audit_log_format(*ab, "[%d]", i); +- audit_log_format(*ab, "="); +- if (has_cntl) +- audit_log_n_hex(*ab, buf, to_send); +- else +- audit_log_string(*ab, buf); +- +- p += to_send; +- len_left -= to_send; +- *len_sent += arg_num_len; +- if (has_cntl) +- *len_sent += to_send * 2; +- else +- *len_sent += to_send; +- } +- /* include the null we didn't log */ +- return len + 1; +-} + +-static void audit_log_execve_info(struct audit_context *context, +- struct audit_buffer **ab) +-{ +- int i, len; +- size_t len_sent = 0; +- const char __user *p; +- char *buf; ++ /* write as much as we can to the audit log */ ++ if (len_buf > 0) { ++ /* NOTE: some magic numbers here - basically if we ++ * can't fit a reasonable amount of data into the ++ * existing audit buffer, flush it and start with ++ * a new buffer */ ++ if ((sizeof(abuf) + 8) > len_rem) { ++ len_rem = len_max; ++ audit_log_end(*ab); ++ *ab = audit_log_start(context, ++ GFP_KERNEL, AUDIT_EXECVE); ++ if (!*ab) ++ goto out; ++ } + +- p = (const char __user *)current->mm->arg_start; ++ /* create the non-arg portion of the arg record */ ++ len_tmp = 0; ++ if (require_data || (iter > 0) || ++ ((len_abuf + sizeof(abuf)) > len_rem)) { ++ if (iter == 0) { ++ len_tmp += snprintf(&abuf[len_tmp], ++ sizeof(abuf) - len_tmp, ++ " a%d_len=%lu", ++ arg, len_full); ++ } ++ len_tmp += snprintf(&abuf[len_tmp], ++ sizeof(abuf) - len_tmp, ++ " a%d[%d]=", arg, iter++); ++ } else ++ len_tmp += snprintf(&abuf[len_tmp], ++ sizeof(abuf) - len_tmp, ++ " a%d=", arg); ++ WARN_ON(len_tmp >= sizeof(abuf)); ++ abuf[sizeof(abuf) - 1] = '\0'; ++ ++ /* log the arg in the audit record */ ++ audit_log_format(*ab, "%s", abuf); ++ len_rem -= len_tmp; ++ len_tmp = len_buf; ++ if (encode) { ++ if (len_abuf > len_rem) ++ len_tmp = len_rem / 2; /* encoding */ ++ audit_log_n_hex(*ab, buf, len_tmp); ++ len_rem -= len_tmp * 2; ++ len_abuf -= len_tmp * 2; ++ } else { ++ if (len_abuf > len_rem) ++ len_tmp = len_rem - 2; /* quotes */ ++ audit_log_n_string(*ab, buf, len_tmp); ++ len_rem -= len_tmp + 2; ++ /* don't subtract the "2" because we still need ++ * to add quotes to the remaining string */ ++ len_abuf -= len_tmp; ++ } ++ len_buf -= len_tmp; ++ buf += len_tmp; ++ } + +- audit_log_format(*ab, "argc=%d", context->execve.argc); ++ /* ready to move to the next argument? */ ++ if ((len_buf == 0) && !require_data) { ++ arg++; ++ iter = 0; ++ len_full = 0; ++ require_data = true; ++ encode = false; ++ } ++ } while (arg < context->execve.argc); + +- /* +- * we need some kernel buffer to hold the userspace args. Just +- * allocate one big one rather than allocating one of the right size +- * for every single argument inside audit_log_single_execve_arg() +- * should be <8k allocation so should be pretty safe. +- */ +- buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); +- if (!buf) { +- audit_panic("out of memory for argv string"); +- return; +- } ++ /* NOTE: the caller handles the final audit_log_end() call */ + +- for (i = 0; i < context->execve.argc; i++) { +- len = audit_log_single_execve_arg(context, ab, i, +- &len_sent, p, buf); +- if (len <= 0) +- break; +- p += len; +- } +- kfree(buf); ++out: ++ kfree(buf_head); + } + + static void show_special(struct audit_context *context, int *call_panic) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6672/0.patch b/Patches/Linux_CVEs/CVE-2016-6672/0.patch new file mode 100644 index 00000000..436c5316 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6672/0.patch @@ -0,0 +1,65 @@ +From d8649432b96bd361de20168372c10269e88e1258 Mon Sep 17 00:00:00 2001 +From: Min Chong +Date: Wed, 17 Aug 2016 23:50:14 -0700 +Subject: [PATCH] input: synaptics: allocate heap memory for buffer + +Allocate buffer memory on the heap instead of the stack +to avoid a potential stack overflow in the write function. + +Bug: 30537088 +Change-Id: Ibe54ac391ade69e4c0c87bf5332c8bcae730e94c +Signed-off-by: Ivan Lozano +--- + drivers/input/touchscreen/synaptics_i2c_rmi4.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c +index eade21de3e15d..ecfbe6a3f9a23 100644 +--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c ++++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c +@@ -1214,15 +1214,16 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + { + int retval; + unsigned char retry; +- unsigned char buf[length + 1]; +- struct i2c_msg msg[] = { +- { +- .addr = rmi4_data->i2c_client->addr, +- .flags = 0, +- .len = length + 1, +- .buf = buf, +- } +- }; ++ unsigned char *buf; ++ struct i2c_msg msg[1]; ++ ++ buf = kzalloc(length + 1, GFP_KERNEL); ++ if (!buf) { ++ dev_err(&rmi4_data->i2c_client->dev, ++ "%s: Failed to alloc mem for buffer\n", ++ __func__); ++ return -ENOMEM; ++ } + + mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex)); + +@@ -1230,6 +1231,11 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + if (retval != PAGE_SELECT_LEN) + goto exit; + ++ msg[0].addr = rmi4_data->i2c_client->addr; ++ msg[0].flags = 0; ++ msg[0].len = length + 1; ++ msg[0].buf = buf; ++ + buf[0] = addr & MASK_8BIT; + memcpy(&buf[1], &data[0], length); + +@@ -1253,6 +1259,7 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + + exit: + mutex_unlock(&(rmi4_data->rmi4_io_ctrl_mutex)); ++ kfree(buf); + + return retval; + } diff --git a/Patches/Linux_CVEs/CVE-2016-6679/0.patch b/Patches/Linux_CVEs/CVE-2016-6679/0.patch new file mode 100644 index 00000000..de5d237a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6679/0.patch @@ -0,0 +1,480 @@ +From d39345f0abc309959d831d09fcbf1619cc0ae0f5 Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Thu, 26 May 2016 15:07:50 +0530 +Subject: wlan: Remove the support for setwpaie ioctl + +This ioctl gets call during the start of SAP/hostapd with wext +interface and which is obsolete, currently using nl80211 interface +for the same + +Remove the code related to setwpaie ioctl + +CRs-Fixed: 1000913 +Change-Id: I8b00db1753d8f72192e4cdb88bc7c638007180fe +--- + CORE/HDD/inc/qc_sap_ioctl.h | 4 +- + CORE/HDD/src/wlan_hdd_hostapd.c | 414 ---------------------------------------- + 2 files changed, 2 insertions(+), 416 deletions(-) + +diff --git a/CORE/HDD/inc/qc_sap_ioctl.h b/CORE/HDD/inc/qc_sap_ioctl.h +index dfa7d1c..2bc3b6a 100644 +--- a/CORE/HDD/inc/qc_sap_ioctl.h ++++ b/CORE/HDD/inc/qc_sap_ioctl.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -143,7 +143,7 @@ typedef struct + #define QCSAP_IOCTL_COMMIT (SIOCIWFIRSTPRIV+2) + + #define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV+4) +-#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV+5) ++ + #define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV+6) + #define QCSAP_IOCTL_VERSION (SIOCIWFIRSTPRIV+7) + #define QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES (SIOCIWFIRSTPRIV+8) +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index 03889a4..752a34c 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -3862,417 +3862,6 @@ static int iw_get_mode(struct net_device *dev, + return ret; + } + +-static int __iw_softap_setwpsie(struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra) +-{ +- hdd_adapter_t *pHostapdAdapter; +- hdd_context_t *pHddCtx; +- v_CONTEXT_t pVosContext; +- hdd_hostapd_state_t *pHostapdState; +- eHalStatus halStatus= eHAL_STATUS_SUCCESS; +- u_int8_t *wps_genie; +- u_int8_t *fwps_genie; +- u_int8_t *pos; +- tpSap_WPSIE pSap_WPSIe; +- u_int8_t WPSIeType; +- u_int16_t length; +- struct iw_point s_priv_data; +- int ret = 0; +- +- ENTER(); +- +- if (!capable(CAP_NET_ADMIN)) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- FL("permission check failed")); +- return -EPERM; +- } +- +- pHostapdAdapter = (netdev_priv(dev)); +- if (NULL == pHostapdAdapter) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "%s: Adapter is NULL",__func__); +- return -EINVAL; +- } +- pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); +- ret = wlan_hdd_validate_context(pHddCtx); +- if (0 != ret) +- { +- return ret; +- } +- pVosContext = pHddCtx->pvosContext; +- if (NULL == pVosContext) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "%s: HDD context is not valid ",__func__); +- return -EINVAL; +- } +- /* helper function to get iwreq_data with compat handling. */ +- if (hdd_priv_get_data(&s_priv_data, wrqu)) +- { +- return -EINVAL; +- } +- +- if ((NULL == s_priv_data.pointer) || (s_priv_data.length < QCSAP_MAX_WSC_IE)) +- { +- return -EINVAL; +- } +- +- wps_genie = mem_alloc_copy_from_user_helper(s_priv_data.pointer, +- s_priv_data.length); +- +- if(NULL == wps_genie) +- { +- hddLog(LOG1, "%s: failed to alloc memory " +- "and copy data from user buffer", __func__); +- return -EFAULT; +- } +- +- fwps_genie = wps_genie; +- +- pSap_WPSIe = vos_mem_malloc(sizeof(tSap_WPSIE)); +- if (NULL == pSap_WPSIe) +- { +- hddLog(LOGE, "VOS unable to allocate memory"); +- kfree(fwps_genie); +- return -ENOMEM; +- } +- vos_mem_zero(pSap_WPSIe, sizeof(tSap_WPSIE)); +- +- hddLog(LOG1,"%s WPS IE type[0x%X] IE[0x%X], LEN[%d]", __func__, wps_genie[0], wps_genie[1], wps_genie[2]); +- WPSIeType = wps_genie[0]; +- if ( wps_genie[0] == eQC_WPS_BEACON_IE) +- { +- pSap_WPSIe->sapWPSIECode = eSAP_WPS_BEACON_IE; +- wps_genie = wps_genie + 1; +- switch ( wps_genie[0] ) +- { +- case DOT11F_EID_WPA: +- if (wps_genie[1] < 2 + 4) +- { +- ret = -EINVAL; +- goto exit; +- } +- else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) +- { +- hddLog (LOG1, "%s Set WPS BEACON IE(len %d)",__func__, wps_genie[1]+2); +- pos = &wps_genie[6]; +- while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) ) +- { +- switch((u_int16_t)(*pos<<8) | *(pos+1)) +- { +- case HDD_WPS_ELEM_VERSION: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version = *pos; +- hddLog(LOG1, "WPS version %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_VER_PRESENT; +- pos += 1; +- break; +- +- case HDD_WPS_ELEM_WPS_STATE: +- pos +=4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState = *pos; +- hddLog(LOG1, "WPS State %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_STATE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_APSETUPLOCK: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked = *pos; +- hddLog(LOG1, "AP setup lock %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_APSETUPLOCK_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_SELECTEDREGISTRA: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra = *pos; +- hddLog(LOG1, "Selected Registra %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRA_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_DEVICE_PASSWORD_ID: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Password ID: %x", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_DEVICEPASSWORDID_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_REGISTRA_CONF_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Select Registra Config Methods: %x", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT; +- pos += 2; +- break; +- +- case HDD_WPS_ELEM_UUID_E: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > sizeof(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E)) +- { +- ret = -EINVAL; +- goto exit; +- } +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_RF_BANDS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand = *pos; +- hddLog(LOG1, "RF band: %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_RF_BANDS_PRESENT; +- pos += 1; +- break; +- +- default: +- hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)", (*pos<<8 | *(pos+1))); +- ret = -EINVAL; +- goto exit; +- } +- } +- } +- else { +- hddLog (LOGE, "%s WPS IE Mismatch %X", +- __func__, wps_genie[0]); +- } +- break; +- +- default: +- hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, wps_genie[0]); +- ret = -EINVAL; +- goto exit; +- } +- } +- else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE) +- { +- pSap_WPSIe->sapWPSIECode = eSAP_WPS_PROBE_RSP_IE; +- wps_genie = wps_genie + 1; +- switch ( wps_genie[0] ) +- { +- case DOT11F_EID_WPA: +- if (wps_genie[1] < 2 + 4) +- { +- ret = -EINVAL; +- goto exit; +- } +- else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) +- { +- hddLog (LOG1, "%s Set WPS PROBE RSP IE(len %d)",__func__, wps_genie[1]+2); +- pos = &wps_genie[6]; +- while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) ) +- { +- switch((u_int16_t)(*pos<<8) | *(pos+1)) +- { +- case HDD_WPS_ELEM_VERSION: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version = *pos; +- hddLog(LOG1, "WPS version %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_VER_PRESENT; +- pos += 1; +- break; +- +- case HDD_WPS_ELEM_WPS_STATE: +- pos +=4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState = *pos; +- hddLog(LOG1, "WPS State %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_STATE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_APSETUPLOCK: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked = *pos; +- hddLog(LOG1, "AP setup lock %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_APSETUPLOCK_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_SELECTEDREGISTRA: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra = *pos; +- hddLog(LOG1, "Selected Registra %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRA_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_DEVICE_PASSWORD_ID: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Password ID: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICEPASSWORDID_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_REGISTRA_CONF_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Select Registra Config Methods: %x", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_RSP_TYPE: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType = *pos; +- hddLog(LOG1, "Config Methods: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RESPONSETYPE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_UUID_E: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E))) +- { +- ret = -EINVAL; +- goto exit; +- } +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT; +- pos += length; +- break; +- +- case HDD_WPS_ELEM_MANUFACTURER: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT; +- pos += length; +- break; +- +- case HDD_WPS_ELEM_MODEL_NAME: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_MODEL_NUM: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_SERIAL_NUM: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_PRIMARY_DEVICE_TYPE: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory = (*pos<<8 | *(pos+1)); +- hddLog(LOG1, "primary dev category: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory); +- pos += 2; +- +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceOUI, pos, HDD_WPS_DEVICE_OUI_LEN); +- hddLog(LOG1, "primary dev oui: %02x, %02x, %02x, %02x", pos[0], pos[1], pos[2], pos[3]); +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory = (*pos<<8 | *(pos+1)); +- hddLog(LOG1, "primary dev sub category: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory); +- pos += 2; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT; +- break; +- case HDD_WPS_ELEM_DEVICE_NAME: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length); +- pos += length; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICENAME_PRESENT; +- break; +- case HDD_WPS_ELEM_CONFIG_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ConfigMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Config Methods: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod); +- pos += 2; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_CONFIGMETHODS_PRESENT; +- break; +- +- case HDD_WPS_ELEM_RF_BANDS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand = *pos; +- hddLog(LOG1, "RF band: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand); +- pos += 1; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RF_BANDS_PRESENT; +- break; +- } // switch +- } +- } +- else +- { +- hddLog (LOGE, "%s WPS IE Mismatch %X",__func__, wps_genie[0]); +- } +- +- } // switch +- } +- halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe); +- if (halStatus != eHAL_STATUS_SUCCESS) +- ret = -EINVAL; +- pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); +- if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE) +- { +- //hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); +- //v_CONTEXT_t pVosContext = pHostapdAdapter->pvosContext; +- WLANSAP_Update_WpsIe ( pVosContext ); +- } +- +-exit: +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- EXIT(); +- return ret; +-} +- +-static int iw_softap_setwpsie(struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra) +-{ +- int ret; +- +- vos_ssr_protect(__func__); +- ret = __iw_softap_setwpsie(dev, info, wrqu, extra); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} + + static int __iw_softap_stopbss(struct net_device *dev, + struct iw_request_info *info, +@@ -4845,8 +4434,6 @@ static const struct iw_priv_args hostapd_private_args[] = { + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setAclMode" }, + { QCSAP_IOCTL_GET_STAWPAIE, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "get_staWPAIE" }, +- { QCSAP_IOCTL_SETWPAIE, +- IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE | IW_PRIV_SIZE_FIXED, 0, "setwpaie" }, + { QCSAP_IOCTL_STOPBSS, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED, 0, "stopbss" }, + { QCSAP_IOCTL_VERSION, 0, +@@ -4945,7 +4532,6 @@ static const iw_handler hostapd_private[] = { + [QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam, //set priv ioctl + [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, //get priv ioctl + [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, //get station genIE +- [QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie, + [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, // stop bss + [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, // get driver version + [QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES - SIOCIWFIRSTPRIV] = iw_get_WPSPBCProbeReqIEs, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6679/1.patch b/Patches/Linux_CVEs/CVE-2016-6679/1.patch new file mode 100644 index 00000000..84609117 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6679/1.patch @@ -0,0 +1,478 @@ +From f081695446679aa44baa0d00940ea18455eeb4c5 Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Thu, 26 May 2016 15:24:26 +0530 +Subject: qcacld-2.0: Remove the support for setwpaie ioctl + +This ioctl gets call during the start of SAP/hostapd with wext +interface and which is obsolete, currently using nl80211 interface +for the same + +Remove the code related to setwpaie ioctl + +CRs-Fixed: 1000913 +Change-Id: Ia45860d7143639aa62d02afe8c08e283e20ba27a +--- + CORE/HDD/inc/qc_sap_ioctl.h | 2 +- + CORE/HDD/src/wlan_hdd_hostapd.c | 419 ---------------------------------------- + 2 files changed, 1 insertion(+), 420 deletions(-) + +diff --git a/CORE/HDD/inc/qc_sap_ioctl.h b/CORE/HDD/inc/qc_sap_ioctl.h +index 570e6c0..1e52ac9 100644 +--- a/CORE/HDD/inc/qc_sap_ioctl.h ++++ b/CORE/HDD/inc/qc_sap_ioctl.h +@@ -143,7 +143,7 @@ typedef struct + #define QCSAP_IOCTL_SET_NONE_GET_THREE (SIOCIWFIRSTPRIV+3) + #define WE_GET_TSF 1 + #define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV+4) +-#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV+5) ++ + #define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV+6) + #define QCSAP_IOCTL_VERSION (SIOCIWFIRSTPRIV+7) + #define QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES (SIOCIWFIRSTPRIV+8) +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index 40ae5cb..dceb610 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -5270,422 +5270,6 @@ static int iw_get_mode(struct net_device *dev, + } + + +-static int __iw_softap_setwpsie(struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra) +-{ +- hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); +-#ifndef WLAN_FEATURE_MBSSID +- v_CONTEXT_t pVosContext; +-#endif +- hdd_hostapd_state_t *pHostapdState; +- eHalStatus halStatus= eHAL_STATUS_SUCCESS; +- u_int8_t *wps_genie; +- u_int8_t *fwps_genie; +- u_int8_t *pos; +- tpSap_WPSIE pSap_WPSIe; +- u_int8_t WPSIeType; +- u_int16_t length; +- struct iw_point s_priv_data; +- hdd_context_t *hdd_ctx; +- int ret; +- +- ENTER(); +- +- if (!capable(CAP_NET_ADMIN)) { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- FL("permission check failed")); +- return -EPERM; +- } +- +- hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); +- ret = wlan_hdd_validate_context(hdd_ctx); +- if (0 != ret) +- return ret; +- +-#ifndef WLAN_FEATURE_MBSSID +- pVosContext = hdd_ctx->pvosContext; +- if (NULL == pVosContext) { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "%s: VOS context is not valid ", __func__); +- return -EINVAL; +- } +-#endif +- +- /* helper function to get iwreq_data with compat handling. */ +- if (hdd_priv_get_data(&s_priv_data, wrqu)) { +- return -EINVAL; +- } +- +- if ((NULL == s_priv_data.pointer) || +- (s_priv_data.length < QCSAP_MAX_WSC_IE)) { +- return -EINVAL; +- } +- +- wps_genie = mem_alloc_copy_from_user_helper(s_priv_data.pointer, +- s_priv_data.length); +- +- if (NULL == wps_genie) { +- hddLog(LOG1, +- "%s: failed to alloc memory and copy data from user buffer", +- __func__); +- return -EFAULT; +- } +- +- fwps_genie = wps_genie; +- +- pSap_WPSIe = vos_mem_malloc(sizeof(tSap_WPSIE)); +- if (NULL == pSap_WPSIe) +- { +- hddLog(LOGE, "VOS unable to allocate memory"); +- kfree(fwps_genie); +- return -ENOMEM; +- } +- vos_mem_zero(pSap_WPSIe, sizeof(tSap_WPSIE)); +- +- hddLog(LOG1,"%s WPS IE type[0x%X] IE[0x%X], LEN[%d]", __func__, wps_genie[0], wps_genie[1], wps_genie[2]); +- WPSIeType = wps_genie[0]; +- if ( wps_genie[0] == eQC_WPS_BEACON_IE) +- { +- pSap_WPSIe->sapWPSIECode = eSAP_WPS_BEACON_IE; +- wps_genie = wps_genie + 1; +- switch ( wps_genie[0] ) +- { +- case DOT11F_EID_WPA: +- if (wps_genie[1] < DOT11F_EID_HEADER_LEN || +- wps_genie[1] > DOT11F_IE_WPA_MAX_LEN + DOT11F_EID_HEADER_LEN) +- { +- ret = -EINVAL; +- goto exit; +- } +- else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) +- { +- hddLog (LOG1, "%s Set WPS BEACON IE(len %d)",__func__, wps_genie[1]+2); +- pos = &wps_genie[6]; +- while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) ) +- { +- switch((u_int16_t)(*pos<<8) | *(pos+1)) +- { +- case HDD_WPS_ELEM_VERSION: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version = *pos; +- hddLog(LOG1, "WPS version %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_VER_PRESENT; +- pos += 1; +- break; +- +- case HDD_WPS_ELEM_WPS_STATE: +- pos +=4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState = *pos; +- hddLog(LOG1, "WPS State %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_STATE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_APSETUPLOCK: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked = *pos; +- hddLog(LOG1, "AP setup lock %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_APSETUPLOCK_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_SELECTEDREGISTRA: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra = *pos; +- hddLog(LOG1, "Selected Registra %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRA_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_DEVICE_PASSWORD_ID: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Password ID: %x", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_DEVICEPASSWORDID_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_REGISTRA_CONF_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Select Registra Config Methods: %x", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT; +- pos += 2; +- break; +- +- case HDD_WPS_ELEM_UUID_E: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > sizeof(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E)) +- { +- ret = -EINVAL; +- goto exit; +- } +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_RF_BANDS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand = *pos; +- hddLog(LOG1, "RF band: %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_RF_BANDS_PRESENT; +- pos += 1; +- break; +- +- default: +- hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)", (*pos<<8 | *(pos+1))); +- ret = -EINVAL; +- goto exit; +- } +- } +- } +- else { +- hddLog (LOGE, "%s WPS IE Mismatch %X", +- __func__, wps_genie[0]); +- } +- break; +- +- default: +- hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, wps_genie[0]); +- ret = -EINVAL; +- goto exit; +- } +- } +- else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE) +- { +- pSap_WPSIe->sapWPSIECode = eSAP_WPS_PROBE_RSP_IE; +- wps_genie = wps_genie + 1; +- switch ( wps_genie[0] ) +- { +- case DOT11F_EID_WPA: +- if (wps_genie[1] < DOT11F_EID_HEADER_LEN || +- wps_genie[1] > DOT11F_IE_WPA_MAX_LEN + DOT11F_EID_HEADER_LEN) +- { +- ret = -EINVAL; +- goto exit; +- } +- else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) +- { +- hddLog (LOG1, "%s Set WPS PROBE RSP IE(len %d)",__func__, wps_genie[1]+2); +- pos = &wps_genie[6]; +- while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) ) +- { +- switch((u_int16_t)(*pos<<8) | *(pos+1)) +- { +- case HDD_WPS_ELEM_VERSION: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version = *pos; +- hddLog(LOG1, "WPS version %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_VER_PRESENT; +- pos += 1; +- break; +- +- case HDD_WPS_ELEM_WPS_STATE: +- pos +=4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState = *pos; +- hddLog(LOG1, "WPS State %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_STATE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_APSETUPLOCK: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked = *pos; +- hddLog(LOG1, "AP setup lock %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_APSETUPLOCK_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_SELECTEDREGISTRA: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra = *pos; +- hddLog(LOG1, "Selected Registra %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRA_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_DEVICE_PASSWORD_ID: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Password ID: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICEPASSWORDID_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_REGISTRA_CONF_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Select Registra Config Methods: %x", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_RSP_TYPE: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType = *pos; +- hddLog(LOG1, "Config Methods: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RESPONSETYPE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_UUID_E: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E))) +- { +- ret = -EINVAL; +- goto exit; +- } +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT; +- pos += length; +- break; +- +- case HDD_WPS_ELEM_MANUFACTURER: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT; +- pos += length; +- break; +- +- case HDD_WPS_ELEM_MODEL_NAME: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_MODEL_NUM: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_SERIAL_NUM: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_PRIMARY_DEVICE_TYPE: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory = (*pos<<8 | *(pos+1)); +- hddLog(LOG1, "primary dev category: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory); +- pos += 2; +- +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceOUI, pos, HDD_WPS_DEVICE_OUI_LEN); +- hddLog(LOG1, "primary dev oui: %02x, %02x, %02x, %02x", pos[0], pos[1], pos[2], pos[3]); +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory = (*pos<<8 | *(pos+1)); +- hddLog(LOG1, "primary dev sub category: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory); +- pos += 2; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT; +- break; +- case HDD_WPS_ELEM_DEVICE_NAME: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length); +- pos += length; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICENAME_PRESENT; +- break; +- case HDD_WPS_ELEM_CONFIG_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ConfigMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Config Methods: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod); +- pos += 2; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_CONFIGMETHODS_PRESENT; +- break; +- +- case HDD_WPS_ELEM_RF_BANDS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand = *pos; +- hddLog(LOG1, "RF band: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand); +- pos += 1; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RF_BANDS_PRESENT; +- break; +- } // switch +- } +- } +- else +- { +- hddLog (LOGE, "%s WPS IE Mismatch %X",__func__, wps_genie[0]); +- } +- +- } // switch +- } +- +-#ifdef WLAN_FEATURE_MBSSID +- halStatus = WLANSAP_Set_WpsIe(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), pSap_WPSIe); +-#else +- halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe); +-#endif +- if (halStatus != eHAL_STATUS_SUCCESS) +- ret = -EINVAL; +- pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); +- if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE) +- { +- //hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); +- //v_CONTEXT_t pVosContext = pHostapdAdapter->pvosContext; +-#ifdef WLAN_FEATURE_MBSSID +- WLANSAP_Update_WpsIe ( WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter) ); +-#else +- WLANSAP_Update_WpsIe ( pVosContext ); +-#endif +- } +-exit: +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- EXIT(); +- return ret; +-} +- +-static int iw_softap_setwpsie(struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra) +-{ +- int ret; +- +- vos_ssr_protect(__func__); +- ret = __iw_softap_setwpsie(dev, info, wrqu, extra); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} +- + static int __iw_softap_stopbss(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, +@@ -6752,8 +6336,6 @@ static const struct iw_priv_args hostapd_private_args[] = { + + { QCSAP_IOCTL_GET_STAWPAIE, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "get_staWPAIE" }, +- { QCSAP_IOCTL_SETWPAIE, +- IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE | IW_PRIV_SIZE_FIXED, 0, "setwpaie" }, + { QCSAP_IOCTL_STOPBSS, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED, 0, "stopbss" }, + { QCSAP_IOCTL_VERSION, 0, +@@ -6928,7 +6510,6 @@ static const iw_handler hostapd_private[] = { + [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, //get priv ioctl + [QCSAP_IOCTL_SET_NONE_GET_THREE - SIOCIWFIRSTPRIV] = iw_softap_get_three, + [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, //get station genIE +- [QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie, + [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, // stop bss + [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, // get driver version + [QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES - SIOCIWFIRSTPRIV] = iw_get_WPSPBCProbeReqIEs, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6679/2.patch b/Patches/Linux_CVEs/CVE-2016-6679/2.patch new file mode 100644 index 00000000..08bfb43a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6679/2.patch @@ -0,0 +1,476 @@ +From 2d8b76ef0d269dd2939050c4eae4838803730c42 Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Thu, 26 May 2016 15:24:26 +0530 +Subject: [PATCH] qcacld-2.0: Remove the support for setwpaie ioctl + +This ioctl gets call during the start of SAP/hostapd with wext +interface and which is obsolete, currently using nl80211 interface +for the same + +Remove the code related to setwpaie ioctl + +Bug: 29915601 +CRs-Fixed: 1000913 +Change-Id: Ia45860d7143639aa62d02afe8c08e283e20ba27a +--- + .../staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h | 2 +- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c | 419 --------------------- + 2 files changed, 1 insertion(+), 420 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h +index 256c14d8e2a49..010be1cb7fb7a 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h +@@ -143,7 +143,7 @@ typedef struct + #define QCSAP_IOCTL_SET_NONE_GET_THREE (SIOCIWFIRSTPRIV+3) + #define WE_GET_TSF 1 + #define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV+4) +-#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV+5) ++ + #define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV+6) + #define QCSAP_IOCTL_VERSION (SIOCIWFIRSTPRIV+7) + #define QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES (SIOCIWFIRSTPRIV+8) +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c +index 354d69cc522c9..024b3135ee74f 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -5241,422 +5241,6 @@ static int iw_get_mode(struct net_device *dev, + } + + +-static int __iw_softap_setwpsie(struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra) +-{ +- hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); +-#ifndef WLAN_FEATURE_MBSSID +- v_CONTEXT_t pVosContext; +-#endif +- hdd_hostapd_state_t *pHostapdState; +- eHalStatus halStatus= eHAL_STATUS_SUCCESS; +- u_int8_t *wps_genie; +- u_int8_t *fwps_genie; +- u_int8_t *pos; +- tpSap_WPSIE pSap_WPSIe; +- u_int8_t WPSIeType; +- u_int16_t length; +- struct iw_point s_priv_data; +- hdd_context_t *hdd_ctx; +- int ret; +- +- ENTER(); +- +- if (!capable(CAP_NET_ADMIN)) { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- FL("permission check failed")); +- return -EPERM; +- } +- +- hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); +- ret = wlan_hdd_validate_context(hdd_ctx); +- if (0 != ret) +- return ret; +- +-#ifndef WLAN_FEATURE_MBSSID +- pVosContext = hdd_ctx->pvosContext; +- if (NULL == pVosContext) { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "%s: VOS context is not valid ", __func__); +- return -EINVAL; +- } +-#endif +- +- /* helper function to get iwreq_data with compat handling. */ +- if (hdd_priv_get_data(&s_priv_data, wrqu)) { +- return -EINVAL; +- } +- +- if ((NULL == s_priv_data.pointer) || +- (s_priv_data.length < QCSAP_MAX_WSC_IE)) { +- return -EINVAL; +- } +- +- wps_genie = mem_alloc_copy_from_user_helper(s_priv_data.pointer, +- s_priv_data.length); +- +- if (NULL == wps_genie) { +- hddLog(LOG1, +- "%s: failed to alloc memory and copy data from user buffer", +- __func__); +- return -EFAULT; +- } +- +- fwps_genie = wps_genie; +- +- pSap_WPSIe = vos_mem_malloc(sizeof(tSap_WPSIE)); +- if (NULL == pSap_WPSIe) +- { +- hddLog(LOGE, "VOS unable to allocate memory"); +- kfree(fwps_genie); +- return -ENOMEM; +- } +- vos_mem_zero(pSap_WPSIe, sizeof(tSap_WPSIE)); +- +- hddLog(LOG1,"%s WPS IE type[0x%X] IE[0x%X], LEN[%d]", __func__, wps_genie[0], wps_genie[1], wps_genie[2]); +- WPSIeType = wps_genie[0]; +- if ( wps_genie[0] == eQC_WPS_BEACON_IE) +- { +- pSap_WPSIe->sapWPSIECode = eSAP_WPS_BEACON_IE; +- wps_genie = wps_genie + 1; +- switch ( wps_genie[0] ) +- { +- case DOT11F_EID_WPA: +- if (wps_genie[1] < DOT11F_EID_HEADER_LEN || +- wps_genie[1] > DOT11F_IE_WPA_MAX_LEN + DOT11F_EID_HEADER_LEN) +- { +- ret = -EINVAL; +- goto exit; +- } +- else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) +- { +- hddLog (LOG1, "%s Set WPS BEACON IE(len %d)",__func__, wps_genie[1]+2); +- pos = &wps_genie[6]; +- while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) ) +- { +- switch((u_int16_t)(*pos<<8) | *(pos+1)) +- { +- case HDD_WPS_ELEM_VERSION: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version = *pos; +- hddLog(LOG1, "WPS version %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.Version); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_VER_PRESENT; +- pos += 1; +- break; +- +- case HDD_WPS_ELEM_WPS_STATE: +- pos +=4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState = *pos; +- hddLog(LOG1, "WPS State %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.wpsState); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_STATE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_APSETUPLOCK: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked = *pos; +- hddLog(LOG1, "AP setup lock %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.APSetupLocked); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_APSETUPLOCK_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_SELECTEDREGISTRA: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra = *pos; +- hddLog(LOG1, "Selected Registra %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistra); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRA_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_DEVICE_PASSWORD_ID: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Password ID: %x", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.DevicePasswordID); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_DEVICEPASSWORDID_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_REGISTRA_CONF_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Select Registra Config Methods: %x", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.SelectedRegistraCfgMethod); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT; +- pos += 2; +- break; +- +- case HDD_WPS_ELEM_UUID_E: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > sizeof(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E)) +- { +- ret = -EINVAL; +- goto exit; +- } +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSBeaconIE.UUID_E, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_UUIDE_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_RF_BANDS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand = *pos; +- hddLog(LOG1, "RF band: %d", pSap_WPSIe->sapwpsie.sapWPSBeaconIE.RFBand); +- pSap_WPSIe->sapwpsie.sapWPSBeaconIE.FieldPresent |= WPS_BEACON_RF_BANDS_PRESENT; +- pos += 1; +- break; +- +- default: +- hddLog (LOGW, "UNKNOWN TLV in WPS IE(%x)", (*pos<<8 | *(pos+1))); +- ret = -EINVAL; +- goto exit; +- } +- } +- } +- else { +- hddLog (LOGE, "%s WPS IE Mismatch %X", +- __func__, wps_genie[0]); +- } +- break; +- +- default: +- hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, wps_genie[0]); +- ret = -EINVAL; +- goto exit; +- } +- } +- else if( wps_genie[0] == eQC_WPS_PROBE_RSP_IE) +- { +- pSap_WPSIe->sapWPSIECode = eSAP_WPS_PROBE_RSP_IE; +- wps_genie = wps_genie + 1; +- switch ( wps_genie[0] ) +- { +- case DOT11F_EID_WPA: +- if (wps_genie[1] < DOT11F_EID_HEADER_LEN || +- wps_genie[1] > DOT11F_IE_WPA_MAX_LEN + DOT11F_EID_HEADER_LEN) +- { +- ret = -EINVAL; +- goto exit; +- } +- else if (memcmp(&wps_genie[2], "\x00\x50\xf2\x04", 4) == 0) +- { +- hddLog (LOG1, "%s Set WPS PROBE RSP IE(len %d)",__func__, wps_genie[1]+2); +- pos = &wps_genie[6]; +- while (((size_t)pos - (size_t)&wps_genie[6]) < (wps_genie[1] - 4) ) +- { +- switch((u_int16_t)(*pos<<8) | *(pos+1)) +- { +- case HDD_WPS_ELEM_VERSION: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version = *pos; +- hddLog(LOG1, "WPS version %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Version); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_VER_PRESENT; +- pos += 1; +- break; +- +- case HDD_WPS_ELEM_WPS_STATE: +- pos +=4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState = *pos; +- hddLog(LOG1, "WPS State %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.wpsState); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_STATE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_APSETUPLOCK: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked = *pos; +- hddLog(LOG1, "AP setup lock %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.APSetupLocked); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_APSETUPLOCK_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_SELECTEDREGISTRA: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra = *pos; +- hddLog(LOG1, "Selected Registra %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistra); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRA_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_DEVICE_PASSWORD_ID: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Password ID: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DevicePasswordID); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICEPASSWORDID_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_REGISTRA_CONF_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Select Registra Config Methods: %x", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT; +- pos += 2; +- break; +- case HDD_WPS_ELEM_RSP_TYPE: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType = *pos; +- hddLog(LOG1, "Config Methods: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ResponseType); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RESPONSETYPE_PRESENT; +- pos += 1; +- break; +- case HDD_WPS_ELEM_UUID_E: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E))) +- { +- ret = -EINVAL; +- goto exit; +- } +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.UUID_E, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_UUIDE_PRESENT; +- pos += length; +- break; +- +- case HDD_WPS_ELEM_MANUFACTURER: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.num_name = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.Manufacture.name, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MANUFACTURE_PRESENT; +- pos += length; +- break; +- +- case HDD_WPS_ELEM_MODEL_NAME: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelName.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNAME_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_MODEL_NUM: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ModelNumber.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_MODELNUMBER_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_SERIAL_NUM: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SerialNumber.text, pos, length); +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_SERIALNUMBER_PRESENT; +- pos += length; +- break; +- case HDD_WPS_ELEM_PRIMARY_DEVICE_TYPE: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory = (*pos<<8 | *(pos+1)); +- hddLog(LOG1, "primary dev category: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceCategory); +- pos += 2; +- +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.PrimaryDeviceOUI, pos, HDD_WPS_DEVICE_OUI_LEN); +- hddLog(LOG1, "primary dev oui: %02x, %02x, %02x, %02x", pos[0], pos[1], pos[2], pos[3]); +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory = (*pos<<8 | *(pos+1)); +- hddLog(LOG1, "primary dev sub category: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceSubCategory); +- pos += 2; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT; +- break; +- case HDD_WPS_ELEM_DEVICE_NAME: +- pos += 2; +- length = *pos<<8 | *(pos+1); +- pos += 2; +- if (length > (sizeof(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text))) +- { +- ret = -EINVAL; +- goto exit; +- } +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.num_text = length; +- vos_mem_copy(pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.DeviceName.text, pos, length); +- pos += length; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_DEVICENAME_PRESENT; +- break; +- case HDD_WPS_ELEM_CONFIG_METHODS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.ConfigMethod = (*pos<<8) | *(pos+1); +- hddLog(LOG1, "Config Methods: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.SelectedRegistraCfgMethod); +- pos += 2; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_CONFIGMETHODS_PRESENT; +- break; +- +- case HDD_WPS_ELEM_RF_BANDS: +- pos += 4; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand = *pos; +- hddLog(LOG1, "RF band: %d", pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.RFBand); +- pos += 1; +- pSap_WPSIe->sapwpsie.sapWPSProbeRspIE.FieldPresent |= WPS_PROBRSP_RF_BANDS_PRESENT; +- break; +- } // switch +- } +- } +- else +- { +- hddLog (LOGE, "%s WPS IE Mismatch %X",__func__, wps_genie[0]); +- } +- +- } // switch +- } +- +-#ifdef WLAN_FEATURE_MBSSID +- halStatus = WLANSAP_Set_WpsIe(WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter), pSap_WPSIe); +-#else +- halStatus = WLANSAP_Set_WpsIe(pVosContext, pSap_WPSIe); +-#endif +- if (halStatus != eHAL_STATUS_SUCCESS) +- ret = -EINVAL; +- pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); +- if( pHostapdState->bCommit && WPSIeType == eQC_WPS_PROBE_RSP_IE) +- { +- //hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); +- //v_CONTEXT_t pVosContext = pHostapdAdapter->pvosContext; +-#ifdef WLAN_FEATURE_MBSSID +- WLANSAP_Update_WpsIe ( WLAN_HDD_GET_SAP_CTX_PTR(pHostapdAdapter) ); +-#else +- WLANSAP_Update_WpsIe ( pVosContext ); +-#endif +- } +-exit: +- vos_mem_free(pSap_WPSIe); +- kfree(fwps_genie); +- EXIT(); +- return ret; +-} +- +-static int iw_softap_setwpsie(struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra) +-{ +- int ret; +- +- vos_ssr_protect(__func__); +- ret = __iw_softap_setwpsie(dev, info, wrqu, extra); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} +- + static int __iw_softap_stopbss(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, +@@ -6719,8 +6303,6 @@ static const struct iw_priv_args hostapd_private_args[] = { + + { QCSAP_IOCTL_GET_STAWPAIE, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "get_staWPAIE" }, +- { QCSAP_IOCTL_SETWPAIE, +- IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE | IW_PRIV_SIZE_FIXED, 0, "setwpaie" }, + { QCSAP_IOCTL_STOPBSS, + IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED, 0, "stopbss" }, + { QCSAP_IOCTL_VERSION, 0, +@@ -6884,7 +6466,6 @@ static const iw_handler hostapd_private[] = { + [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, //get priv ioctl + [QCSAP_IOCTL_SET_NONE_GET_THREE - SIOCIWFIRSTPRIV] = iw_softap_get_three, + [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, //get station genIE +- [QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie, + [QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, // stop bss + [QCSAP_IOCTL_VERSION - SIOCIWFIRSTPRIV] = iw_softap_version, // get driver version + [QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES - SIOCIWFIRSTPRIV] = iw_get_WPSPBCProbeReqIEs, diff --git a/Patches/Linux_CVEs/CVE-2016-6680/0.patch b/Patches/Linux_CVEs/CVE-2016-6680/0.patch new file mode 100644 index 00000000..7d039296 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6680/0.patch @@ -0,0 +1,480 @@ +From 2f2fa073b95d4700de88c0f7558b4a18c13ac552 Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Tue, 9 Aug 2016 16:10:39 +0530 +Subject: qcacld-2.0: Remove the support for iw_set_priv ioctl + +iw_set_priv is obsolete, now hdd_ioctl handles the +driver commands. + +Remove the code related to iw_set_priv ioctl + +CRs-Fixed: 1048052 +Change-Id: Ic64a45aab2d23669d6d1219f6d2d8a465d34ac10 +--- + CORE/HDD/src/wlan_hdd_wext.c | 436 +------------------------------------------ + 1 file changed, 1 insertion(+), 435 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c +index e8d0578..90431ea 100644 +--- a/CORE/HDD/src/wlan_hdd_wext.c ++++ b/CORE/HDD/src/wlan_hdd_wext.c +@@ -4023,69 +4023,6 @@ static int iw_get_linkspeed_priv(struct net_device *dev, + return ret; + } + +-/* +- * Support for the RSSI & RSSI-APPROX private commands +- * Per the WiFi framework the response must be of the form +- * " rssi " +- * unless we are not associated, in which case the response is +- * "OK" +- */ +-static int iw_get_rssi(struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, char *extra) +-{ +- hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); +- char *cmd = extra; +- int len = wrqu->data.length; +- v_S7_t s7Rssi = 0; +- hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); +- int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length; +- VOS_STATUS vosStatus; +- int rc; +- +- if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) || +- (0 == ssidlen) || (ssidlen >= len)) +- { +- /* we are not connected or our SSID is too long +- so we cannot report an rssi */ +- rc = scnprintf(cmd, len, "OK"); +- } +- else +- { +- /* we are connected with a valid SSID +- so we can write the SSID into the return buffer +- (note that it is not NUL-terminated) */ +- memcpy(cmd, pHddStaCtx->conn_info.SSID.SSID.ssId, ssidlen ); +- +- vosStatus = wlan_hdd_get_rssi(pAdapter, &s7Rssi); +- +- if (VOS_STATUS_SUCCESS == vosStatus) +- { +- /* append the rssi to the ssid in the format required by +- the WiFI Framework */ +- rc = scnprintf(&cmd[ssidlen], len - ssidlen, " rssi %d", s7Rssi); +- rc += ssidlen; +- } +- else +- { +- rc = -1; +- } +- } +- +- /* verify that we wrote a valid response */ +- if ((rc < 0) || (rc >= len)) +- { +- // encoding or length error? +- hddLog(VOS_TRACE_LEVEL_ERROR, +- "%s: Unable to encode RSSI, got [%s]", +- __func__, cmd); +- return -EIO; +- } +- +- /* a value is being successfully returned */ +- return rc; +-} +- + VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) + { + struct statsContext context; +@@ -4323,377 +4260,6 @@ void* wlan_hdd_change_country_code_callback(void *pAdapter) + } + + /** +- * __iw_set_priv() - SIOCSIWPRIV ioctl handler +- * @dev: device upon which the ioctl was received +- * @info: ioctl request information +- * @wrqu: ioctl request data +- * @extra: ioctl extra data +- * +- * Return: 0 on success, non-zero on error +- */ +-static int __iw_set_priv(struct net_device *dev, struct iw_request_info *info, +- union iwreq_data *wrqu, char *extra) +-{ +- hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); +- char *cmd = NULL; +- int cmd_len = wrqu->data.length; +- int ret = 0; +- int rc = 0; +- VOS_STATUS vos_status = VOS_STATUS_SUCCESS; +- +- hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +- +- ENTER(); +- cmd = mem_alloc_copy_from_user_helper(wrqu->data.pointer, +- wrqu->data.length); +- if (NULL == cmd) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "mem_alloc_copy_from_user_helper fail"); +- return -ENOMEM; +- } +- +- if (ioctl_debug) +- { +- pr_info("%s: req [%s] len [%d]\n", __func__, cmd, cmd_len); +- } +- +- hddLog(VOS_TRACE_LEVEL_INFO_MED, +- "%s: ***Received %s cmd from Wi-Fi GUI***", __func__, cmd); +- +- if (pHddCtx->isLogpInProgress) { +- if (ioctl_debug) +- { +- pr_info("%s: RESTART in progress\n", __func__); +- } +- +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, +- "%s:LOGP in Progress. Ignore!!!",__func__); +- vos_mem_free(cmd); +- return -EBUSY; +- } +- +- if (strncmp(cmd, "CSCAN", 5) == 0 ) +- { +- if (eHAL_STATUS_SUCCESS != iw_set_cscan(dev, info, wrqu, cmd)) { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "%s: Error in iw_set_scan!", __func__); +- rc = -EINVAL; +- } +- } +- else if( strcasecmp(cmd, "start") == 0 ) { +- +- hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Start command"); +- /*Exit from Deep sleep or standby if we get the driver START cmd from android GUI*/ +- +- vos_status = wlan_hdd_exit_lowpower(pHddCtx, pAdapter); +- if (vos_status == VOS_STATUS_SUCCESS) +- { +- union iwreq_data wrqu; +- char buf[10]; +- +- memset(&wrqu, 0, sizeof(wrqu)); +- wrqu.data.length = strlcpy(buf, "START", sizeof(buf)); +- wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +- } +- else +- { +- hddLog(VOS_TRACE_LEVEL_ERROR, "%s: START CMD Status %d", __func__, vos_status); +- rc = -EIO; +- } +- goto done; +- } +- else if( strcasecmp(cmd, "stop") == 0 ) +- { +- union iwreq_data wrqu; +- char buf[10]; +- +- hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Stop command"); +- +- wlan_hdd_enter_lowpower(pHddCtx); +- memset(&wrqu, 0, sizeof(wrqu)); +- wrqu.data.length = strlcpy(buf, "STOP", sizeof(buf)); +- wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +- goto done; +- } +- else if (strcasecmp(cmd, "macaddr") == 0) +- { +- ret = snprintf(cmd, cmd_len, "Macaddr = " MAC_ADDRESS_STR, +- MAC_ADDR_ARRAY(pAdapter->macAddressCurrent.bytes)); +- } +- else if (strcasecmp(cmd, "scan-active") == 0) +- { +- hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +- hddLog(LOG1, FL("making default scan to active")); +- pHddCtx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; +- ret = snprintf(cmd, cmd_len, "OK"); +- } +- else if (strcasecmp(cmd, "scan-passive") == 0) +- { +- hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +- hddLog(LOG1, FL("making default scan to active")); +- pHddCtx->ioctl_scan_mode = eSIR_PASSIVE_SCAN; +- ret = snprintf(cmd, cmd_len, "OK"); +- } +- else if( strcasecmp(cmd, "scan-mode") == 0 ) +- { +- ret = snprintf(cmd, cmd_len, "ScanMode = %u", pAdapter->scan_info.scan_mode); +- } +- else if( strcasecmp(cmd, "linkspeed") == 0 ) +- { +- ret = iw_get_linkspeed(dev, info, wrqu, cmd); +- } +- else if( strncasecmp(cmd, "COUNTRY", 7) == 0 ) { +- char *country_code; +- unsigned long rc; +- eHalStatus eHal_status; +- +- country_code = cmd + 8; +- +- init_completion(&pAdapter->change_country_code); +- +- eHal_status = sme_ChangeCountryCode(pHddCtx->hHal, +- (void *)(tSmeChangeCountryCallback)wlan_hdd_change_country_code_callback, +- country_code, +- pAdapter, +- pHddCtx->pvosContext, +- eSIR_TRUE, +- eSIR_TRUE); +- +- /* Wait for completion */ +- rc = wait_for_completion_timeout(&pAdapter->change_country_code, +- msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); +- +- if (!rc) { +- hddLog(VOS_TRACE_LEVEL_ERROR, +- FL("SME timedout while setting country code")); +- } +- +- if (eHAL_STATUS_SUCCESS != eHal_status) +- { +- VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, +- "%s: SME Change Country code fail", __func__); +- vos_mem_free(cmd); +- return -EIO; +- } +- } +- else if( strncasecmp(cmd, "rssi", 4) == 0 ) +- { +- ret = iw_get_rssi(dev, info, wrqu, cmd); +- } +- else if( strncasecmp(cmd, "powermode", 9) == 0 ) { +- int mode; +- char *ptr; +- +- if (9 < cmd_len) +- { +- ptr = (char*)(cmd + 9); +- +- }else{ +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "CMD LENGTH %d is not correct",cmd_len); +- vos_mem_free(cmd); +- return -EINVAL; +- } +- +- if (1 != sscanf(ptr,"%d",&mode)) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "powermode input %s is not correct",ptr); +- vos_mem_free(cmd); +- return -EIO; +- } +- +- if(!pHddCtx->cfg_ini->enablePowersaveOffload) +- wlan_hdd_enter_bmps(pAdapter, mode); +- else +- wlan_hdd_set_powersave(pAdapter, mode); +- } +- else if (strncasecmp(cmd, "getpower", 8) == 0 ) { +- v_U32_t pmc_state; +- v_U16_t value; +- +- pmc_state = pmcGetPmcState(WLAN_HDD_GET_HAL_CTX(pAdapter)); +- if(pmc_state == BMPS) { +- value = DRIVER_POWER_MODE_AUTO; +- } +- else { +- value = DRIVER_POWER_MODE_ACTIVE; +- } +- ret = snprintf(cmd, cmd_len, "powermode = %u", value); +- } +- else if( strncasecmp(cmd, "btcoexmode", 10) == 0 ) { +- hddLog( VOS_TRACE_LEVEL_INFO, "btcoexmode"); +- /*TODO: set the btcoexmode*/ +- } +- else if( strcasecmp(cmd, "btcoexstat") == 0 ) { +- +- hddLog(VOS_TRACE_LEVEL_INFO, "BtCoex Status"); +- /*TODO: Return the btcoex status*/ +- } +- else if( strcasecmp(cmd, "rxfilter-start") == 0 ) { +- +- hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Start command"); +- +- /*TODO: Enable Rx data Filter*/ +- } +- else if( strcasecmp(cmd, "rxfilter-stop") == 0 ) { +- +- hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Stop command"); +- +- /*TODO: Disable Rx data Filter*/ +- } +- else if( strcasecmp(cmd, "rxfilter-statistics") == 0 ) { +- +- hddLog( VOS_TRACE_LEVEL_INFO, "Rx Data Filter Statistics command"); +- /*TODO: rxfilter-statistics*/ +- } +- else if( strncasecmp(cmd, "rxfilter-add", 12) == 0 ) { +- +- hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-add"); +- /*TODO: rxfilter-add*/ +- } +- else if( strncasecmp(cmd, "rxfilter-remove",15) == 0 ) { +- +- hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-remove"); +- /*TODO: rxfilter-remove*/ +- } +-#ifdef FEATURE_WLAN_SCAN_PNO +- else if( strncasecmp(cmd, "pnosetup", 8) == 0 ) { +- hddLog( VOS_TRACE_LEVEL_INFO, "pnosetup"); +- /*TODO: support pnosetup*/ +- } +- else if( strncasecmp(cmd, "pnoforce", 8) == 0 ) { +- hddLog( VOS_TRACE_LEVEL_INFO, "pnoforce"); +- /*TODO: support pnoforce*/ +- } +- else if( strncasecmp(cmd, "pno",3) == 0 ) { +- +- hddLog( VOS_TRACE_LEVEL_INFO, "pno"); +- ret = iw_set_pno(dev, info, wrqu, cmd, 3); +- vos_mem_free(cmd); +- return ret; +- } +-#endif /*FEATURE_WLAN_SCAN_PNO*/ +- else if( strncasecmp(cmd, "powerparams",11) == 0 ) { +- hddLog( VOS_TRACE_LEVEL_INFO, "powerparams"); +- vos_status = iw_set_power_params(dev, info, wrqu, cmd, 11); +- vos_mem_free(cmd); +- return (vos_status == VOS_STATUS_SUCCESS) ? 0 : -EINVAL; +- } +- else if( 0 == strncasecmp(cmd, "CONFIG-TX-TRACKING", 18) ) { +- tSirTxPerTrackingParam tTxPerTrackingParam; +- char *ptr; +- +- if (18 < cmd_len) +- { +- ptr = (char*)(cmd + 18); +- }else{ +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "CMD LENGTH %d is not correct",cmd_len); +- vos_mem_free(cmd); +- return -EINVAL; +- } +- +- if (4 != sscanf(ptr,"%hhu %hhu %hhu %u", +- &(tTxPerTrackingParam.ucTxPerTrackingEnable), +- &(tTxPerTrackingParam.ucTxPerTrackingPeriod), +- &(tTxPerTrackingParam.ucTxPerTrackingRatio), +- &(tTxPerTrackingParam.uTxPerTrackingWatermark))) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "CONFIG-TX-TRACKING %s input is not correct",ptr); +- vos_mem_free(cmd); +- return -EIO; +- } +- +- // parameters checking +- // period has to be larger than 0 +- if (0 == tTxPerTrackingParam.ucTxPerTrackingPeriod) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Period input is not correct"); +- vos_mem_free(cmd); +- return -EIO; +- } +- +- // use default value 5 is the input is not reasonable. in unit of 10% +- if ((tTxPerTrackingParam.ucTxPerTrackingRatio > TX_PER_TRACKING_MAX_RATIO) || (0 == tTxPerTrackingParam.ucTxPerTrackingRatio)) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Ratio input is not good. use default 5"); +- tTxPerTrackingParam.ucTxPerTrackingRatio = TX_PER_TRACKING_DEFAULT_RATIO; +- } +- +- // default is 5 +- if (0 == tTxPerTrackingParam.uTxPerTrackingWatermark) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx Packet number input is not good. use default 5"); +- tTxPerTrackingParam.uTxPerTrackingWatermark = TX_PER_TRACKING_DEFAULT_WATERMARK; +- } +- +- if (eHAL_STATUS_SUCCESS != +- sme_SetTxPerTracking(pHddCtx->hHal, +- hdd_tx_per_hit_cb, +- (void*)pAdapter, &tTxPerTrackingParam)) { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Set Tx PER Tracking Failed!"); +- rc = -EIO; +- } +- } +- else { +- hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s", +- __func__, cmd); +- } +-done: +- /* many of the commands write information back into the command +- string using snprintf(). check the return value here in one +- place */ +- if ((ret < 0) || (ret >= cmd_len)) +- { +- /* there was an encoding error or overflow */ +- rc = -EINVAL; +- } +- else if (ret > 0) +- { +- if (copy_to_user(wrqu->data.pointer, cmd, ret)) +- { +- hddLog(VOS_TRACE_LEVEL_ERROR, +- "%s: failed to copy data to user buffer", __func__); +- vos_mem_free(cmd); +- return -EFAULT; +- } +- wrqu->data.length = ret; +- } +- +- if (ioctl_debug) +- { +- pr_info("%s: rsp [%s] len [%d] status %d\n", +- __func__, cmd, wrqu->data.length, rc); +- } +- vos_mem_free(cmd); +- return rc; +-} +- +-/** +- * iw_set_priv() - SSR wrapper for __iw_set_priv() +- * @dev: pointer to net_device +- * @info: pointer to iw_request_info +- * @wrqu: pointer to iwreq_data +- * @extra: pointer to extra ioctl payload +- * +- * Return: 0 on success, error number otherwise +- */ +-static int iw_set_priv(struct net_device *dev, struct iw_request_info *info, +- union iwreq_data *wrqu, char *extra) +-{ +- int ret; +- +- vos_ssr_protect(__func__); +- ret = __iw_set_priv(dev, info, wrqu, extra); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} +- +-/** + * __iw_set_nick() - set nick + * @dev: pointer to net_device + * @info: pointer to iw_request_info +@@ -11418,7 +10984,7 @@ static const iw_handler we_handler[] = + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) iw_get_range, /* SIOCGIWRANGE */ +- (iw_handler) iw_set_priv, /* SIOCSIWPRIV */ ++ (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6680/1.patch b/Patches/Linux_CVEs/CVE-2016-6680/1.patch new file mode 100644 index 00000000..e7377ad5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6680/1.patch @@ -0,0 +1,479 @@ +From f4e24e60b5729032ac9d53cb2ac08ab0d05d67a4 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Tue, 16 Aug 2016 14:29:26 -0700 +Subject: [PATCH] qcacld-2.0: Remove the support for iw_set_priv ioctl + +iw_set_priv is obsolete, now hdd_ioctl handles the +driver commands. + +Remove the code related to iw_set_priv ioctl + +CRs-Fixed: 1048052 +Change-Id: Ic64a45aab2d23669d6d1219f6d2d8a465d34ac10 +Bug: 29982678 +Signed-off-by: Srinivas Girigowda +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c | 436 +-------------------- + 1 file changed, 1 insertion(+), 435 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c +index b226a9d42daa2..804c74f5d03e9 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c +@@ -4005,69 +4005,6 @@ static int iw_get_linkspeed_priv(struct net_device *dev, + return ret; + } + +-/* +- * Support for the RSSI & RSSI-APPROX private commands +- * Per the WiFi framework the response must be of the form +- * " rssi " +- * unless we are not associated, in which case the response is +- * "OK" +- */ +-static int iw_get_rssi(struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, char *extra) +-{ +- hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); +- char *cmd = extra; +- int len = wrqu->data.length; +- v_S7_t s7Rssi = 0; +- hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); +- int ssidlen = pHddStaCtx->conn_info.SSID.SSID.length; +- VOS_STATUS vosStatus; +- int rc; +- +- if ((eConnectionState_Associated != pHddStaCtx->conn_info.connState) || +- (0 == ssidlen) || (ssidlen >= len)) +- { +- /* we are not connected or our SSID is too long +- so we cannot report an rssi */ +- rc = scnprintf(cmd, len, "OK"); +- } +- else +- { +- /* we are connected with a valid SSID +- so we can write the SSID into the return buffer +- (note that it is not NUL-terminated) */ +- memcpy(cmd, pHddStaCtx->conn_info.SSID.SSID.ssId, ssidlen ); +- +- vosStatus = wlan_hdd_get_rssi(pAdapter, &s7Rssi); +- +- if (VOS_STATUS_SUCCESS == vosStatus) +- { +- /* append the rssi to the ssid in the format required by +- the WiFI Framework */ +- rc = scnprintf(&cmd[ssidlen], len - ssidlen, " rssi %d", s7Rssi); +- rc += ssidlen; +- } +- else +- { +- rc = -1; +- } +- } +- +- /* verify that we wrote a valid response */ +- if ((rc < 0) || (rc >= len)) +- { +- // encoding or length error? +- hddLog(VOS_TRACE_LEVEL_ERROR, +- "%s: Unable to encode RSSI, got [%s]", +- __func__, cmd); +- return -EIO; +- } +- +- /* a value is being successfully returned */ +- return rc; +-} +- + VOS_STATUS wlan_hdd_enter_bmps(hdd_adapter_t *pAdapter, int mode) + { + struct statsContext context; +@@ -4300,377 +4237,6 @@ void* wlan_hdd_change_country_code_callback(void *pAdapter) + } + + /** +- * __iw_set_priv() - SIOCSIWPRIV ioctl handler +- * @dev: device upon which the ioctl was received +- * @info: ioctl request information +- * @wrqu: ioctl request data +- * @extra: ioctl extra data +- * +- * Return: 0 on success, non-zero on error +- */ +-static int __iw_set_priv(struct net_device *dev, struct iw_request_info *info, +- union iwreq_data *wrqu, char *extra) +-{ +- hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); +- char *cmd = NULL; +- int cmd_len = wrqu->data.length; +- int ret = 0; +- int rc = 0; +- VOS_STATUS vos_status = VOS_STATUS_SUCCESS; +- +- hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +- +- ENTER(); +- cmd = mem_alloc_copy_from_user_helper(wrqu->data.pointer, +- wrqu->data.length); +- if (NULL == cmd) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "mem_alloc_copy_from_user_helper fail"); +- return -ENOMEM; +- } +- +- if (ioctl_debug) +- { +- pr_info("%s: req [%s] len [%d]\n", __func__, cmd, cmd_len); +- } +- +- hddLog(VOS_TRACE_LEVEL_INFO_MED, +- "%s: ***Received %s cmd from Wi-Fi GUI***", __func__, cmd); +- +- if (pHddCtx->isLogpInProgress) { +- if (ioctl_debug) +- { +- pr_info("%s: RESTART in progress\n", __func__); +- } +- +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, +- "%s:LOGP in Progress. Ignore!!!",__func__); +- kfree(cmd); +- return -EBUSY; +- } +- +- if (strncmp(cmd, "CSCAN", 5) == 0 ) +- { +- if (eHAL_STATUS_SUCCESS != iw_set_cscan(dev, info, wrqu, cmd)) { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "%s: Error in iw_set_scan!", __func__); +- rc = -EINVAL; +- } +- } +- else if( strcasecmp(cmd, "start") == 0 ) { +- +- hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Start command"); +- /*Exit from Deep sleep or standby if we get the driver START cmd from android GUI*/ +- +- vos_status = wlan_hdd_exit_lowpower(pHddCtx, pAdapter); +- if (vos_status == VOS_STATUS_SUCCESS) +- { +- union iwreq_data wrqu; +- char buf[10]; +- +- memset(&wrqu, 0, sizeof(wrqu)); +- wrqu.data.length = strlcpy(buf, "START", sizeof(buf)); +- wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +- } +- else +- { +- hddLog(VOS_TRACE_LEVEL_ERROR, "%s: START CMD Status %d", __func__, vos_status); +- rc = -EIO; +- } +- goto done; +- } +- else if( strcasecmp(cmd, "stop") == 0 ) +- { +- union iwreq_data wrqu; +- char buf[10]; +- +- hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "Stop command"); +- +- wlan_hdd_enter_lowpower(pHddCtx); +- memset(&wrqu, 0, sizeof(wrqu)); +- wrqu.data.length = strlcpy(buf, "STOP", sizeof(buf)); +- wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu, buf); +- goto done; +- } +- else if (strcasecmp(cmd, "macaddr") == 0) +- { +- ret = snprintf(cmd, cmd_len, "Macaddr = " MAC_ADDRESS_STR, +- MAC_ADDR_ARRAY(pAdapter->macAddressCurrent.bytes)); +- } +- else if (strcasecmp(cmd, "scan-active") == 0) +- { +- hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +- hddLog(LOG1, FL("making default scan to active")); +- pHddCtx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; +- ret = snprintf(cmd, cmd_len, "OK"); +- } +- else if (strcasecmp(cmd, "scan-passive") == 0) +- { +- hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); +- hddLog(LOG1, FL("making default scan to active")); +- pHddCtx->ioctl_scan_mode = eSIR_PASSIVE_SCAN; +- ret = snprintf(cmd, cmd_len, "OK"); +- } +- else if( strcasecmp(cmd, "scan-mode") == 0 ) +- { +- ret = snprintf(cmd, cmd_len, "ScanMode = %u", pAdapter->scan_info.scan_mode); +- } +- else if( strcasecmp(cmd, "linkspeed") == 0 ) +- { +- ret = iw_get_linkspeed(dev, info, wrqu, cmd); +- } +- else if( strncasecmp(cmd, "COUNTRY", 7) == 0 ) { +- char *country_code; +- unsigned long rc; +- eHalStatus eHal_status; +- +- country_code = cmd + 8; +- +- init_completion(&pAdapter->change_country_code); +- +- eHal_status = sme_ChangeCountryCode(pHddCtx->hHal, +- (void *)(tSmeChangeCountryCallback)wlan_hdd_change_country_code_callback, +- country_code, +- pAdapter, +- pHddCtx->pvosContext, +- eSIR_TRUE, +- eSIR_TRUE); +- +- /* Wait for completion */ +- rc = wait_for_completion_timeout(&pAdapter->change_country_code, +- msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); +- +- if (!rc) { +- hddLog(VOS_TRACE_LEVEL_ERROR, +- FL("SME timedout while setting country code")); +- } +- +- if (eHAL_STATUS_SUCCESS != eHal_status) +- { +- VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, +- "%s: SME Change Country code fail", __func__); +- kfree(cmd); +- return -EIO; +- } +- } +- else if( strncasecmp(cmd, "rssi", 4) == 0 ) +- { +- ret = iw_get_rssi(dev, info, wrqu, cmd); +- } +- else if( strncasecmp(cmd, "powermode", 9) == 0 ) { +- int mode; +- char *ptr; +- +- if (9 < cmd_len) +- { +- ptr = (char*)(cmd + 9); +- +- }else{ +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "CMD LENGTH %d is not correct",cmd_len); +- kfree(cmd); +- return -EINVAL; +- } +- +- if (1 != sscanf(ptr,"%d",&mode)) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "powermode input %s is not correct",ptr); +- kfree(cmd); +- return -EIO; +- } +- +- if(!pHddCtx->cfg_ini->enablePowersaveOffload) +- wlan_hdd_enter_bmps(pAdapter, mode); +- else +- wlan_hdd_set_powersave(pAdapter, mode); +- } +- else if (strncasecmp(cmd, "getpower", 8) == 0 ) { +- v_U32_t pmc_state; +- v_U16_t value; +- +- pmc_state = pmcGetPmcState(WLAN_HDD_GET_HAL_CTX(pAdapter)); +- if(pmc_state == BMPS) { +- value = DRIVER_POWER_MODE_AUTO; +- } +- else { +- value = DRIVER_POWER_MODE_ACTIVE; +- } +- ret = snprintf(cmd, cmd_len, "powermode = %u", value); +- } +- else if( strncasecmp(cmd, "btcoexmode", 10) == 0 ) { +- hddLog( VOS_TRACE_LEVEL_INFO, "btcoexmode"); +- /*TODO: set the btcoexmode*/ +- } +- else if( strcasecmp(cmd, "btcoexstat") == 0 ) { +- +- hddLog(VOS_TRACE_LEVEL_INFO, "BtCoex Status"); +- /*TODO: Return the btcoex status*/ +- } +- else if( strcasecmp(cmd, "rxfilter-start") == 0 ) { +- +- hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Start command"); +- +- /*TODO: Enable Rx data Filter*/ +- } +- else if( strcasecmp(cmd, "rxfilter-stop") == 0 ) { +- +- hddLog(VOS_TRACE_LEVEL_INFO, "Rx Data Filter Stop command"); +- +- /*TODO: Disable Rx data Filter*/ +- } +- else if( strcasecmp(cmd, "rxfilter-statistics") == 0 ) { +- +- hddLog( VOS_TRACE_LEVEL_INFO, "Rx Data Filter Statistics command"); +- /*TODO: rxfilter-statistics*/ +- } +- else if( strncasecmp(cmd, "rxfilter-add", 12) == 0 ) { +- +- hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-add"); +- /*TODO: rxfilter-add*/ +- } +- else if( strncasecmp(cmd, "rxfilter-remove",15) == 0 ) { +- +- hddLog( VOS_TRACE_LEVEL_INFO, "rxfilter-remove"); +- /*TODO: rxfilter-remove*/ +- } +-#ifdef FEATURE_WLAN_SCAN_PNO +- else if( strncasecmp(cmd, "pnosetup", 8) == 0 ) { +- hddLog( VOS_TRACE_LEVEL_INFO, "pnosetup"); +- /*TODO: support pnosetup*/ +- } +- else if( strncasecmp(cmd, "pnoforce", 8) == 0 ) { +- hddLog( VOS_TRACE_LEVEL_INFO, "pnoforce"); +- /*TODO: support pnoforce*/ +- } +- else if( strncasecmp(cmd, "pno",3) == 0 ) { +- +- hddLog( VOS_TRACE_LEVEL_INFO, "pno"); +- ret = iw_set_pno(dev, info, wrqu, cmd, 3); +- kfree(cmd); +- return ret; +- } +-#endif /*FEATURE_WLAN_SCAN_PNO*/ +- else if( strncasecmp(cmd, "powerparams",11) == 0 ) { +- hddLog( VOS_TRACE_LEVEL_INFO, "powerparams"); +- vos_status = iw_set_power_params(dev, info, wrqu, cmd, 11); +- kfree(cmd); +- return (vos_status == VOS_STATUS_SUCCESS) ? 0 : -EINVAL; +- } +- else if( 0 == strncasecmp(cmd, "CONFIG-TX-TRACKING", 18) ) { +- tSirTxPerTrackingParam tTxPerTrackingParam; +- char *ptr; +- +- if (18 < cmd_len) +- { +- ptr = (char*)(cmd + 18); +- }else{ +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "CMD LENGTH %d is not correct",cmd_len); +- kfree(cmd); +- return -EINVAL; +- } +- +- if (4 != sscanf(ptr,"%hhu %hhu %hhu %u", +- &(tTxPerTrackingParam.ucTxPerTrackingEnable), +- &(tTxPerTrackingParam.ucTxPerTrackingPeriod), +- &(tTxPerTrackingParam.ucTxPerTrackingRatio), +- &(tTxPerTrackingParam.uTxPerTrackingWatermark))) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, +- "CONFIG-TX-TRACKING %s input is not correct",ptr); +- kfree(cmd); +- return -EIO; +- } +- +- // parameters checking +- // period has to be larger than 0 +- if (0 == tTxPerTrackingParam.ucTxPerTrackingPeriod) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Period input is not correct"); +- kfree(cmd); +- return -EIO; +- } +- +- // use default value 5 is the input is not reasonable. in unit of 10% +- if ((tTxPerTrackingParam.ucTxPerTrackingRatio > TX_PER_TRACKING_MAX_RATIO) || (0 == tTxPerTrackingParam.ucTxPerTrackingRatio)) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Ratio input is not good. use default 5"); +- tTxPerTrackingParam.ucTxPerTrackingRatio = TX_PER_TRACKING_DEFAULT_RATIO; +- } +- +- // default is 5 +- if (0 == tTxPerTrackingParam.uTxPerTrackingWatermark) +- { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx Packet number input is not good. use default 5"); +- tTxPerTrackingParam.uTxPerTrackingWatermark = TX_PER_TRACKING_DEFAULT_WATERMARK; +- } +- +- if (eHAL_STATUS_SUCCESS != +- sme_SetTxPerTracking(pHddCtx->hHal, +- hdd_tx_per_hit_cb, +- (void*)pAdapter, &tTxPerTrackingParam)) { +- VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Set Tx PER Tracking Failed!"); +- rc = -EIO; +- } +- } +- else { +- hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s", +- __func__, cmd); +- } +-done: +- /* many of the commands write information back into the command +- string using snprintf(). check the return value here in one +- place */ +- if ((ret < 0) || (ret >= cmd_len)) +- { +- /* there was an encoding error or overflow */ +- rc = -EINVAL; +- } +- else if (ret > 0) +- { +- if (copy_to_user(wrqu->data.pointer, cmd, ret)) +- { +- hddLog(VOS_TRACE_LEVEL_ERROR, +- "%s: failed to copy data to user buffer", __func__); +- kfree(cmd); +- return -EFAULT; +- } +- wrqu->data.length = ret; +- } +- +- if (ioctl_debug) +- { +- pr_info("%s: rsp [%s] len [%d] status %d\n", +- __func__, cmd, wrqu->data.length, rc); +- } +- kfree(cmd); +- return rc; +-} +- +-/** +- * iw_set_priv() - SSR wrapper for __iw_set_priv() +- * @dev: pointer to net_device +- * @info: pointer to iw_request_info +- * @wrqu: pointer to iwreq_data +- * @extra: pointer to extra ioctl payload +- * +- * Return: 0 on success, error number otherwise +- */ +-static int iw_set_priv(struct net_device *dev, struct iw_request_info *info, +- union iwreq_data *wrqu, char *extra) +-{ +- int ret; +- +- vos_ssr_protect(__func__); +- ret = __iw_set_priv(dev, info, wrqu, extra); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} +- +-/** + * __iw_set_nick() - set nick + * @dev: pointer to net_device + * @info: pointer to iw_request_info +@@ -11405,7 +10971,7 @@ static const iw_handler we_handler[] = + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) iw_get_range, /* SIOCGIWRANGE */ +- (iw_handler) iw_set_priv, /* SIOCSIWPRIV */ ++ (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ diff --git a/Patches/Linux_CVEs/CVE-2016-6681/0.patch b/Patches/Linux_CVEs/CVE-2016-6681/0.patch new file mode 100644 index 00000000..f827297d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6681/0.patch @@ -0,0 +1,46 @@ +From f3a55611dc1c0363374ad92eb52b6ee09bf5ff49 Mon Sep 17 00:00:00 2001 +From: vivek mehta +Date: Thu, 11 Aug 2016 13:27:32 -0700 +Subject: [PATCH] misc: qcom: qdsp6v2: Add missing initialization + +Use variables in driver context after proper initialization + +Bug: 30152182 30152501 +Change-Id: I3e59e27534b8e1088d74b42c72e0075d2fe910e6 +Signed-off-by: Haynes Mathew George +Signed-off-by: vivek mehta +--- + drivers/misc/qcom/qdsp6v2/audio_utils.c | 3 ++- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils.c b/drivers/misc/qcom/qdsp6v2/audio_utils.c +index 2206a3461cc0d..ac56464683600 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2014, 2016, The 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 +@@ -593,6 +593,7 @@ long audio_in_compat_ioctl(struct file *file, + } + case AUDIO_GET_CONFIG_32: { + struct msm_audio_config32 cfg_32; ++ memset(&cfg_32, 0, sizeof(cfg_32)); + cfg_32.buffer_size = audio->pcm_cfg.buffer_size; + cfg_32.buffer_count = audio->pcm_cfg.buffer_count; + cfg_32.channel_count = audio->pcm_cfg.channel_count; +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index 11d890d443007..d444742c603cb 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -1877,6 +1877,7 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + case AUDIO_GET_CONFIG_32: { + struct msm_audio_config32 cfg_32; + mutex_lock(&audio->lock); ++ memset(&cfg_32, 0, sizeof(cfg_32)); + cfg_32.buffer_size = audio->pcm_cfg.buffer_size; + cfg_32.buffer_count = audio->pcm_cfg.buffer_count; + cfg_32.channel_count = audio->pcm_cfg.channel_count; diff --git a/Patches/Linux_CVEs/CVE-2016-6682/0.patch b/Patches/Linux_CVEs/CVE-2016-6682/0.patch new file mode 100644 index 00000000..f827297d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6682/0.patch @@ -0,0 +1,46 @@ +From f3a55611dc1c0363374ad92eb52b6ee09bf5ff49 Mon Sep 17 00:00:00 2001 +From: vivek mehta +Date: Thu, 11 Aug 2016 13:27:32 -0700 +Subject: [PATCH] misc: qcom: qdsp6v2: Add missing initialization + +Use variables in driver context after proper initialization + +Bug: 30152182 30152501 +Change-Id: I3e59e27534b8e1088d74b42c72e0075d2fe910e6 +Signed-off-by: Haynes Mathew George +Signed-off-by: vivek mehta +--- + drivers/misc/qcom/qdsp6v2/audio_utils.c | 3 ++- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils.c b/drivers/misc/qcom/qdsp6v2/audio_utils.c +index 2206a3461cc0d..ac56464683600 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2014, 2016, The 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 +@@ -593,6 +593,7 @@ long audio_in_compat_ioctl(struct file *file, + } + case AUDIO_GET_CONFIG_32: { + struct msm_audio_config32 cfg_32; ++ memset(&cfg_32, 0, sizeof(cfg_32)); + cfg_32.buffer_size = audio->pcm_cfg.buffer_size; + cfg_32.buffer_count = audio->pcm_cfg.buffer_count; + cfg_32.channel_count = audio->pcm_cfg.channel_count; +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index 11d890d443007..d444742c603cb 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -1877,6 +1877,7 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + case AUDIO_GET_CONFIG_32: { + struct msm_audio_config32 cfg_32; + mutex_lock(&audio->lock); ++ memset(&cfg_32, 0, sizeof(cfg_32)); + cfg_32.buffer_size = audio->pcm_cfg.buffer_size; + cfg_32.buffer_count = audio->pcm_cfg.buffer_count; + cfg_32.channel_count = audio->pcm_cfg.channel_count; diff --git a/Patches/Linux_CVEs/CVE-2016-6698/0.patch b/Patches/Linux_CVEs/CVE-2016-6698/0.patch new file mode 100644 index 00000000..8116c1e7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6698/0.patch @@ -0,0 +1,253 @@ +From de90beb76ad0b80da821c3b857dd30cd36319e61 Mon Sep 17 00:00:00 2001 +From: Laxminath Kasam +Date: Mon, 29 Aug 2016 21:58:32 +0530 +Subject: misc: qcom: qdsp6v2: initialize config_32 + +Not all memebers of config_32 are set before they are used which +might lead to invalid values being passed and used. To fix this issue +initialize all member variables of struct config_32 to 0 before +assigning specific values individually. + +CRs-Fixed: 1058826 +Change-Id: Ifea3a6e8bf45481c65a4455ee64318304798fee2 +Signed-off-by: Laxminath Kasam +--- + drivers/misc/qcom/qdsp6v2/aac_in.c | 4 +++- + drivers/misc/qcom/qdsp6v2/amrnb_in.c | 5 ++++- + drivers/misc/qcom/qdsp6v2/amrwb_in.c | 2 ++ + drivers/misc/qcom/qdsp6v2/audio_alac.c | 4 +++- + drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c | 6 +++++- + drivers/misc/qcom/qdsp6v2/audio_ape.c | 4 +++- + drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 2 ++ + drivers/misc/qcom/qdsp6v2/audio_multi_aac.c | 4 +++- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 1 + + drivers/misc/qcom/qdsp6v2/audio_wmapro.c | 4 +++- + drivers/misc/qcom/qdsp6v2/evrc_in.c | 4 +++- + drivers/misc/qcom/qdsp6v2/qcelp_in.c | 4 +++- + 12 files changed, 35 insertions(+), 9 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/aac_in.c b/drivers/misc/qcom/qdsp6v2/aac_in.c +index c9d5dbb..7176c114 100644 +--- a/drivers/misc/qcom/qdsp6v2/aac_in.c ++++ b/drivers/misc/qcom/qdsp6v2/aac_in.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2010-2016, The 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 +@@ -421,6 +421,8 @@ static long aac_in_compat_ioctl(struct file *file, unsigned int cmd, + struct msm_audio_aac_enc_config cfg; + struct msm_audio_aac_enc_config32 cfg_32; + ++ memset(&cfg_32, 0, sizeof(cfg_32)); ++ + cmd = AUDIO_GET_AAC_ENC_CONFIG; + rc = aac_in_ioctl_shared(file, cmd, &cfg); + if (rc) { +diff --git a/drivers/misc/qcom/qdsp6v2/amrnb_in.c b/drivers/misc/qcom/qdsp6v2/amrnb_in.c +index eb92137..1bb441b 100644 +--- a/drivers/misc/qcom/qdsp6v2/amrnb_in.c ++++ b/drivers/misc/qcom/qdsp6v2/amrnb_in.c +@@ -1,4 +1,5 @@ +-/* Copyright (c) 2010-2012, 2014 The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2012, 2014, 2016 The 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 +@@ -221,6 +222,8 @@ static long amrnb_in_compat_ioctl(struct file *file, + struct msm_audio_amrnb_enc_config_v2 *amrnb_config; + struct msm_audio_amrnb_enc_config_v2_32 amrnb_config_32; + ++ memset(&amrnb_config_32, 0, sizeof(amrnb_config_32)); ++ + amrnb_config = + (struct msm_audio_amrnb_enc_config_v2 *)audio->enc_cfg; + amrnb_config_32.band_mode = amrnb_config->band_mode; +diff --git a/drivers/misc/qcom/qdsp6v2/amrwb_in.c b/drivers/misc/qcom/qdsp6v2/amrwb_in.c +index 9bd19d9..43dcbd5 100644 +--- a/drivers/misc/qcom/qdsp6v2/amrwb_in.c ++++ b/drivers/misc/qcom/qdsp6v2/amrwb_in.c +@@ -217,6 +217,8 @@ static long amrwb_in_compat_ioctl(struct file *file, + struct msm_audio_amrwb_enc_config *amrwb_config; + struct msm_audio_amrwb_enc_config_32 amrwb_config_32; + ++ memset(&amrwb_config_32, 0, sizeof(amrwb_config_32)); ++ + amrwb_config = + (struct msm_audio_amrwb_enc_config *)audio->enc_cfg; + amrwb_config_32.band_mode = amrwb_config->band_mode; +diff --git a/drivers/misc/qcom/qdsp6v2/audio_alac.c b/drivers/misc/qcom/qdsp6v2/audio_alac.c +index eaae366..27d542c 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_alac.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_alac.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2016, The 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 +@@ -202,6 +202,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, + struct msm_audio_alac_config *alac_config; + struct msm_audio_alac_config_32 alac_config_32; + ++ memset(&alac_config_32, 0, sizeof(alac_config_32)); ++ + alac_config = (struct msm_audio_alac_config *)audio->codec_cfg; + alac_config_32.frameLength = alac_config->frameLength; + alac_config_32.compatVersion = +diff --git a/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c b/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c +index ec4d8f5..727a536 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_amrwbplus.c +@@ -2,7 +2,7 @@ + * + * Copyright (C) 2008 Google, Inc. + * Copyright (C) 2008 HTC Corporation +- * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -205,6 +205,10 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, + struct msm_audio_amrwbplus_config_v2 *amrwbplus_config; + struct msm_audio_amrwbplus_config_v2_32 + amrwbplus_config_32; ++ ++ memset(&amrwbplus_config_32, 0, ++ sizeof(amrwbplus_config_32)); ++ + amrwbplus_config = + (struct msm_audio_amrwbplus_config_v2 *) + audio->codec_cfg; +diff --git a/drivers/misc/qcom/qdsp6v2/audio_ape.c b/drivers/misc/qcom/qdsp6v2/audio_ape.c +index 3ba7050..d7d550c 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_ape.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_ape.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2016, The 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 +@@ -180,6 +180,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, + struct msm_audio_ape_config *ape_config; + struct msm_audio_ape_config_32 ape_config_32; + ++ memset(&ape_config_32, 0, sizeof(ape_config_32)); ++ + ape_config = (struct msm_audio_ape_config *)audio->codec_cfg; + ape_config_32.compatibleVersion = ape_config->compatibleVersion; + ape_config_32.compressionLevel = +diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +index 6843fd7..940fd08 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +@@ -630,6 +630,8 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, + case AUDIO_EFFECTS_GET_BUF_AVAIL32: { + struct msm_hwacc_buf_avail32 buf_avail; + ++ memset(&buf_avail, 0, sizeof(buf_avail)); ++ + buf_avail.input_num_avail = atomic_read(&effects->in_count); + buf_avail.output_num_avail = atomic_read(&effects->out_count); + pr_debug("%s: write buf avail: %d, read buf avail: %d\n", +diff --git a/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c b/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c +index 52e9bdd..bad1cbb 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_multi_aac.c +@@ -2,7 +2,7 @@ + * + * Copyright (C) 2008 Google, Inc. + * Copyright (C) 2008 HTC Corporation +- * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -304,6 +304,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, + struct msm_audio_aac_config *aac_config; + struct msm_audio_aac_config32 aac_config_32; + ++ memset(&aac_config_32, 0, sizeof(aac_config_32)); ++ + aac_config = (struct msm_audio_aac_config *)audio->codec_cfg; + aac_config_32.format = aac_config->format; + aac_config_32.audio_object = aac_config->audio_object; +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index 3e096fd..5196028 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -2071,6 +2071,7 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + audio->buf_cfg.frames_per_buf); + + mutex_lock(&audio->lock); ++ memset(&cfg_32, 0, sizeof(cfg_32)); + cfg_32.meta_info_enable = audio->buf_cfg.meta_info_enable; + cfg_32.frames_per_buf = audio->buf_cfg.frames_per_buf; + if (copy_to_user((void *)arg, &cfg_32, +diff --git a/drivers/misc/qcom/qdsp6v2/audio_wmapro.c b/drivers/misc/qcom/qdsp6v2/audio_wmapro.c +index c323cb4..d37a578 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_wmapro.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_wmapro.c +@@ -2,7 +2,7 @@ + * + * Copyright (C) 2008 Google, Inc. + * Copyright (C) 2008 HTC Corporation +- * Copyright (c) 2009-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -217,6 +217,8 @@ static long audio_compat_ioctl(struct file *file, unsigned int cmd, + struct msm_audio_wmapro_config *wmapro_config; + struct msm_audio_wmapro_config32 wmapro_config_32; + ++ memset(&wmapro_config_32, 0, sizeof(wmapro_config_32)); ++ + wmapro_config = + (struct msm_audio_wmapro_config *)audio->codec_cfg; + wmapro_config_32.armdatareqthr = wmapro_config->armdatareqthr; +diff --git a/drivers/misc/qcom/qdsp6v2/evrc_in.c b/drivers/misc/qcom/qdsp6v2/evrc_in.c +index 2f931be..aab8e27 100644 +--- a/drivers/misc/qcom/qdsp6v2/evrc_in.c ++++ b/drivers/misc/qcom/qdsp6v2/evrc_in.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2016, The 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 +@@ -224,6 +224,8 @@ static long evrc_in_compat_ioctl(struct file *file, + struct msm_audio_evrc_enc_config32 cfg_32; + struct msm_audio_evrc_enc_config *enc_cfg; + ++ memset(&cfg_32, 0, sizeof(cfg_32)); ++ + enc_cfg = audio->enc_cfg; + cfg_32.cdma_rate = enc_cfg->cdma_rate; + cfg_32.min_bit_rate = enc_cfg->min_bit_rate; +diff --git a/drivers/misc/qcom/qdsp6v2/qcelp_in.c b/drivers/misc/qcom/qdsp6v2/qcelp_in.c +index b5d5ad1..aabf5d3 100644 +--- a/drivers/misc/qcom/qdsp6v2/qcelp_in.c ++++ b/drivers/misc/qcom/qdsp6v2/qcelp_in.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2016, The 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 +@@ -225,6 +225,8 @@ static long qcelp_in_compat_ioctl(struct file *file, + struct msm_audio_qcelp_enc_config32 cfg_32; + struct msm_audio_qcelp_enc_config *enc_cfg; + ++ memset(&cfg_32, 0, sizeof(cfg_32)); ++ + enc_cfg = (struct msm_audio_qcelp_enc_config *)audio->enc_cfg; + cfg_32.cdma_rate = enc_cfg->cdma_rate; + cfg_32.min_bit_rate = enc_cfg->min_bit_rate; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6725/0.patch b/Patches/Linux_CVEs/CVE-2016-6725/0.patch new file mode 100644 index 00000000..5444206f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6725/0.patch @@ -0,0 +1,40 @@ +From cc95d644ee8a043f2883d65dda20e16f95041de3 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Tue, 16 Aug 2016 12:46:12 -0700 +Subject: msm: crypto: Fix integer over flow check in qcrypto driver + +Integer overflow check is invalid when ULONG_MAX is used, +as ULONG_MAX has typeof 'unsigned long', while req->assoclen, +req->crytlen, and qreq.ivsize are 'unsigned int'. Make change +to use UINT_MAX instead of ULONG_MAX. + +CRs-fixed: 1050970 +Change-Id: I3782ea7ed2eaacdcad15b34e047a4699bf4f9e4f +Signed-off-by: Zhen Kong +--- + drivers/crypto/msm/qcrypto.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c +index 40a4105..2d83304 100644 +--- a/drivers/crypto/msm/qcrypto.c ++++ b/drivers/crypto/msm/qcrypto.c +@@ -1870,12 +1870,12 @@ static int _qcrypto_process_aead(struct crypto_engine *pengine, + * include assoicated data, ciphering data stream, + * generated MAC, and CCM padding. + */ +- if ((MAX_ALIGN_SIZE * 2 > ULONG_MAX - req->assoclen) || ++ if ((MAX_ALIGN_SIZE * 2 > UINT_MAX - req->assoclen) || + ((MAX_ALIGN_SIZE * 2 + req->assoclen) > +- ULONG_MAX - qreq.ivsize) || ++ UINT_MAX - qreq.ivsize) || + ((MAX_ALIGN_SIZE * 2 + req->assoclen + + qreq.ivsize) +- > ULONG_MAX - req->cryptlen)) { ++ > UINT_MAX - req->cryptlen)) { + pr_err("Integer overflow on aead req length.\n"); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6728/0.patch b/Patches/Linux_CVEs/CVE-2016-6728/0.patch new file mode 100644 index 00000000..1b899dd2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6728/0.patch @@ -0,0 +1,47 @@ +From 37b3cefe6c01bed2e048d7a42b1c4021f4ba279d Mon Sep 17 00:00:00 2001 +From: Liam Mark +Date: Wed, 12 Oct 2016 14:22:56 -0700 +Subject: ion: disable system contig heap + +A malicious application can take advantage of the ION contig heap to +create a specific memory chunk size to exercise a rowhammer attack on the +physical hardware. +So remove support for the ION contig heap. + +Change-Id: I9cb454cebb74df291479cecc3533d2c684363f77 +Signed-off-by: Liam Mark +Signed-off-by: Prakash Gupta +Signed-off-by: Meghana Ashok +--- + drivers/gpu/ion/ion_heap.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c +index 98c1a8c..061e22a 100644 +--- a/drivers/gpu/ion/ion_heap.c ++++ b/drivers/gpu/ion/ion_heap.c +@@ -26,8 +26,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) + + switch ((int) heap_data->type) { + case ION_HEAP_TYPE_SYSTEM_CONTIG: +- heap = ion_system_contig_heap_create(heap_data); +- break; ++ pr_err("%s: Heap type is disabled: %d\n", __func__, ++ heap_data->type); ++ return ERR_PTR(-EINVAL); + case ION_HEAP_TYPE_SYSTEM: + heap = ion_system_heap_create(heap_data); + break; +@@ -71,7 +72,8 @@ void ion_heap_destroy(struct ion_heap *heap) + + switch ((int) heap->type) { + case ION_HEAP_TYPE_SYSTEM_CONTIG: +- ion_system_contig_heap_destroy(heap); ++ pr_err("%s: Heap type is disabled: %d\n", __func__, ++ heap->type); + break; + case ION_HEAP_TYPE_SYSTEM: + ion_system_heap_destroy(heap); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6728/1.patch b/Patches/Linux_CVEs/CVE-2016-6728/1.patch new file mode 100644 index 00000000..3ded682e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6728/1.patch @@ -0,0 +1,326 @@ +From a3fe90fbd3500e7ecaa32b9da5e582d78cb5cef9 Mon Sep 17 00:00:00 2001 +From: Liam Mark +Date: Wed, 12 Oct 2016 14:22:56 -0700 +Subject: ion: disable system contig heap + +A malicious application can take advantage of the ION contig heap to +create a specific memory chunk size to exercise a rowhammer attack on the +physical hardware. +So remove support for the ION contig heap. + +Change-Id: I9cb454cebb74df291479cecc3533d2c684363f77 +Signed-off-by: Liam Mark +Signed-off-by: Prakash Gupta +Signed-off-by: Paresh Purabhiya +--- + arch/arm/boot/dts/qcom/apq8084-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8226-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8226-w-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8610-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8909-ion.dtsi | 5 ----- + arch/arm/boot/dts/qcom/msm8916-512mb-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8916-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8939-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8974-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8992-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msm8994-ion.dtsi | 7 +------ + arch/arm/boot/dts/qcom/msmtellurium-ion.dtsi | 7 +------ + drivers/staging/android/ion/ion_heap.c | 10 ++++++---- + 13 files changed, 17 insertions(+), 75 deletions(-) + +diff --git a/arch/arm/boot/dts/qcom/apq8084-ion.dtsi b/arch/arm/boot/dts/qcom/apq8084-ion.dtsi +index bd649fe..436a966 100644 +--- a/arch/arm/boot/dts/qcom/apq8084-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/apq8084-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2014,2016, The 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@8 { /* CP_MM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <8>; +diff --git a/arch/arm/boot/dts/qcom/msm8226-ion.dtsi b/arch/arm/boot/dts/qcom/msm8226-ion.dtsi +index b3c25a3..949f506 100644 +--- a/arch/arm/boot/dts/qcom/msm8226-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8226-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014,2016, The 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- system_contig_heap: qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + cp_mm_heap: qcom,ion-heap@8 { /* CP_MM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <8>; +diff --git a/arch/arm/boot/dts/qcom/msm8226-w-ion.dtsi b/arch/arm/boot/dts/qcom/msm8226-w-ion.dtsi +index 1ac36e0..e638bc5 100644 +--- a/arch/arm/boot/dts/qcom/msm8226-w-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8226-w-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014,2016, The 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- system_contig_heap: qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qsecom_heap: qcom,ion-heap@27 { /* QSECOM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <27>; +diff --git a/arch/arm/boot/dts/qcom/msm8610-ion.dtsi b/arch/arm/boot/dts/qcom/msm8610-ion.dtsi +index a7a428b..22ba8c1 100644 +--- a/arch/arm/boot/dts/qcom/msm8610-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8610-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014,2016, The 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@27 { /* QSECOM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <27>; +diff --git a/arch/arm/boot/dts/qcom/msm8909-ion.dtsi b/arch/arm/boot/dts/qcom/msm8909-ion.dtsi +index 509e361..7ec0690 100644 +--- a/arch/arm/boot/dts/qcom/msm8909-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8909-ion.dtsi +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- system_contig_heap: qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qsecom_heap: qcom,ion-heap@27 { /* QSEECOM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <27>; +diff --git a/arch/arm/boot/dts/qcom/msm8916-512mb-ion.dtsi b/arch/arm/boot/dts/qcom/msm8916-512mb-ion.dtsi +index b688a10..2cebe62 100644 +--- a/arch/arm/boot/dts/qcom/msm8916-512mb-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8916-512mb-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014, Linux Foundation. All rights reserved. ++/* Copyright (c) 2014,2016, 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@27 { /* QSEECOM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <27>; +diff --git a/arch/arm/boot/dts/qcom/msm8916-ion.dtsi b/arch/arm/boot/dts/qcom/msm8916-ion.dtsi +index 80baf241..53e85b9 100644 +--- a/arch/arm/boot/dts/qcom/msm8916-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8916-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014, Linux Foundation. All rights reserved. ++/* Copyright (c) 2014,2016, 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@8 { /* CP_MM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <8>; +diff --git a/arch/arm/boot/dts/qcom/msm8939-ion.dtsi b/arch/arm/boot/dts/qcom/msm8939-ion.dtsi +index f5e7054..39e3fa5 100644 +--- a/arch/arm/boot/dts/qcom/msm8939-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8939-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014, Linux Foundation. All rights reserved. ++/* Copyright (c) 2014,2016, 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@8 { /* CP_MM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <8>; +diff --git a/arch/arm/boot/dts/qcom/msm8974-ion.dtsi b/arch/arm/boot/dts/qcom/msm8974-ion.dtsi +index de751a0..e9ead3c 100644 +--- a/arch/arm/boot/dts/qcom/msm8974-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8974-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014,2016, The 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@8 { /* CP_MM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <8>; +diff --git a/arch/arm/boot/dts/qcom/msm8992-ion.dtsi b/arch/arm/boot/dts/qcom/msm8992-ion.dtsi +index b359777..ec9bdab 100644 +--- a/arch/arm/boot/dts/qcom/msm8992-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8992-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014,2016, The 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@22 { /* adsp heap */ + reg = <22>; + linux,contiguous-region = <&adsp_mem>; +diff --git a/arch/arm/boot/dts/qcom/msm8994-ion.dtsi b/arch/arm/boot/dts/qcom/msm8994-ion.dtsi +index 16b920e..deea46f 100644 +--- a/arch/arm/boot/dts/qcom/msm8994-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8994-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014,2016, The 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@8 { /* CP_MM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <8>; +diff --git a/arch/arm/boot/dts/qcom/msmtellurium-ion.dtsi b/arch/arm/boot/dts/qcom/msmtellurium-ion.dtsi +index 79fc0e4..3e8058e 100644 +--- a/arch/arm/boot/dts/qcom/msmtellurium-ion.dtsi ++++ b/arch/arm/boot/dts/qcom/msmtellurium-ion.dtsi +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014, Linux Foundation. All rights reserved. ++/* Copyright (c) 2014,2016, 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 +@@ -21,11 +21,6 @@ + qcom,ion-heap-type = "SYSTEM"; + }; + +- qcom,ion-heap@21 { +- reg = <21>; +- qcom,ion-heap-type = "SYSTEM_CONTIG"; +- }; +- + qcom,ion-heap@8 { /* CP_MM HEAP */ + compatible = "qcom,msm-ion-reserve"; + reg = <8>; +diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c +index 583774e..3026fbe 100644 +--- a/drivers/staging/android/ion/ion_heap.c ++++ b/drivers/staging/android/ion/ion_heap.c +@@ -2,7 +2,7 @@ + * drivers/gpu/ion/ion_heap.c + * + * Copyright (C) 2011 Google, Inc. +- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -302,8 +302,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) + + switch (heap_data->type) { + case ION_HEAP_TYPE_SYSTEM_CONTIG: +- heap = ion_system_contig_heap_create(heap_data); +- break; ++ pr_err("%s: Heap type is disabled: %d\n", __func__, ++ heap_data->type); ++ return ERR_PTR(-EINVAL); + case ION_HEAP_TYPE_SYSTEM: + heap = ion_system_heap_create(heap_data); + break; +@@ -342,7 +343,8 @@ void ion_heap_destroy(struct ion_heap *heap) + + switch (heap->type) { + case ION_HEAP_TYPE_SYSTEM_CONTIG: +- ion_system_contig_heap_destroy(heap); ++ pr_err("%s: Heap type is disabled: %d\n", __func__, ++ heap->type); + break; + case ION_HEAP_TYPE_SYSTEM: + ion_system_heap_destroy(heap); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6728/2.patch b/Patches/Linux_CVEs/CVE-2016-6728/2.patch new file mode 100644 index 00000000..b1f4e3bf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6728/2.patch @@ -0,0 +1,38 @@ +From 6d907675d409feb2145add6aa7f905002a50e8ca Mon Sep 17 00:00:00 2001 +From: Daniel Rosenberg +Date: Fri, 9 Sep 2016 15:32:34 -0700 +Subject: [PATCH] ion: Disable ION_HEAP_TYPE_SYSTEM_CONTIG + +Bug: 30400942 +Change-Id: I19fa5bf6e5c66b532b842180b2cf0ae04ddca337 +Signed-off-by: Daniel Rosenberg +--- + drivers/staging/android/ion/ion_heap.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c +index 0c62683ac0409..fa6c9daf8eec9 100644 +--- a/drivers/staging/android/ion/ion_heap.c ++++ b/drivers/staging/android/ion/ion_heap.c +@@ -300,8 +300,9 @@ struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) + + switch (heap_data->type) { + case ION_HEAP_TYPE_SYSTEM_CONTIG: +- heap = ion_system_contig_heap_create(heap_data); +- break; ++ pr_err("%s: Heap type is disabled: %d\n", __func__, ++ heap_data->type); ++ return ERR_PTR(-EINVAL); + case ION_HEAP_TYPE_SYSTEM: + heap = ion_system_heap_create(heap_data); + break; +@@ -340,7 +341,8 @@ void ion_heap_destroy(struct ion_heap *heap) + + switch (heap->type) { + case ION_HEAP_TYPE_SYSTEM_CONTIG: +- ion_system_contig_heap_destroy(heap); ++ pr_err("%s: Heap type is disabled: %d\n", __func__, ++ heap->type); + break; + case ION_HEAP_TYPE_SYSTEM: + ion_system_heap_destroy(heap); diff --git a/Patches/Linux_CVEs/CVE-2016-6738/0.patch b/Patches/Linux_CVEs/CVE-2016-6738/0.patch new file mode 100644 index 00000000..a2b9d824 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6738/0.patch @@ -0,0 +1,104 @@ +From a829c54236b455885c3e9c7c77ac528b62045e79 Mon Sep 17 00:00:00 2001 +From: AnilKumar Chimata +Date: Wed, 31 Aug 2016 14:08:16 +0530 +Subject: qcedev: Validate Source and Destination addresses + +Source and Destination addresses passed by user space apps/clients +are validated independent of type of operation to mitigate kernel +address space exploitation. + +Change-Id: I9ecb0103d7a73eedb2e0d1db1d5613b18dd77e59 +Signed-off-by: AnilKumar Chimata +--- + drivers/crypto/msm/qcedev.c | 68 ++++++++++++++++++++------------------------- + 1 file changed, 30 insertions(+), 38 deletions(-) + +diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c +index e63f061..1402d3d 100644 +--- a/drivers/crypto/msm/qcedev.c ++++ b/drivers/crypto/msm/qcedev.c +@@ -1234,44 +1234,6 @@ static int qcedev_vbuf_ablk_cipher(struct qcedev_async_req *areq, + struct qcedev_cipher_op_req *saved_req; + struct qcedev_cipher_op_req *creq = &areq->cipher_op_req; + +- /* Verify Source Address's */ +- for (i = 0; i < areq->cipher_op_req.entries; i++) +- if (!access_ok(VERIFY_READ, +- (void __user *)areq->cipher_op_req.vbuf.src[i].vaddr, +- areq->cipher_op_req.vbuf.src[i].len)) +- return -EFAULT; +- +- /* Verify Destination Address's */ +- if (creq->in_place_op != 1) { +- for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) { +- if ((areq->cipher_op_req.vbuf.dst[i].vaddr != 0) && +- (total < creq->data_len)) { +- if (!access_ok(VERIFY_WRITE, +- (void __user *)creq->vbuf.dst[i].vaddr, +- creq->vbuf.dst[i].len)) { +- pr_err("%s:DST WR_VERIFY err %d=0x%lx\n", +- __func__, i, (uintptr_t) +- creq->vbuf.dst[i].vaddr); +- return -EFAULT; +- } +- total += creq->vbuf.dst[i].len; +- } +- } +- } else { +- for (i = 0, total = 0; i < creq->entries; i++) { +- if (total < creq->data_len) { +- if (!access_ok(VERIFY_WRITE, +- (void __user *)creq->vbuf.src[i].vaddr, +- creq->vbuf.src[i].len)) { +- pr_err("%s:SRC WR_VERIFY err %d=0x%lx\n", +- __func__, i, (uintptr_t) +- creq->vbuf.src[i].vaddr); +- return -EFAULT; +- } +- total += creq->vbuf.src[i].len; +- } +- } +- } + total = 0; + + if (areq->cipher_op_req.mode == QCEDEV_AES_MODE_CTR) +@@ -1569,6 +1531,36 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, + __func__, total, req->data_len); + goto error; + } ++ /* Verify Source Address's */ ++ for (i = 0, total = 0; i < req->entries; i++) { ++ if (total < req->data_len) { ++ if (!access_ok(VERIFY_READ, ++ (void __user *)req->vbuf.src[i].vaddr, ++ req->vbuf.src[i].len)) { ++ pr_err("%s:SRC RD_VERIFY err %d=0x%lx\n", ++ __func__, i, (uintptr_t) ++ req->vbuf.src[i].vaddr); ++ goto error; ++ } ++ total += req->vbuf.src[i].len; ++ } ++ } ++ ++ /* Verify Destination Address's */ ++ for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) { ++ if ((req->vbuf.dst[i].vaddr != 0) && ++ (total < req->data_len)) { ++ if (!access_ok(VERIFY_WRITE, ++ (void __user *)req->vbuf.dst[i].vaddr, ++ req->vbuf.dst[i].len)) { ++ pr_err("%s:DST WR_VERIFY err %d=0x%lx\n", ++ __func__, i, (uintptr_t) ++ req->vbuf.dst[i].vaddr); ++ goto error; ++ } ++ total += req->vbuf.dst[i].len; ++ } ++ } + return 0; + error: + return -EINVAL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6739/0.patch b/Patches/Linux_CVEs/CVE-2016-6739/0.patch new file mode 100644 index 00000000..139efbc8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6739/0.patch @@ -0,0 +1,62 @@ +From c4af572a7ad59c0f07fd316a08055bc86dfb5f0d Mon Sep 17 00:00:00 2001 +From: Rajakumar Govindaram +Date: Thu, 15 Sep 2016 17:09:40 -0700 +Subject: msm: camera: 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. + +b/30074605 +CRs-Fixed: 1049826 + +Change-Id: I3e11ca7f6df4bb0d928512f81f3e3dc40fed791a +Signed-off-by: Rajakumar Govindaram +--- + .../platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 26 ++++++++++------------ + 1 file changed, 12 insertions(+), 14 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 c0105a8..18a465f 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 +@@ -2251,21 +2251,19 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + return -EINVAL; + } + +- if (!new_frame->partial_frame_indicator) { +- if (cpp_frame_msg[new_frame->msg_len - 1] != +- MSM_CPP_MSG_ID_TRAILER) { +- pr_err("Invalid frame message\n"); +- return -EINVAL; +- } ++ if (cpp_frame_msg[new_frame->msg_len - 1] != ++ MSM_CPP_MSG_ID_TRAILER) { ++ pr_err("Invalid frame message\n"); ++ return -EINVAL; ++ } + +- if ((stripe_base + new_frame->num_strips * stripe_size + 1) != +- new_frame->msg_len) { +- pr_err("Invalid frame message,len=%d,expected=%d\n", +- new_frame->msg_len, +- (stripe_base + +- new_frame->num_strips * stripe_size + 1)); +- return -EINVAL; +- } ++ if ((stripe_base + new_frame->num_strips * stripe_size + 1) != ++ new_frame->msg_len) { ++ pr_err("Invalid frame message,len=%d,expected=%d\n", ++ new_frame->msg_len, ++ (stripe_base + ++ new_frame->num_strips * stripe_size + 1)); ++ return -EINVAL; + } + + if (cpp_dev->iommu_state != CPP_IOMMU_STATE_ATTACHED) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6739/1.patch b/Patches/Linux_CVEs/CVE-2016-6739/1.patch new file mode 100644 index 00000000..b4759408 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6739/1.patch @@ -0,0 +1,62 @@ +From ac8242269094729c464ac042a58603e01427e509 Mon Sep 17 00:00:00 2001 +From: Rajakumar Govindaram +Date: Thu, 15 Sep 2016 17:09:40 -0700 +Subject: msm: camera: 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. + +b/30074605 +CRs-Fixed: 1049826 + +Change-Id: I3e11ca7f6df4bb0d928512f81f3e3dc40fed791a +Signed-off-by: Rajakumar Govindaram +--- + .../platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 26 ++++++++++------------ + 1 file changed, 12 insertions(+), 14 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 964703c..7874cf6 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 +@@ -2184,21 +2184,19 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + return -EINVAL; + } + +- if (!new_frame->partial_frame_indicator) { +- if (cpp_frame_msg[new_frame->msg_len - 1] != +- MSM_CPP_MSG_ID_TRAILER) { +- pr_err("Invalid frame message\n"); +- return -EINVAL; +- } ++ if (cpp_frame_msg[new_frame->msg_len - 1] != ++ MSM_CPP_MSG_ID_TRAILER) { ++ pr_err("Invalid frame message\n"); ++ return -EINVAL; ++ } + +- if ((stripe_base + new_frame->num_strips * stripe_size + 1) != +- new_frame->msg_len) { +- pr_err("Invalid frame message,len=%d,expected=%d\n", +- new_frame->msg_len, +- (stripe_base + +- new_frame->num_strips * stripe_size + 1)); +- return -EINVAL; +- } ++ if ((stripe_base + new_frame->num_strips * stripe_size + 1) != ++ new_frame->msg_len) { ++ pr_err("Invalid frame message,len=%d,expected=%d\n", ++ new_frame->msg_len, ++ (stripe_base + ++ new_frame->num_strips * stripe_size + 1)); ++ return -EINVAL; + } + + if (cpp_dev->iommu_state != CPP_IOMMU_STATE_ATTACHED) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6740/0.patch b/Patches/Linux_CVEs/CVE-2016-6740/0.patch new file mode 100644 index 00000000..051bfc56 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6740/0.patch @@ -0,0 +1,54 @@ +From a939a87f0adf91feceb329a5c080b86e1ee333c7 Mon Sep 17 00:00:00 2001 +From: Samyukta Mogily +Date: Thu, 1 Sep 2016 18:16:50 +0530 +Subject: msm: sensor: Avoid potential stack overflow + +Add a check to validate the user input data is not +greater than expected stack buffer size to avoid out +of bounds array accesses + +CRs-Fixed: 1056307 +Change-Id: Ifd1f4e828373535fdf963aad22b217ae880c778c +Signed-off-by: Samyukta Mogily +--- + drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c | 6 ++++++ + drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c | 6 ++++++ + 2 files changed, 12 insertions(+) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +index 7315327..99d4b654 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +@@ -272,6 +272,12 @@ int32_t msm_camera_cci_i2c_write_seq_table( + client_addr_type = client->addr_type; + client->addr_type = write_setting->addr_type; + ++ if (reg_setting->reg_data_size > I2C_SEQ_REG_DATA_MAX) { ++ pr_err("%s: number of bytes %u exceeding the max supported %d\n", ++ __func__, reg_setting->reg_data_size, I2C_SEQ_REG_DATA_MAX); ++ return rc; ++ } ++ + for (i = 0; i < write_setting->size; i++) { + rc = msm_camera_cci_i2c_write_seq(client, reg_setting->reg_addr, + reg_setting->reg_data, reg_setting->reg_data_size); +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c +index f542ec2..eced0ce 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c +@@ -290,6 +290,12 @@ int32_t msm_camera_qup_i2c_write_seq_table(struct msm_camera_i2c_client *client, + client_addr_type = client->addr_type; + client->addr_type = write_setting->addr_type; + ++ if (reg_setting->reg_data_size > I2C_SEQ_REG_DATA_MAX) { ++ pr_err("%s: number of bytes %u exceeding the max supported %d\n", ++ __func__, reg_setting->reg_data_size, I2C_SEQ_REG_DATA_MAX); ++ return rc; ++ } ++ + for (i = 0; i < write_setting->size; i++) { + rc = msm_camera_qup_i2c_write_seq(client, reg_setting->reg_addr, + reg_setting->reg_data, reg_setting->reg_data_size); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6740/1.patch b/Patches/Linux_CVEs/CVE-2016-6740/1.patch new file mode 100644 index 00000000..0d9e49a9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6740/1.patch @@ -0,0 +1,138 @@ +From ef78bd62f0c064ae4c827e158d828b2c110ebcdc Mon Sep 17 00:00:00 2001 +From: VijayaKumar T M +Date: Tue, 6 Sep 2016 12:04:57 +0530 +Subject: msm: sensor: Avoid potential stack overflow + +Add a check to validate the user input data is not +greater than expected stack buffer size to avoid out +of bounds array accesses +-Fix checkpatch.pl warnings. + +CRs-Fixed: 1056307 +Change-Id: I8b31006772367a120828269243b1971d33a4d7d3 +Signed-off-by: VijayaKumar T M +--- + .../platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c | 13 ++++++++++++- + .../platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c | 13 ++++++++++++- + 2 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +index 07b7e32..c0ac738 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2016, The 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 +@@ -361,6 +361,12 @@ int32_t msm_camera_cci_i2c_write_seq_table( + client_addr_type = client->addr_type; + client->addr_type = write_setting->addr_type; + ++ if (reg_setting->reg_data_size > I2C_SEQ_REG_DATA_MAX) { ++ pr_err("%s: number of bytes %u exceeding the max supported %d\n", ++ __func__, reg_setting->reg_data_size, I2C_SEQ_REG_DATA_MAX); ++ return rc; ++ } ++ + for (i = 0; i < write_setting->size; i++) { + rc = msm_camera_cci_i2c_write_seq(client, reg_setting->reg_addr, + reg_setting->reg_data, reg_setting->reg_data_size); +@@ -418,6 +424,7 @@ static int32_t msm_camera_cci_i2c_compare(struct msm_camera_i2c_client *client, + int32_t rc; + uint16_t reg_data = 0; + int data_len = 0; ++ + switch (data_type) { + case MSM_CAMERA_I2C_BYTE_DATA: + case MSM_CAMERA_I2C_WORD_DATA: +@@ -472,6 +479,7 @@ int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client, + enum msm_camera_i2c_data_type data_type) + { + int32_t rc; ++ + S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n", + __func__, addr, data, data_type); + +@@ -515,6 +523,7 @@ static int32_t msm_camera_cci_i2c_set_write_mask_data( + { + int32_t rc; + uint16_t reg_data; ++ + CDBG("%s\n", __func__); + if (mask == -1) + return 0; +@@ -544,8 +553,10 @@ int32_t msm_camera_cci_i2c_write_conf_tbl( + { + int i; + int32_t rc = -EFAULT; ++ + for (i = 0; i < size; i++) { + enum msm_camera_i2c_data_type dt; ++ + if (reg_conf_tbl->cmd_type == MSM_CAMERA_I2C_CMD_POLL) { + rc = msm_camera_cci_i2c_poll(client, + reg_conf_tbl->reg_addr, +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c +index ee0e9ba..2c606cc3 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011, 2013-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011, 2013-2016, The 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 +@@ -505,6 +505,12 @@ int32_t msm_camera_qup_i2c_write_seq_table(struct msm_camera_i2c_client *client, + client_addr_type = client->addr_type; + client->addr_type = write_setting->addr_type; + ++ if (reg_setting->reg_data_size > I2C_SEQ_REG_DATA_MAX) { ++ pr_err("%s: number of bytes %u exceeding the max supported %d\n", ++ __func__, reg_setting->reg_data_size, I2C_SEQ_REG_DATA_MAX); ++ return rc; ++ } ++ + for (i = 0; i < write_setting->size; i++) { + rc = msm_camera_qup_i2c_write_seq(client, reg_setting->reg_addr, + reg_setting->reg_data, reg_setting->reg_data_size); +@@ -560,6 +566,7 @@ static int32_t msm_camera_qup_i2c_compare(struct msm_camera_i2c_client *client, + int32_t rc; + uint16_t reg_data = 0; + int data_len = 0; ++ + switch (data_type) { + case MSM_CAMERA_I2C_BYTE_DATA: + case MSM_CAMERA_I2C_WORD_DATA: +@@ -615,6 +622,7 @@ int32_t msm_camera_qup_i2c_poll(struct msm_camera_i2c_client *client, + { + int32_t rc; + int i; ++ + S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n", + __func__, addr, data, data_type); + +@@ -663,6 +671,7 @@ static int32_t msm_camera_qup_i2c_set_write_mask_data( + { + int32_t rc; + uint16_t reg_data; ++ + CDBG("%s\n", __func__); + if (mask == -1) + return 0; +@@ -693,9 +702,11 @@ int32_t msm_camera_qup_i2c_write_conf_tbl( + { + int i; + int32_t rc = -EFAULT; ++ + pr_err("%s, E. ", __func__); + for (i = 0; i < size; i++) { + enum msm_camera_i2c_data_type dt; ++ + if (reg_conf_tbl->cmd_type == MSM_CAMERA_I2C_CMD_POLL) { + rc = msm_camera_qup_i2c_poll(client, + reg_conf_tbl->reg_addr, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6741/0.patch b/Patches/Linux_CVEs/CVE-2016-6741/0.patch new file mode 100644 index 00000000..48b2979e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6741/0.patch @@ -0,0 +1,137 @@ +From 80a1d9978c11f76bbe6d2e622bf2ded18f27e34f Mon Sep 17 00:00:00 2001 +From: VijayaKumar T M +Date: Wed, 7 Sep 2016 12:53:43 +0530 +Subject: msm: camera: Restructure data handling to be more robust + +Use dynamic array allocation instead of static array to +prevent stack overflow. +User-supplied number of bytes may result in integer overflow. +To fix this we check that the num_byte isn't above 8K size. + +CRs-Fixed: 1060554 +Change-Id: I9b05b846e5cc3a62b1a0a67be529f09abc764796 +Signed-off-by: VijayaKumar T M +--- + .../msm/camera_v2/sensor/io/msm_camera_cci_i2c.c | 6 ++++ + .../msm/camera_v2/sensor/io/msm_camera_qup_i2c.c | 39 ++++++++++++++++++++-- + 2 files changed, 43 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +index 07b7e32..f970233 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c +@@ -71,6 +71,12 @@ int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client, + || num_byte == 0) + return rc; + ++ if (num_byte > I2C_REG_DATA_MAX) { ++ pr_err("%s: Error num_byte:0x%x exceeds 8K max supported:0x%x\n", ++ __func__, num_byte, I2C_REG_DATA_MAX); ++ return rc; ++ } ++ + buf = kzalloc(num_byte, GFP_KERNEL); + if (!buf) { + pr_err("%s:%d no memory\n", __func__, __LINE__); +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c +index ee0e9ba..5fd11eb 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c +@@ -102,7 +102,7 @@ int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client, + enum msm_camera_i2c_data_type data_type) + { + int32_t rc = -EFAULT; +- unsigned char buf[client->addr_type+data_type]; ++ unsigned char *buf = NULL; + + if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR + && client->addr_type != MSM_CAMERA_I2C_WORD_ADDR) +@@ -110,6 +110,17 @@ int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client, + && data_type != MSM_CAMERA_I2C_WORD_DATA)) + return rc; + ++ if (client->addr_type > UINT_MAX - data_type) { ++ pr_err("%s: integer overflow prevented\n", __func__); ++ return rc; ++ } ++ ++ buf = kzalloc(client->addr_type+data_type, GFP_KERNEL); ++ if (!buf) { ++ pr_err("%s:%d no memory\n", __func__, __LINE__); ++ return -ENOMEM; ++ } ++ + if (client->addr_type == MSM_CAMERA_I2C_BYTE_ADDR) { + buf[0] = addr; + } else if (client->addr_type == MSM_CAMERA_I2C_WORD_ADDR) { +@@ -119,6 +130,8 @@ int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client, + rc = msm_camera_qup_i2c_rxdata(client, buf, data_type); + if (rc < 0) { + S_I2C_DBG("%s fail\n", __func__); ++ kfree(buf); ++ buf = NULL; + return rc; + } + +@@ -128,6 +141,8 @@ int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client, + *data = buf[0] << 8 | buf[1]; + + S_I2C_DBG("%s addr = 0x%x data: 0x%x\n", __func__, addr, *data); ++ kfree(buf); ++ buf = NULL; + return rc; + } + +@@ -135,7 +150,7 @@ int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client, + uint32_t addr, uint8_t *data, uint32_t num_byte) + { + int32_t rc = -EFAULT; +- unsigned char buf[client->addr_type+num_byte]; ++ unsigned char *buf = NULL; + int i; + + if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR +@@ -143,6 +158,22 @@ int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client, + || num_byte == 0) + return rc; + ++ if (num_byte > I2C_REG_DATA_MAX) { ++ pr_err("%s: Error num_byte:0x%x exceeds 8K max supported:0x%x\n", ++ __func__, num_byte, I2C_REG_DATA_MAX); ++ return rc; ++ } ++ if (client->addr_type > UINT_MAX - num_byte) { ++ pr_err("%s: integer overflow prevented\n", __func__); ++ return rc; ++ } ++ ++ buf = kzalloc(client->addr_type+num_byte, GFP_KERNEL); ++ if (!buf) { ++ pr_err("%s:%d no memory\n", __func__, __LINE__); ++ return -ENOMEM; ++ } ++ + if (client->addr_type == MSM_CAMERA_I2C_BYTE_ADDR) { + buf[0] = addr; + } else if (client->addr_type == MSM_CAMERA_I2C_WORD_ADDR) { +@@ -152,6 +183,8 @@ int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client, + rc = msm_camera_qup_i2c_rxdata(client, buf, num_byte); + if (rc < 0) { + S_I2C_DBG("%s fail\n", __func__); ++ kfree(buf); ++ buf = NULL; + return rc; + } + +@@ -161,6 +194,8 @@ int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client, + S_I2C_DBG("Byte %d: 0x%x\n", i, buf[i]); + S_I2C_DBG("Data: 0x%x\n", data[i]); + } ++ kfree(buf); ++ buf = NULL; + return rc; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6742/0.patch b/Patches/Linux_CVEs/CVE-2016-6742/0.patch new file mode 100644 index 00000000..9c676bce --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6742/0.patch @@ -0,0 +1,33 @@ +From 94f4b81da69ec72486476adb59d7c818bd4ffbd0 Mon Sep 17 00:00:00 2001 +From: chengengjia +Date: Wed, 10 Aug 2016 17:34:43 +0800 +Subject: [PATCH] input: synaptics: Add checks of user input data + +Add checks of the user input count to avoid possible heap overflow + +Bug: 30799828 +Change-Id: I896492b18c4ace6565fb9edd5cbf51f363ce157b +Signed-off-by: chengengjia +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/synaptics_fw_update.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c +index 8e457ccaa5245..170a202590ad4 100644 +--- a/drivers/input/touchscreen/synaptics_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_fw_update.c +@@ -1736,6 +1736,13 @@ static ssize_t fwu_sysfs_store_image(struct file *data_file, + return -EAGAIN; + } + ++ if (count > fwu->image_size - fwu->data_pos) { ++ dev_err(&fwu->rmi4_data->i2c_client->dev, ++ "%s: Not enough space in buffer\n", ++ __func__); ++ return -EINVAL; ++ } ++ + memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]), + (const void *)buf, + count); diff --git a/Patches/Linux_CVEs/CVE-2016-6745/0.patch b/Patches/Linux_CVEs/CVE-2016-6745/0.patch new file mode 100644 index 00000000..dcdb4835 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6745/0.patch @@ -0,0 +1,62 @@ +From 80dd4267f644c7ba9657df52f6bce42f0bef1b4e Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Wed, 14 Sep 2016 15:25:23 -0700 +Subject: [PATCH] input: synaptics: defer sysfs creation during init + +sysfs entries are created which reference fwu->fwu_work. +defer the creation of these sysfs entries until the end of the init +function, after fwu->fwu_work has been initialized. + +Change-Id: Ib7d5304ec2990454486e2b1d28b640a174c83d12 +Bug: 31252388 +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/synaptics_fw_update.c | 28 ++++++++++++------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c +index 170a202590ad4..79b3a780550b8 100644 +--- a/drivers/input/touchscreen/synaptics_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_fw_update.c +@@ -2325,7 +2325,20 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + fwu->initialized = true; + fwu->polling_mode = false; + +- retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, ++ fwu->ts_info = kzalloc(RMI4_INFO_MAX_LEN, GFP_KERNEL); ++ if (!fwu->ts_info) { ++ dev_err(&rmi4_data->i2c_client->dev, "Not enough memory\n"); ++ goto exit_free_ts_info; ++ } ++ ++ synaptics_rmi4_update_debug_info(); ++ ++#ifdef INSIDE_FIRMWARE_UPDATE ++ fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); ++ INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work); ++#endif ++ ++ retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, + &dev_attr_data); + if (retval < 0) { + dev_err(&rmi4_data->i2c_client->dev, +@@ -2357,19 +2370,6 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + goto exit_remove_attrs; + } + +- fwu->ts_info = kzalloc(RMI4_INFO_MAX_LEN, GFP_KERNEL); +- if (!fwu->ts_info) { +- dev_err(&rmi4_data->i2c_client->dev, "Not enough memory\n"); +- goto exit_free_ts_info; +- } +- +- synaptics_rmi4_update_debug_info(); +- +-#ifdef INSIDE_FIRMWARE_UPDATE +- fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); +- INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work); +-#endif +- + return 0; + exit_free_ts_info: + debugfs_remove(temp); diff --git a/Patches/Linux_CVEs/CVE-2016-6745/1.patch b/Patches/Linux_CVEs/CVE-2016-6745/1.patch new file mode 100644 index 00000000..e2c7abee --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6745/1.patch @@ -0,0 +1,444 @@ +From 9397e20764da2fdffdfe20e35cb78211753b83cc Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Wed, 14 Sep 2016 17:21:48 -0700 +Subject: [PATCH] input: synaptics: prevent sysfs races + +concurrent sysfs calls on the fw updater can cause +ugly race conditions. Return EBUSY on concurrent sysfs calls. + +For sysfs calls which generate deferred work, prevent +the deferred work from running concurrently with other +sysfs calls. + +Change-Id: Ie33add946fbcca8309998e4cb7cb01525c667c7e +Signed-off-by: Andrew Chant +Bug: 31252388 +--- + drivers/input/touchscreen/synaptics_fw_update.c | 144 ++++++++++++++++++------ + 1 file changed, 109 insertions(+), 35 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c +index 79b3a780550b8..ffa992b829a5a 100644 +--- a/drivers/input/touchscreen/synaptics_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_fw_update.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -296,6 +297,7 @@ struct synaptics_rmi4_fwu_handle { + static struct synaptics_rmi4_fwu_handle *fwu; + + DECLARE_COMPLETION(fwu_remove_complete); ++DEFINE_MUTEX(fwu_sysfs_mutex); + + static unsigned int extract_uint(const unsigned char *ptr) + { +@@ -1713,34 +1715,47 @@ static ssize_t fwu_sysfs_show_image(struct file *data_file, + char *buf, loff_t pos, size_t count) + { + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; ++ ssize_t retval; ++ ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + + if (count < fwu->config_size) { + dev_err(&rmi4_data->i2c_client->dev, + "%s: Not enough space (%zu bytes) in buffer\n", + __func__, count); +- return -EINVAL; ++ retval = -EINVAL; ++ goto show_image_exit; + } + + memcpy(buf, fwu->read_config_buf, fwu->config_size); +- +- return fwu->config_size; ++ retval = fwu->config_size; ++show_image_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) + { ++ ssize_t retval; ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (!fwu->ext_data_source) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot use this without setting imagesize!\n"); +- return -EAGAIN; ++ retval = -EAGAIN; ++ goto store_image_exit; + } + + if (count > fwu->image_size - fwu->data_pos) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "%s: Not enough space in buffer\n", + __func__); +- return -EINVAL; ++ retval = -EINVAL; ++ goto store_image_exit; + } + + memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]), +@@ -1749,8 +1764,11 @@ static ssize_t fwu_sysfs_store_image(struct file *data_file, + + fwu->data_buffer = fwu->ext_data_source; + fwu->data_pos += count; ++ retval = count; + +- return count; ++store_image_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_image_name_store(struct device *dev, +@@ -1758,11 +1776,15 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev, + { + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + char *strptr; ++ ssize_t retval; ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + + if (count >= NAME_BUFFER_SIZE) { + dev_err(&rmi4_data->i2c_client->dev, + "Input over %d characters long\n", NAME_BUFFER_SIZE); +- return -EINVAL; ++ retval = -EINVAL; ++ goto image_name_store_exit; + } + + strptr = strnstr(buf, ".img", +@@ -1770,21 +1792,32 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev, + if (!strptr) { + dev_err(&rmi4_data->i2c_client->dev, + "Input is not valid .img file\n"); +- return -EINVAL; ++ retval = -EINVAL; ++ goto image_name_store_exit; + } + + strlcpy(rmi4_data->fw_image_name, buf, count); +- return count; ++ retval = count; ++ ++image_name_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_image_name_show(struct device *dev, + struct device_attribute *attr, char *buf) + { ++ ssize_t retval; ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) > 0) +- return snprintf(buf, PAGE_SIZE, "%s\n", ++ retval = snprintf(buf, PAGE_SIZE, "%s\n", + fwu->rmi4_data->fw_image_name); + else +- return snprintf(buf, PAGE_SIZE, "No firmware name given\n"); ++ retval = snprintf(buf, PAGE_SIZE, "No firmware name given\n"); ++ ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_force_reflash_store(struct device *dev, +@@ -1794,14 +1827,17 @@ static ssize_t fwu_sysfs_force_reflash_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto force_reflash_store_exit; + } + + if (input != 1) { + retval = -EINVAL; +- goto exit; ++ goto force_reflash_store_exit; + } + if (LOCKDOWN) + fwu->do_lockdown = true; +@@ -1812,16 +1848,18 @@ static ssize_t fwu_sysfs_force_reflash_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to do reflash\n", + __func__); +- goto exit; ++ goto force_reflash_store_free_exit; + } + + retval = count; + +-exit: ++force_reflash_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = rmi4_data->board->do_lockdown; ++force_reflash_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -1832,9 +1870,12 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto reflash_store_exit; + } + + if (input & LOCKDOWN) { +@@ -1844,7 +1885,7 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + + if ((input != NORMAL) && (input != FORCE)) { + retval = -EINVAL; +- goto exit; ++ goto reflash_store_exit; + } + + if (input == FORCE) +@@ -1855,16 +1896,18 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to do reflash\n", + __func__); +- goto exit; ++ goto reflash_store_free_exit; + } + + retval = count; + +-exit: ++reflash_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = rmi4_data->board->do_lockdown; ++reflash_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -1875,26 +1918,31 @@ static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto lockdown_store_exit; + } + + if (input != 1) { + retval = -EINVAL; +- goto exit; ++ goto lockdown_store_exit; + } + + if (!fwu->ext_data_source) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot use this without loading image in manual way!\n"); +- return -EAGAIN; ++ retval = -EAGAIN; ++ goto lockdown_store_exit; + } + + if (fwu->rmi4_data->suspended == true) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot lockdown while device is in suspend\n"); +- return -EBUSY; ++ retval = -EBUSY; ++ goto lockdown_store_exit; + } + + retval = fwu_start_write_lockdown(); +@@ -1902,16 +1950,18 @@ static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to write lockdown block\n", + __func__); +- goto exit; ++ goto lockdown_store_free_exit; + } + + retval = count; + +-exit: ++lockdown_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = rmi4_data->board->do_lockdown; ++lockdown_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -1920,6 +1970,8 @@ static ssize_t fwu_sysfs_check_fw_store(struct device *dev, + { + unsigned int input = 0; + ++ /* Takes fwu_sysfs_mutex in the deferred work function. */ ++ + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + +@@ -1942,26 +1994,31 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto write_config_store_exit; + } + + if (input != 1) { + retval = -EINVAL; +- goto exit; ++ goto write_config_store_exit; + } + + if (!fwu->ext_data_source) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot use this without loading image in manual way!\n"); +- return -EAGAIN; ++ retval = -EAGAIN; ++ goto write_config_store_exit; + } + + if (fwu->rmi4_data->suspended == true) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot write config while device is in suspend\n"); +- return -EBUSY; ++ retval = -EBUSY; ++ goto write_config_store_exit; + } + + retval = fwu_start_write_config(); +@@ -1969,14 +2026,16 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to write config\n", + __func__); +- goto exit; ++ goto write_config_store_free_exit; + } + + retval = count; + +-exit: ++write_config_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; ++write_config_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -1999,7 +2058,11 @@ static ssize_t fwu_sysfs_read_config_store(struct device *dev, + return -EBUSY; + } + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + retval = fwu_do_read_config(); ++ mutex_unlock(&fwu_sysfs_mutex); ++ + if (retval < 0) { + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to read config\n", +@@ -2028,7 +2091,10 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev, + return -EINVAL; + } + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + fwu->config_area = config_area; ++ mutex_unlock(&fwu_sysfs_mutex); + + return count; + } +@@ -2039,10 +2105,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, + int retval; + unsigned long size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + + retval = kstrtoul(buf, 10, &size); + if (retval) +- return retval; ++ goto image_size_store_exit; + + fwu->image_size = size; + fwu->data_pos = 0; +@@ -2053,10 +2121,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to alloc mem for image data\n", + __func__); +- return -ENOMEM; ++ retval = -ENOMEM; + } + +- return count; ++image_size_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_block_size_show(struct device *dev, +@@ -2241,6 +2311,8 @@ static void synaptics_rmi4_fwu_work(struct work_struct *work) + container_of(to_delayed_work(work), + struct synaptics_rmi4_fwu_handle, fwu_work); + ++ mutex_lock(&fwu_sysfs_mutex); ++ + if (fwu->fn_ptr->enable) + fwu->fn_ptr->enable(fwu->rmi4_data, false); + +@@ -2248,6 +2320,8 @@ static void synaptics_rmi4_fwu_work(struct work_struct *work) + + if (fwu->fn_ptr->enable) + fwu->fn_ptr->enable(fwu->rmi4_data, true); ++ ++ mutex_unlock(&fwu_sysfs_mutex); + } + + static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) +@@ -2338,7 +2412,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work); + #endif + +- retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, ++ retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, + &dev_attr_data); + if (retval < 0) { + dev_err(&rmi4_data->i2c_client->dev, diff --git a/Patches/Linux_CVEs/CVE-2016-6745/2.patch b/Patches/Linux_CVEs/CVE-2016-6745/2.patch new file mode 100644 index 00000000..3002fc01 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6745/2.patch @@ -0,0 +1,71 @@ +From 8667cc5ed59b7a4b64d82d8014bead09bddb1f76 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Wed, 14 Sep 2016 19:28:37 -0700 +Subject: [PATCH] input: synaptics: defer sysfs creation during init + +sysfs entries are created which reference fwu->fwu_work. +defer the creation of these sysfs entries until the end of the init +function, after fwu->fwu_work has been initialized. + +Change-Id: I89bdf0088f98b4513d3f3c3c95ae967584dc5171 +Bug: 31252388 +Signed-off-by: Andrew Chant +--- + .../synaptics_dsx25/synaptics_dsx_fw_update.c | 25 ++++++++++++++-------- + 1 file changed, 16 insertions(+), 9 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 734baafa4cfa1..3edeaa22aa336 100755 +--- a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c +@@ -4131,13 +4131,20 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + fwu->do_lockdown = DO_LOCKDOWN; + fwu->initialized = true; + +- retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, ++#ifdef DO_STARTUP_FW_UPDATE ++ fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); ++ INIT_WORK(&fwu->fwu_work, fwu_startup_fw_update_work); ++ queue_work(fwu->fwu_workqueue, ++ &fwu->fwu_work); ++#endif ++ ++ 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", + __func__); +- goto exit_free_mem; ++ goto exit_destroy_work; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { +@@ -4152,13 +4159,6 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + } + } + +-#ifdef DO_STARTUP_FW_UPDATE +- fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); +- INIT_WORK(&fwu->fwu_work, fwu_startup_fw_update_work); +- queue_work(fwu->fwu_workqueue, +- &fwu->fwu_work); +-#endif +- + return 0; + + exit_remove_attrs: +@@ -4169,6 +4169,13 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + ++exit_destroy_work: ++#ifdef DO_STARTUP_FW_UPDATE ++ cancel_work_sync(&fwu->fwu_work); ++ flush_workqueue(fwu->fwu_workqueue); ++ destroy_workqueue(fwu->fwu_workqueue); ++#endif ++ + exit_free_mem: + kfree(fwu->image_name); + diff --git a/Patches/Linux_CVEs/CVE-2016-6745/3.patch b/Patches/Linux_CVEs/CVE-2016-6745/3.patch new file mode 100644 index 00000000..3b798db7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6745/3.patch @@ -0,0 +1,386 @@ +From 19055017169363f176693c3e41ebdfc3c8e11ef4 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Thu, 15 Sep 2016 12:10:56 -0700 +Subject: [PATCH] input: touchscreen: synaptics: prevent sysfs races + +Concurrent sysfs calls can cause ugly race conditions. +Return EBUSY on concurrent sysfs calls, and prevent sysfs calls +during initial fw load. + +Change-Id: I5e295c4cd7c3ba4b998de5b75f9b631679e7c39f +Signed-off-by: Andrew Chant +Bug: 31252388 +--- + .../synaptics_dsx25/synaptics_dsx_fw_update.c | 138 +++++++++++++++------ + 1 file changed, 99 insertions(+), 39 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 3edeaa22aa336..908693bd26a43 100755 +--- a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -654,6 +655,7 @@ static struct device_attribute attrs[] = { + static struct synaptics_rmi4_fwu_handle *fwu; + + DECLARE_COMPLETION(dsx_fwu_remove_complete); ++DEFINE_MUTEX(fwu_sysfs_mutex); + + static bool tp_2k_panel = false; + /** +@@ -3719,14 +3721,18 @@ static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) + { +- int retval; ++ ssize_t retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (count < fwu->config_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%zu bytes) in buffer\n", + __func__, count); +- return -EINVAL; ++ retval = -EINVAL; ++ goto show_image_exit; + } + + retval = secure_memcpy(buf, count, fwu->read_config_buf, +@@ -3735,43 +3741,56 @@ static ssize_t fwu_sysfs_show_image(struct file *data_file, + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy config data\n", + __func__); +- return retval; ++ goto show_image_exit; + } + +- return fwu->config_size; ++ retval = fwu->config_size; ++ ++show_image_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) + { +- int retval; ++ ssize_t retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + retval = secure_memcpy(&fwu->ext_data_source[fwu->data_pos], + fwu->image_size - fwu->data_pos, buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image data\n", + __func__); +- return retval; ++ goto store_image_exit; + } + + fwu->data_pos += count; ++ retval = count; + ++store_image_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return count; + } + + static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) + { +- int retval; ++ ssize_t retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto recovery_store_exit; + } + + if (!fwu->in_ub_mode) { +@@ -3779,28 +3798,32 @@ static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + "%s: Not in microbootloader mode\n", + __func__); + retval = -EINVAL; +- goto exit; ++ goto recovery_store_exit; + } + +- if (!fwu->ext_data_source) +- return -EINVAL; +- else ++ if (!fwu->ext_data_source) { ++ retval = -EINVAL; ++ goto recovery_store_exit; ++ } else { + fwu->image = fwu->ext_data_source; ++ } + + retval = fwu_start_recovery(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do recovery\n", + __func__); +- goto exit; ++ goto recovery_store_free_exit; + } + + retval = count; + +-exit: ++recovery_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; ++recovery_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -3811,15 +3834,20 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto reflash_store_exit; + } + +- if (!fwu->ext_data_source) +- return -EINVAL; +- else ++ if (!fwu->ext_data_source) { ++ retval = -EINVAL; ++ goto reflash_store_exit; ++ } else { + fwu->image = fwu->ext_data_source; ++ } + + if (input & LOCKDOWN) { + fwu->do_lockdown = true; +@@ -3828,7 +3856,7 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + + if ((input != NORMAL) && (input != FORCE)) { + retval = -EINVAL; +- goto exit; ++ goto reflash_store_exit; + } + + if (input == FORCE) +@@ -3839,17 +3867,19 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); +- goto exit; ++ goto reflash_store_free_exit; + } + + retval = count; + +-exit: ++reflash_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; ++reflash_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -3860,35 +3890,42 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto write_config_store_exit; + } + + if (input != 1) { + retval = -EINVAL; +- goto exit; ++ goto write_config_store_exit; + } + +- if (!fwu->ext_data_source) +- return -EINVAL; +- else ++ if (!fwu->ext_data_source) { ++ retval = -EINVAL; ++ goto write_config_store_exit; ++ } else { + fwu->image = fwu->ext_data_source; ++ } + + retval = fwu_start_write_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write config\n", + __func__); +- goto exit; ++ goto write_config_store_free_exit; + } + + retval = count; + +-exit: ++write_config_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; ++write_config_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -3905,7 +3942,11 @@ static ssize_t fwu_sysfs_read_config_store(struct device *dev, + if (input != 1) + return -EINVAL; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + retval = fwu_do_read_config(); ++ mutex_unlock(&fwu_sysfs_mutex); ++ + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read config\n", +@@ -3926,7 +3967,10 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev, + if (retval) + return retval; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + fwu->config_area = config_area; ++ mutex_unlock(&fwu_sysfs_mutex); + + return count; + } +@@ -3937,8 +3981,12 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev, + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + buf, count, count); ++ mutex_unlock(&fwu_sysfs_mutex); ++ + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", +@@ -3952,7 +4000,7 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev, + static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) + { +- int retval; ++ ssize_t retval; + unsigned long size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + +@@ -3960,6 +4008,9 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, + if (retval) + return retval; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + fwu->image_size = size; + fwu->data_pos = 0; + +@@ -3969,10 +4020,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image data\n", + __func__); +- return -ENOMEM; ++ retval = -ENOMEM; ++ } else { ++ retval = count; + } +- +- return count; ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_block_size_show(struct device *dev, +@@ -4024,35 +4077,42 @@ static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto guest_code_store_exit; + } + + if (input != 1) { + retval = -EINVAL; +- goto exit; ++ goto guest_code_store_exit; + } + +- if (!fwu->ext_data_source) +- return -EINVAL; +- else ++ if (!fwu->ext_data_source) { ++ retval = -EINVAL; ++ goto guest_code_store_exit; ++ } else { + fwu->image = fwu->ext_data_source; ++ } + + retval = fwu_start_write_guest_code(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write guest code\n", + __func__); +- goto exit; ++ goto guest_code_store_free_exit; + } + + retval = count; + +-exit: ++guest_code_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; ++guest_code_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + diff --git a/Patches/Linux_CVEs/CVE-2016-6745/4.patch b/Patches/Linux_CVEs/CVE-2016-6745/4.patch new file mode 100644 index 00000000..85373076 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6745/4.patch @@ -0,0 +1 @@ +Not Found \ No newline at end of file diff --git a/Patches/Linux_CVEs/CVE-2016-6748/0.patch b/Patches/Linux_CVEs/CVE-2016-6748/0.patch new file mode 100644 index 00000000..e6bc8818 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6748/0.patch @@ -0,0 +1,1739 @@ +From 313d9f89e76ada8d900c9a578cd5cb77d5813625 Mon Sep 17 00:00:00 2001 +From: Abdulla Anam +Date: Fri, 3 Jun 2016 17:39:42 +0530 +Subject: msm: vidc: use %pK instead of %p which respects kptr_restrict sysctl + +Hide kernel pointers from unprivileged ussers by using %pK format- +specifier instead of %p. This respects the kptr_restrict sysctl +setting which is by default on. So by default %pK will print zeroes +as address. echo 1 to kptr_restrict to print proper kernel addresses. + +CRs-Fixed: 987018 +Change-Id: I4772257a557c6730ecc0624cbc8e5614e893e9fd +Signed-off-by: Abdulla Anam +Signed-off-by: Bikshapathi Kothapeta +--- + .../msm/vidc/governors/msm_vidc_table_gov.c | 6 +- + .../media/platform/msm/vidc/hfi_packetization.c | 8 +- + .../media/platform/msm/vidc/hfi_response_handler.c | 8 +- + drivers/media/platform/msm/vidc/msm_smem.c | 32 +++--- + drivers/media/platform/msm/vidc/msm_v4l2_vidc.c | 6 +- + drivers/media/platform/msm/vidc/msm_vdec.c | 34 +++--- + drivers/media/platform/msm/vidc/msm_venc.c | 34 +++--- + drivers/media/platform/msm/vidc/msm_vidc.c | 30 ++--- + drivers/media/platform/msm/vidc/msm_vidc_common.c | 122 ++++++++++----------- + drivers/media/platform/msm/vidc/msm_vidc_dcvs.c | 16 +-- + drivers/media/platform/msm/vidc/msm_vidc_debug.c | 20 ++-- + .../media/platform/msm/vidc/msm_vidc_res_parse.c | 6 +- + drivers/media/platform/msm/vidc/venus_boot.c | 4 +- + drivers/media/platform/msm/vidc/venus_hfi.c | 52 ++++----- + drivers/media/platform/msm/vidc/vidc_hfi.c | 4 +- + drivers/media/platform/msm/vidc/vmem/vmem.c | 7 +- + 16 files changed, 194 insertions(+), 195 deletions(-) + +diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_table_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_table_gov.c +index f733c08..dded8a2 100644 +--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_table_gov.c ++++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_table_gov.c +@@ -90,7 +90,7 @@ static int msm_vidc_table_get_target_freq(struct devfreq *dev, + int i = 0; + + if (!dev || !frequency || !flag) { +- dprintk(VIDC_ERR, "%s: Invalid params %p, %p, %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid params %pK, %pK, %pK\n", + __func__, dev, frequency, flag); + return -EINVAL; + } +@@ -173,7 +173,7 @@ static int msm_vidc_free_bus_table(struct platform_device *pdev, + int rc = 0, i = 0; + + if (!pdev || !data) { +- dprintk(VIDC_ERR, "%s: invalid args %p %p\n", ++ dprintk(VIDC_ERR, "%s: invalid args %pK %pK\n", + __func__, pdev, data); + return -EINVAL; + } +@@ -197,7 +197,7 @@ static int msm_vidc_load_bus_table(struct platform_device *pdev, + struct device_node *child_node = NULL; + + if (!pdev || !data) { +- dprintk(VIDC_ERR, "%s: invalid args %p %p\n", ++ dprintk(VIDC_ERR, "%s: invalid args %pK %pK\n", + __func__, pdev, data); + return -EINVAL; + } +diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c +index 0d38aa9..90e4aa4 100644 +--- a/drivers/media/platform/msm/vidc/hfi_packetization.c ++++ b/drivers/media/platform/msm/vidc/hfi_packetization.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-201666666, The 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 +@@ -1439,7 +1439,7 @@ int create_pkt_cmd_session_set_property( + break; + default: + dprintk(VIDC_ERR, +- "Invalid Rate control setting: %p\n", ++ "Invalid Rate control setting: %pK\n", + pdata); + break; + } +@@ -2130,7 +2130,7 @@ int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type, + struct hfi_cmd_sys_test_ssr_packet *pkt) + { + if (!pkt) { +- dprintk(VIDC_ERR, "Invalid params, device: %p\n", pkt); ++ dprintk(VIDC_ERR, "Invalid params, device: %pK\n", pkt); + return -EINVAL; + } + pkt->size = sizeof(struct hfi_cmd_sys_test_ssr_packet); +@@ -2143,7 +2143,7 @@ int create_pkt_cmd_sys_image_version( + struct hfi_cmd_sys_get_property_packet *pkt) + { + if (!pkt) { +- dprintk(VIDC_ERR, "%s invalid param :%p\n", __func__, pkt); ++ dprintk(VIDC_ERR, "%s invalid param :%pK\n", __func__, pkt); + return -EINVAL; + } + pkt->size = sizeof(struct hfi_cmd_sys_get_property_packet); +diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c +index db0ea848a..91eab00 100644 +--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c ++++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -943,7 +943,7 @@ static enum vidc_status hfi_parse_init_done_properties( + } + default: + dprintk(VIDC_DBG, +- "%s: default case - data_ptr %p, prop_id 0x%x\n", ++ "%s: default case - data_ptr %pK, prop_id 0x%x\n", + __func__, data_ptr, prop_id); + break; + } +@@ -1043,7 +1043,7 @@ static void hfi_process_sess_get_prop_profile_level( + dprintk(VIDC_DBG, "Entered %s\n", __func__); + if (!prop) { + dprintk(VIDC_ERR, +- "hal_process_sess_get_profile_level: bad_prop: %p\n", ++ "hal_process_sess_get_profile_level: bad_prop: %pK\n", + prop); + return; + } +@@ -1074,7 +1074,7 @@ static void hfi_process_sess_get_prop_buf_req( + + if (!prop) { + dprintk(VIDC_ERR, +- "hal_process_sess_get_prop_buf_req: bad_prop: %p\n", ++ "hal_process_sess_get_prop_buf_req: bad_prop: %pK\n", + prop); + return; + } +diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c +index 009d827..f4724c9 100644 +--- a/drivers/media/platform/msm/vidc/msm_smem.c ++++ b/drivers/media/platform/msm/vidc/msm_smem.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -45,7 +45,7 @@ static int get_device_address(struct smem_client *smem_client, + struct context_bank_info *cb = NULL; + + if (!iova || !buffer_size || !hndl || !smem_client || !mapping_info) { +- dprintk(VIDC_ERR, "Invalid params: %p, %p, %p, %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK, %pK, %pK, %pK\n", + smem_client, hndl, iova, buffer_size); + return -EINVAL; + } +@@ -107,7 +107,7 @@ static int get_device_address(struct smem_client *smem_client, + } + if (table->sgl) { + dprintk(VIDC_DBG, +- "%s: CB : %s, DMA buf: %p, device: %p, attach: %p, table: %p, table sgl: %p, rc: %d, dma_address: %pa\n", ++ "%s: CB : %s, DMA buf: %pK, device: %pK, attach: %pK, table: %pK, table sgl: %pK, rc: %d, dma_address: %pa\n", + __func__, cb->name, buf, cb->dev, attach, + table, table->sgl, rc, + &table->sgl->dma_address); +@@ -137,7 +137,7 @@ static int get_device_address(struct smem_client *smem_client, + } + } + +- dprintk(VIDC_DBG, "mapped ion handle %p to %pa\n", hndl, iova); ++ dprintk(VIDC_DBG, "mapped ion handle %pK to %pa\n", hndl, iova); + return 0; + mem_map_sg_failed: + dma_buf_unmap_attachment(attach, table, DMA_BIDIRECTIONAL); +@@ -157,7 +157,7 @@ static void put_device_address(struct smem_client *smem_client, + struct ion_client *clnt = NULL; + + if (!hndl || !smem_client || !mapping_info) { +- dprintk(VIDC_WARN, "Invalid params: %p, %p\n", ++ dprintk(VIDC_WARN, "Invalid params: %pK, %pK\n", + smem_client, hndl); + return; + } +@@ -175,7 +175,7 @@ static void put_device_address(struct smem_client *smem_client, + } + if (is_iommu_present(smem_client->res)) { + dprintk(VIDC_DBG, +- "Calling dma_unmap_sg - device: %p, address: %pa, buf: %p, table: %p, attach: %p\n", ++ "Calling dma_unmap_sg - device: %pK, address: %pa, buf: %pK, table: %pK, attach: %pK\n", + mapping_info->dev, + &mapping_info->table->sgl->dma_address, + mapping_info->buf, mapping_info->table, +@@ -204,9 +204,9 @@ static int ion_user_to_kernel(struct smem_client *client, int fd, u32 offset, + unsigned long ion_flags = 0; + + hndl = ion_import_dma_buf(client->clnt, fd); +- dprintk(VIDC_DBG, "%s ion handle: %p\n", __func__, hndl); ++ dprintk(VIDC_DBG, "%s ion handle: %pK\n", __func__, hndl); + if (IS_ERR_OR_NULL(hndl)) { +- dprintk(VIDC_ERR, "Failed to get handle: %p, %d, %d, %p\n", ++ dprintk(VIDC_ERR, "Failed to get handle: %pK, %d, %d, %pK\n", + client, fd, offset, hndl); + rc = -ENOMEM; + goto fail_import_fd; +@@ -242,7 +242,7 @@ static int ion_user_to_kernel(struct smem_client *client, int fd, u32 offset, + goto fail_device_address; + } + dprintk(VIDC_DBG, +- "%s: ion_handle = %p, fd = %d, device_addr = %pa, size = %zx, kvaddr = %p, buffer_type = %d, flags = %#lx\n", ++ "%s: ion_handle = %pK, fd = %d, device_addr = %pa, size = %zx, kvaddr = %pK, buffer_type = %d, flags = %#lx\n", + __func__, mem->smem_priv, fd, &mem->device_addr, mem->size, + mem->kvaddr, mem->buffer_type, mem->flags); + return rc; +@@ -339,7 +339,7 @@ static int alloc_ion_mem(struct smem_client *client, size_t size, u32 align, + hndl = ion_alloc(client->clnt, size, align, heap_mask, ion_flags); + if (IS_ERR_OR_NULL(hndl)) { + dprintk(VIDC_ERR, +- "Failed to allocate shared memory = %p, %zx, %d, %#x\n", ++ "Failed to allocate shared memory = %pK, %zx, %d, %#x\n", + client, size, align, flags); + rc = -ENOMEM; + goto fail_shared_mem_alloc; +@@ -377,7 +377,7 @@ static int alloc_ion_mem(struct smem_client *client, size_t size, u32 align, + } + mem->size = size; + dprintk(VIDC_DBG, +- "%s: ion_handle = %p, device_addr = %pa, size = %#zx, kvaddr = %p, buffer_type = %#x, flags = %#lx\n", ++ "%s: ion_handle = %pK, device_addr = %pa, size = %#zx, kvaddr = %pK, buffer_type = %#x, flags = %#lx\n", + __func__, mem->smem_priv, &mem->device_addr, + mem->size, mem->kvaddr, mem->buffer_type, mem->flags); + return rc; +@@ -393,7 +393,7 @@ fail_shared_mem_alloc: + static void free_ion_mem(struct smem_client *client, struct msm_smem *mem) + { + dprintk(VIDC_DBG, +- "%s: ion_handle = %p, device_addr = %pa, size = %#zx, kvaddr = %p, buffer_type = %#x\n", ++ "%s: ion_handle = %pK, device_addr = %pa, size = %#zx, kvaddr = %pK, buffer_type = %#x\n", + __func__, mem->smem_priv, &mem->device_addr, + mem->size, mem->kvaddr, mem->buffer_type); + +@@ -408,7 +408,7 @@ static void free_ion_mem(struct smem_client *client, struct msm_smem *mem) + (u32)mem->buffer_type, -1, mem->size, -1, + mem->flags, -1); + dprintk(VIDC_DBG, +- "%s: Freeing handle %p, client: %p\n", ++ "%s: Freeing handle %pK, client: %pK\n", + __func__, mem->smem_priv, client->clnt); + ion_free(client->clnt, mem->smem_priv); + trace_msm_smem_buffer_ion_op_end("FREE", (u32)mem->buffer_type, +@@ -469,7 +469,7 @@ static int ion_cache_operations(struct smem_client *client, + int rc = 0; + int msm_cache_ops = 0; + if (!mem || !client) { +- dprintk(VIDC_ERR, "Invalid params: %p, %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK, %pK\n", + mem, client); + return -EINVAL; + } +@@ -516,7 +516,7 @@ int msm_smem_cache_operations(void *clt, struct msm_smem *mem, + struct smem_client *client = clt; + int rc = 0; + if (!client) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", + client); + return -EINVAL; + } +@@ -667,7 +667,7 @@ struct context_bank_info *msm_smem_get_context_bank(void *clt, + cb->buffer_type & buffer_type) { + match = cb; + dprintk(VIDC_DBG, +- "context bank found for CB : %s, device: %p mapping: %p\n", ++ "context bank found for CB : %s, device: %pK mapping: %pK\n", + match->name, match->dev, match->mapping); + break; + } +diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +index 0f7ddf5..4ef6cb5 100644 +--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c ++++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -279,7 +279,7 @@ static int read_platform_resources(struct msm_vidc_core *core, + struct platform_device *pdev) + { + if (!core || !pdev) { +- dprintk(VIDC_ERR, "%s: Invalid params %p %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid params %pK %pK\n", + __func__, core, pdev); + return -EINVAL; + } +@@ -608,7 +608,7 @@ static int msm_vidc_remove(struct platform_device *pdev) + struct msm_vidc_core *core; + + if (!pdev) { +- dprintk(VIDC_ERR, "%s invalid input %p", __func__, pdev); ++ dprintk(VIDC_ERR, "%s invalid input %pK", __func__, pdev); + return -EINVAL; + } + +diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c +index 34a2130..99b14f4 100644 +--- a/drivers/media/platform/msm/vidc/msm_vdec.c ++++ b/drivers/media/platform/msm/vidc/msm_vdec.c +@@ -891,7 +891,7 @@ int msm_vdec_prepare_buf(struct msm_vidc_inst *inst, + if (inst->state == MSM_VIDC_CORE_INVALID || + inst->core->state == VIDC_CORE_INVALID) { + dprintk(VIDC_ERR, +- "Core %p in bad state, ignoring prepare buf\n", ++ "Core %pK in bad state, ignoring prepare buf\n", + inst->core); + goto exit; + } +@@ -970,7 +970,7 @@ int msm_vdec_release_buf(struct msm_vidc_inst *inst, + if (inst->state == MSM_VIDC_CORE_INVALID || + core->state == VIDC_CORE_INVALID) { + dprintk(VIDC_ERR, +- "Core %p in bad state, ignoring release output buf\n", ++ "Core %pK in bad state, ignoring release output buf\n", + core); + goto exit; + } +@@ -1068,7 +1068,7 @@ int msm_vdec_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b) + + if (!inst || !b) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, buffer = %p\n", inst, b); ++ "Invalid input, inst = %pK, buffer = %pK\n", inst, b); + return -EINVAL; + } + +@@ -1098,7 +1098,7 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) + + if (!inst || !f || !inst->core || !inst->core->device) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, format = %p\n", inst, f); ++ "Invalid input, inst = %pK, format = %pK\n", inst, f); + return -EINVAL; + } + +@@ -1545,7 +1545,7 @@ int msm_vdec_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap) + { + if (!inst || !cap) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, cap = %p\n", inst, cap); ++ "Invalid input, inst = %pK, cap = %pK\n", inst, cap); + return -EINVAL; + } + strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver)); +@@ -1565,7 +1565,7 @@ int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) + int rc = 0; + if (!inst || !f) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, f = %p\n", inst, f); ++ "Invalid input, inst = %pK, f = %pK\n", inst, f); + return -EINVAL; + } + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { +@@ -1623,7 +1623,7 @@ static int msm_vdec_queue_setup(struct vb2_queue *q, + + if (!q || !num_buffers || !num_planes + || !sizes || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n", ++ dprintk(VIDC_ERR, "Invalid input, q = %pK, %pK, %pK\n", + q, num_buffers, num_planes); + return -EINVAL; + } +@@ -1903,7 +1903,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) + rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto fail_start; + } + msm_dcvs_init_load(inst); +@@ -1927,7 +1927,7 @@ static inline int stop_streaming(struct msm_vidc_inst *inst) + rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE); + if (rc) + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + return rc; + } + +@@ -1937,7 +1937,7 @@ static int msm_vdec_start_streaming(struct vb2_queue *q, unsigned int count) + int rc = 0; + struct hfi_device *hdev; + if (!q || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p\n", q); ++ dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); + return -EINVAL; + } + inst = q->drv_priv; +@@ -1946,7 +1946,7 @@ static int msm_vdec_start_streaming(struct vb2_queue *q, unsigned int count) + return -EINVAL; + } + hdev = inst->core->device; +- dprintk(VIDC_DBG, "Streamon called on: %d capability for inst: %p\n", ++ dprintk(VIDC_DBG, "Streamon called on: %d capability for inst: %pK\n", + q->type, inst); + switch (q->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +@@ -1964,7 +1964,7 @@ static int msm_vdec_start_streaming(struct vb2_queue *q, unsigned int count) + } + if (rc) { + dprintk(VIDC_ERR, +- "Streamon failed on: %d capability for inst: %p\n", ++ "Streamon failed on: %d capability for inst: %pK\n", + q->type, inst); + goto stream_start_failed; + } +@@ -1986,7 +1986,7 @@ static void msm_vdec_stop_streaming(struct vb2_queue *q) + struct msm_vidc_inst *inst; + int rc = 0; + if (!q || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p\n", q); ++ dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); + return; + } + +@@ -2012,7 +2012,7 @@ static void msm_vdec_stop_streaming(struct vb2_queue *q) + + if (rc) + dprintk(VIDC_ERR, +- "Failed to move inst: %p, cap = %d to state: %d\n", ++ "Failed to move inst: %pK, cap = %d to state: %d\n", + inst, q->type, MSM_VIDC_RELEASE_RESOURCES_DONE); + } + +@@ -2039,7 +2039,7 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) + { + int rc = 0; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid input = %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid input = %pK\n", inst); + return -EINVAL; + } + inst->fmts[OUTPUT_PORT] = &vdec_formats[2]; +@@ -2767,7 +2767,7 @@ static int msm_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) + rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto failed_open_done; + } + +@@ -2796,7 +2796,7 @@ static int msm_vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl) + rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto failed_open_done; + } + for (c = 0; c < master->ncontrols; ++c) { +diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c +index 2809d06..9589b57 100644 +--- a/drivers/media/platform/msm/vidc/msm_venc.c ++++ b/drivers/media/platform/msm/vidc/msm_venc.c +@@ -1634,13 +1634,13 @@ static inline int msm_venc_power_save_mode_enable(struct msm_vidc_inst *inst) + (void *)inst->session, prop_id, pdata); + if (rc) { + dprintk(VIDC_ERR, +- "%s: Failed to set power save mode for inst: %p\n", ++ "%s: Failed to set power save mode for inst: %pK\n", + __func__, inst); + goto fail_power_mode_set; + } + inst->flags |= VIDC_LOW_POWER; + msm_dcvs_enc_set_power_save_mode(inst, true); +- dprintk(VIDC_INFO, "Power Save Mode set for inst: %p\n", inst); ++ dprintk(VIDC_INFO, "Power Save Mode set for inst: %pK\n", inst); + } + + fail_power_mode_set: +@@ -1685,7 +1685,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) + rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto fail_start; + } + msm_dcvs_init_load(inst); +@@ -1699,11 +1699,11 @@ static int msm_venc_start_streaming(struct vb2_queue *q, unsigned int count) + struct msm_vidc_inst *inst; + int rc = 0; + if (!q || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p\n", q); ++ dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); + return -EINVAL; + } + inst = q->drv_priv; +- dprintk(VIDC_DBG, "Streamon called on: %d capability for inst: %p\n", ++ dprintk(VIDC_DBG, "Streamon called on: %d capability for inst: %pK\n", + q->type, inst); + switch (q->type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: +@@ -1721,7 +1721,7 @@ static int msm_venc_start_streaming(struct vb2_queue *q, unsigned int count) + } + if (rc) { + dprintk(VIDC_ERR, +- "Streamon failed on: %d capability for inst: %p\n", ++ "Streamon failed on: %d capability for inst: %pK\n", + q->type, inst); + goto stream_start_failed; + } +@@ -1743,7 +1743,7 @@ static void msm_venc_stop_streaming(struct vb2_queue *q) + struct msm_vidc_inst *inst; + int rc = 0; + if (!q || !q->drv_priv) { +- dprintk(VIDC_ERR, "%s - Invalid input, q = %p\n", __func__, q); ++ dprintk(VIDC_ERR, "%s - Invalid input, q = %pK\n", __func__, q); + return; + } + +@@ -1765,7 +1765,7 @@ static void msm_venc_stop_streaming(struct vb2_queue *q) + + if (rc) + dprintk(VIDC_ERR, +- "Failed to move inst: %p, cap = %d to state: %d\n", ++ "Failed to move inst: %pK, cap = %d to state: %d\n", + inst, q->type, MSM_VIDC_CLOSE_DONE); + } + +@@ -3271,7 +3271,7 @@ static int msm_venc_op_s_ctrl(struct v4l2_ctrl *ctrl) + + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto failed_open_done; + } + +@@ -3315,7 +3315,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) + { + int rc = 0; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid input = %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid input = %pK\n", inst); + return -EINVAL; + } + inst->fmts[CAPTURE_PORT] = &venc_formats[4]; +@@ -3359,7 +3359,7 @@ int msm_venc_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap) + { + if (!inst || !cap) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, cap = %p\n", inst, cap); ++ "Invalid input, inst = %pK, cap = %pK\n", inst, cap); + return -EINVAL; + } + strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver)); +@@ -3379,7 +3379,7 @@ int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) + int rc = 0; + if (!inst || !f) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, f = %p\n", inst, f); ++ "Invalid input, inst = %pK, f = %pK\n", inst, f); + return -EINVAL; + } + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { +@@ -3436,7 +3436,7 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) + struct hfi_device *hdev; + if (!inst || !f) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, format = %p\n", inst, f); ++ "Invalid input, inst = %pK, format = %pK\n", inst, f); + return -EINVAL; + } + +@@ -3583,7 +3583,7 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) + + if (!inst || !f) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, format = %p\n", inst, f); ++ "Invalid input, inst = %pK, format = %pK\n", inst, f); + return -EINVAL; + } + +@@ -3656,7 +3656,7 @@ int msm_venc_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b) + int rc = 0; + if (!inst || !b) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, buffer = %p\n", inst, b); ++ "Invalid input, inst = %pK, buffer = %pK\n", inst, b); + return -EINVAL; + } + q = msm_comm_get_vb2q(inst, b->type); +@@ -3693,7 +3693,7 @@ int msm_venc_prepare_buf(struct msm_vidc_inst *inst, + if (inst->state == MSM_VIDC_CORE_INVALID || + inst->core->state == VIDC_CORE_INVALID) { + dprintk(VIDC_ERR, +- "Core %p in bad state, ignoring prepare buf\n", ++ "Core %pK in bad state, ignoring prepare buf\n", + inst->core); + goto exit; + } +@@ -3764,7 +3764,7 @@ int msm_venc_release_buf(struct msm_vidc_inst *inst, + rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to release res done state\n", ++ "Failed to move inst: %pK to release res done state\n", + inst); + goto exit; + } +diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c +index 904ced9..7e186f6 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc.c +@@ -285,7 +285,7 @@ struct buffer_info *device_to_uvaddr(struct msm_vidc_list *buf_list, + + if (!buf_list || !device_addr) { + dprintk(VIDC_ERR, +- "Invalid input- device_addr: %pa buf_list: %p\n", ++ "Invalid input- device_addr: %pa buf_list: %pK\n", + &device_addr, buf_list); + goto err_invalid_input; + } +@@ -425,7 +425,7 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b) + goto exit; + } + +- dprintk(VIDC_DBG, "[MAP] Create binfo = %p fd = %d type = %d\n", ++ dprintk(VIDC_DBG, "[MAP] Create binfo = %pK fd = %d type = %d\n", + binfo, b->m.planes[0].reserved[0], b->type); + + for (i = 0; i < b->length; ++i) { +@@ -515,7 +515,7 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b) + goto exit; + } + dprintk(VIDC_DBG, +- "%s: [MAP] binfo = %p, handle[%d] = %p, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n", ++ "%s: [MAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n", + __func__, binfo, i, binfo->handle[i], + &binfo->device_addr[i], binfo->fd[i], + binfo->buff_off[i], binfo->mapped[i]); +@@ -538,7 +538,7 @@ int unmap_and_deregister_buf(struct msm_vidc_inst *inst, + bool found = false, keep_node = false; + + if (!inst || !binfo) { +- dprintk(VIDC_ERR, "%s invalid param: %p %p\n", ++ dprintk(VIDC_ERR, "%s invalid param: %pK %pK\n", + __func__, inst, binfo); + return -EINVAL; + } +@@ -568,7 +568,7 @@ int unmap_and_deregister_buf(struct msm_vidc_inst *inst, + + for (i = 0; i < temp->num_planes; i++) { + dprintk(VIDC_DBG, +- "%s: [UNMAP] binfo = %p, handle[%d] = %p, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n", ++ "%s: [UNMAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n", + __func__, temp, i, temp->handle[i], + &temp->device_addr[i], temp->fd[i], + temp->buff_off[i], temp->mapped[i]); +@@ -597,12 +597,12 @@ int unmap_and_deregister_buf(struct msm_vidc_inst *inst, + } + } + if (!keep_node) { +- dprintk(VIDC_DBG, "[UNMAP] AND-FREED binfo: %p\n", temp); ++ dprintk(VIDC_DBG, "[UNMAP] AND-FREED binfo: %pK\n", temp); + list_del(&temp->list); + kfree(temp); + } else { + temp->inactive = true; +- dprintk(VIDC_DBG, "[UNMAP] NOT-FREED binfo: %p\n", temp); ++ dprintk(VIDC_DBG, "[UNMAP] NOT-FREED binfo: %pK\n", temp); + } + exit: + return 0; +@@ -616,7 +616,7 @@ int qbuf_dynamic_buf(struct msm_vidc_inst *inst, + struct v4l2_plane plane[VIDEO_MAX_PLANES] = { {0} }; + + if (!binfo) { +- dprintk(VIDC_ERR, "%s invalid param: %p\n", __func__, binfo); ++ dprintk(VIDC_ERR, "%s invalid param: %pK\n", __func__, binfo); + return -EINVAL; + } + dprintk(VIDC_DBG, "%s fd[0] = %d\n", __func__, binfo->fd[0]); +@@ -639,12 +639,12 @@ int output_buffer_cache_invalidate(struct msm_vidc_inst *inst, + int rc = 0; + + if (!inst) { +- dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst); + return -EINVAL; + } + + if (!binfo) { +- dprintk(VIDC_ERR, "%s: invalid buffer info: %p\n", ++ dprintk(VIDC_ERR, "%s: invalid buffer info: %pK\n", + __func__, inst); + return -EINVAL; + } +@@ -720,7 +720,7 @@ int msm_vidc_release_buffers(void *instance, int buffer_type) + rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to release res done\n", ++ "Failed to move inst: %pK to release res done\n", + inst); + } + } +@@ -784,7 +784,7 @@ free_and_unmap: + for (i = 0; i < bi->num_planes; i++) { + if (bi->handle[i] && bi->mapped[i]) { + dprintk(VIDC_DBG, +- "%s: [UNMAP] binfo = %p, handle[%d] = %p, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n", ++ "%s: [UNMAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n", + __func__, bi, i, bi->handle[i], + &bi->device_addr[i], bi->fd[i], + bi->buff_off[i], bi->mapped[i]); +@@ -986,7 +986,7 @@ int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize) + struct msm_vidc_capability *capability = NULL; + + if (!inst || !fsize) { +- dprintk(VIDC_ERR, "%s: invalid parameter: %p %p\n", ++ dprintk(VIDC_ERR, "%s: invalid parameter: %pK %pK\n", + __func__, inst, fsize); + return -EINVAL; + } +@@ -1148,7 +1148,7 @@ void *msm_vidc_open(int core_id, int session_type) + goto err_invalid_core; + } + +- pr_info(VIDC_DBG_TAG "Opening video instance: %p, %d\n", ++ pr_info(VIDC_DBG_TAG "Opening video instance: %pK, %d\n", + VIDC_MSG_PRIO2STRING(VIDC_INFO), inst, session_type); + mutex_init(&inst->sync_lock); + mutex_init(&inst->bufq[CAPTURE_PORT].lock); +@@ -1314,7 +1314,7 @@ int msm_vidc_destroy(struct msm_vidc_inst *inst) + for (i = 0; i < MAX_PORT_NUM; i++) + vb2_queue_release(&inst->bufq[i].vb2_bufq); + +- pr_info(VIDC_DBG_TAG "Closed video instance: %p\n", ++ pr_info(VIDC_DBG_TAG "Closed video instance: %pK\n", + VIDC_MSG_PRIO2STRING(VIDC_INFO), inst); + kfree(inst); + return 0; +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c +index 1eed94b..5a9e6d2 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c +@@ -303,7 +303,7 @@ int msm_comm_get_inst_load(struct msm_vidc_inst *inst, + if (is_non_realtime_session(inst) && + (quirks & LOAD_CALC_IGNORE_NON_REALTIME_LOAD)) { + if (!inst->prop.fps) { +- dprintk(VIDC_INFO, "instance:%p fps = 0\n", inst); ++ dprintk(VIDC_INFO, "instance:%pK fps = 0\n", inst); + load = 0; + } else { + load = msm_comm_get_mbs_per_sec(inst) / inst->prop.fps; +@@ -322,7 +322,7 @@ int msm_comm_get_load(struct msm_vidc_core *core, + int num_mbs_per_sec = 0; + + if (!core) { +- dprintk(VIDC_ERR, "Invalid args: %p\n", core); ++ dprintk(VIDC_ERR, "Invalid args: %pK\n", core); + return -EINVAL; + } + +@@ -451,13 +451,13 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core) + unsigned long core_freq = 0; + + if (!core) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, core); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, core); + return -EINVAL; + } + + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "%s Invalid device handle: %p\n", ++ dprintk(VIDC_ERR, "%s Invalid device handle: %pK\n", + __func__, hdev); + return -EINVAL; + } +@@ -569,7 +569,7 @@ const struct msm_vidc_format *msm_comm_get_pixel_fmt_index( + { + int i, k = 0; + if (!fmt || index < 0) { +- dprintk(VIDC_ERR, "Invalid inputs, fmt = %p, index = %d\n", ++ dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK, index = %d\n", + fmt, index); + return NULL; + } +@@ -591,7 +591,7 @@ struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc( + { + int i; + if (!fmt) { +- dprintk(VIDC_ERR, "Invalid inputs, fmt = %p\n", fmt); ++ dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK\n", fmt); + return NULL; + } + for (i = 0; i < size; i++) { +@@ -819,11 +819,11 @@ static void change_inst_state(struct msm_vidc_inst *inst, + mutex_lock(&inst->lock); + if (inst->state == MSM_VIDC_CORE_INVALID) { + dprintk(VIDC_DBG, +- "Inst: %p is in bad state can't change state to %d\n", ++ "Inst: %pK is in bad state can't change state to %d\n", + inst, state); + goto exit; + } +- dprintk(VIDC_DBG, "Moved inst: %p from state: %d to state: %d\n", ++ dprintk(VIDC_DBG, "Moved inst: %pK from state: %d to state: %d\n", + inst, inst->state, state); + inst->state = state; + exit: +@@ -834,7 +834,7 @@ static int signal_session_msg_receipt(enum hal_command_response cmd, + struct msm_vidc_inst *inst) + { + if (!inst) { +- dprintk(VIDC_ERR, "Invalid(%p) instance id\n", inst); ++ dprintk(VIDC_ERR, "Invalid(%pK) instance id\n", inst); + return -EINVAL; + } + if (IS_HAL_SESSION_CMD(cmd)) { +@@ -877,7 +877,7 @@ static int wait_for_state(struct msm_vidc_inst *inst, + { + int rc = 0; + if (IS_ALREADY_IN_STATE(flipped_state, desired_state)) { +- dprintk(VIDC_INFO, "inst: %p is already in state: %d\n", ++ dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n", + inst, inst->state); + goto err_same_state; + } +@@ -1083,7 +1083,7 @@ static void handle_event_change(enum hal_command_response cmd, void *data) + struct buffer_info *binfo = NULL, *temp = NULL; + u32 *ptr = NULL; + +- dprintk(VIDC_DBG, "%s - inst: %p buffer: %pa extra: %pa\n", ++ dprintk(VIDC_DBG, "%s - inst: %pK buffer: %pa extra: %pa\n", + __func__, inst, &event_notify->packet_buffer, + &event_notify->extra_data_buffer); + +@@ -1479,11 +1479,11 @@ static void handle_session_error(enum hal_command_response cmd, void *data) + } + + hdev = inst->core->device; +- dprintk(VIDC_WARN, "Session error received for session %p\n", inst); ++ dprintk(VIDC_WARN, "Session error received for session %pK\n", inst); + change_inst_state(inst, MSM_VIDC_CORE_INVALID); + + if (response->status == VIDC_ERR_MAX_CLIENTS) { +- dprintk(VIDC_WARN, "Too many clients, rejecting %p", inst); ++ dprintk(VIDC_WARN, "Too many clients, rejecting %pK", inst); + event = V4L2_EVENT_MSM_VIDC_MAX_CLIENTS; + + /* +@@ -1495,10 +1495,10 @@ static void handle_session_error(enum hal_command_response cmd, void *data) + + msm_comm_session_clean(inst); + } else if (response->status == VIDC_ERR_NOT_SUPPORTED) { +- dprintk(VIDC_WARN, "Unsupported bitstream in %p", inst); ++ dprintk(VIDC_WARN, "Unsupported bitstream in %pK", inst); + event = V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED; + } else { +- dprintk(VIDC_WARN, "Unknown session error (%d) for %p\n", ++ dprintk(VIDC_WARN, "Unknown session error (%d) for %pK\n", + response->status, inst); + event = V4L2_EVENT_MSM_VIDC_SYS_ERROR; + } +@@ -1515,7 +1515,7 @@ static void msm_comm_clean_notify_client(struct msm_vidc_core *core) + return; + } + +- dprintk(VIDC_WARN, "%s: Core %p\n", __func__, core); ++ dprintk(VIDC_WARN, "%s: Core %pK\n", __func__, core); + mutex_lock(&core->lock); + core->state = VIDC_CORE_INVALID; + +@@ -1524,7 +1524,7 @@ static void msm_comm_clean_notify_client(struct msm_vidc_core *core) + inst->state = MSM_VIDC_CORE_INVALID; + mutex_unlock(&inst->lock); + dprintk(VIDC_WARN, +- "%s Send sys error for inst %p\n", __func__, inst); ++ "%s Send sys error for inst %pK\n", __func__, inst); + msm_vidc_queue_v4l2_event(inst, + V4L2_EVENT_MSM_VIDC_SYS_ERROR); + } +@@ -1552,7 +1552,7 @@ static void handle_sys_error(enum hal_command_response cmd, void *data) + return; + } + +- dprintk(VIDC_WARN, "SYS_ERROR %d received for core %p\n", cmd, core); ++ dprintk(VIDC_WARN, "SYS_ERROR %d received for core %pK\n", cmd, core); + msm_comm_clean_notify_client(core); + + hdev = core->device; +@@ -1584,12 +1584,12 @@ void msm_comm_session_clean(struct msm_vidc_inst *inst) + hdev = inst->core->device; + mutex_lock(&inst->lock); + if (hdev && inst->session) { +- dprintk(VIDC_DBG, "cleaning up instance: %p\n", inst); ++ dprintk(VIDC_DBG, "cleaning up instance: %pK\n", inst); + rc = call_hfi_op(hdev, session_clean, + (void *)inst->session); + if (rc) { + dprintk(VIDC_ERR, +- "Session clean failed :%p\n", inst); ++ "Session clean failed :%pK\n", inst); + } + inst->session = NULL; + } +@@ -2003,7 +2003,7 @@ static void handle_fbd(enum hal_command_response cmd, void *data) + + if (extra_idx && extra_idx < VIDEO_MAX_PLANES) { + dprintk(VIDC_DBG, +- "extradata: userptr = %p;" ++ "extradata: userptr = %pK;" + " bytesused = %d; length = %d\n", + (u8 *)vb->v4l2_planes[extra_idx].m.userptr, + vb->v4l2_planes[extra_idx].bytesused, +@@ -2159,13 +2159,13 @@ int msm_comm_scale_clocks_load(struct msm_vidc_core *core, + int codec = 0; + + if (!core) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, core); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, core); + return -EINVAL; + } + + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "%s Invalid device handle: %p\n", ++ dprintk(VIDC_ERR, "%s Invalid device handle: %pK\n", + __func__, hdev); + return -EINVAL; + } +@@ -2339,7 +2339,7 @@ static int msm_comm_session_abort(struct msm_vidc_inst *inst) + msecs_to_jiffies(msm_vidc_hw_rsp_timeout)); + if (!rc) { + dprintk(VIDC_ERR, +- "%s: Wait interrupted or timed out [%p]: %d\n", ++ "%s: Wait interrupted or timed out [%pK]: %d\n", + __func__, inst, abort_completion); + BUG_ON(msm_vidc_debug_timeout); + rc = -EBUSY; +@@ -2367,7 +2367,7 @@ static void handle_thermal_event(struct msm_vidc_core *core) + mutex_unlock(&core->lock); + if (inst->state >= MSM_VIDC_OPEN_DONE && + inst->state < MSM_VIDC_CLOSE_DONE) { +- dprintk(VIDC_WARN, "%s: abort inst %p\n", ++ dprintk(VIDC_WARN, "%s: abort inst %pK\n", + __func__, inst); + rc = msm_comm_session_abort(inst); + if (rc) { +@@ -2378,7 +2378,7 @@ static void handle_thermal_event(struct msm_vidc_core *core) + } + change_inst_state(inst, MSM_VIDC_CORE_INVALID); + dprintk(VIDC_WARN, +- "%s Send sys error for inst %p\n", ++ "%s Send sys error for inst %pK\n", + __func__, inst); + msm_vidc_queue_v4l2_event(inst, + V4L2_EVENT_MSM_VIDC_SYS_ERROR); +@@ -2578,7 +2578,7 @@ static int msm_comm_session_init(int flipped_state, + hdev = inst->core->device; + + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_OPEN)) { +- dprintk(VIDC_INFO, "inst: %p is already in state: %d\n", ++ dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2600,7 +2600,7 @@ static int msm_comm_session_init(int flipped_state, + + if (rc || !inst->session) { + dprintk(VIDC_ERR, +- "Failed to call session init for: %p, %p, %d, %d\n", ++ "Failed to call session init for: %pK, %pK, %d, %d\n", + inst->core->device, inst, + inst->session_type, fourcc); + rc = -EINVAL; +@@ -2689,7 +2689,7 @@ static int msm_vidc_load_resources(int flipped_state, + + hdev = core->device; + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) { +- dprintk(VIDC_INFO, "inst: %p is already in state: %d\n", ++ dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2725,7 +2725,7 @@ static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst) + + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) { + dprintk(VIDC_INFO, +- "inst: %p is already in state: %d\n", ++ "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2755,7 +2755,7 @@ static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst) + + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) { + dprintk(VIDC_INFO, +- "inst: %p is already in state: %d\n", ++ "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2785,7 +2785,7 @@ static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst) + + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) { + dprintk(VIDC_INFO, +- "inst: %p is already in state: %d\n", ++ "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2817,7 +2817,7 @@ static int msm_comm_session_close(int flipped_state, + hdev = inst->core->device; + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) { + dprintk(VIDC_INFO, +- "inst: %p is already in state: %d\n", ++ "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -3221,16 +3221,16 @@ int msm_comm_try_state(struct msm_vidc_inst *inst, int state) + struct msm_vidc_core *core; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + dprintk(VIDC_DBG, +- "Trying to move inst: %p from: %#x to %#x\n", ++ "Trying to move inst: %pK from: %#x to %#x\n", + inst, inst->state, state); + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", inst); ++ "Invalid core pointer = %pK\n", inst); + return -EINVAL; + } + mutex_lock(&inst->sync_lock); +@@ -3636,7 +3636,7 @@ int msm_comm_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb) + defer = defer ?: batch_mode && (!output_count || !capture_count); + + if (defer) { +- dprintk(VIDC_DBG, "Deferring queue of %p\n", vb); ++ dprintk(VIDC_DBG, "Deferring queue of %pK\n", vb); + return 0; + } + +@@ -3844,7 +3844,7 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype, + */ + + dprintk(VIDC_ERR, +- "In Wrong state to call Buf Req: Inst %p or Core %p\n", ++ "In Wrong state to call Buf Req: Inst %pK or Core %pK\n", + inst, inst->core); + rc = -EAGAIN; + mutex_unlock(&inst->sync_lock); +@@ -3879,7 +3879,7 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype, + msecs_to_jiffies(msm_vidc_hw_rsp_timeout)); + if (!rc) { + dprintk(VIDC_ERR, +- "%s: Wait interrupted or timed out [%p]: %d\n", ++ "%s: Wait interrupted or timed out [%pK]: %d\n", + __func__, inst, + SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO)); + inst->state = MSM_VIDC_CORE_INVALID; +@@ -3919,7 +3919,7 @@ int msm_comm_release_output_buffers(struct msm_vidc_inst *inst) + struct hfi_device *hdev; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + mutex_lock(&inst->outputbufs.lock); +@@ -3934,12 +3934,12 @@ int msm_comm_release_output_buffers(struct msm_vidc_inst *inst) + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", core); ++ "Invalid core pointer = %pK\n", core); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev); ++ dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev); + return -EINVAL; + } + mutex_lock(&inst->outputbufs.lock); +@@ -4035,18 +4035,18 @@ int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst, + enum hal_buffer sufficiency = HAL_BUFFER_NONE; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", core); ++ "Invalid core pointer = %pK\n", core); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev); ++ dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev); + return -EINVAL; + } + +@@ -4123,18 +4123,18 @@ int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst) + struct hfi_device *hdev; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", core); ++ "Invalid core pointer = %pK\n", core); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev); ++ dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev); + return -EINVAL; + } + +@@ -4183,7 +4183,7 @@ int msm_comm_try_set_prop(struct msm_vidc_inst *inst, + int rc = 0; + struct hfi_device *hdev; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid input: %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid input: %pK\n", inst); + return -EINVAL; + } + +@@ -4395,7 +4395,7 @@ void msm_comm_flush_pending_dynamic_buffers(struct msm_vidc_inst *inst) + list_for_each_entry(binfo, &inst->registeredbufs.list, list) { + if (binfo->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + dprintk(VIDC_DBG, +- "%s: binfo = %p device_addr = %pa\n", ++ "%s: binfo = %pK device_addr = %pa\n", + __func__, binfo, &binfo->device_addr[0]); + buf_ref_put(inst, binfo); + } +@@ -4414,18 +4414,18 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags) + struct hfi_device *hdev; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", core); ++ "Invalid core pointer = %pK\n", core); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev); ++ dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev); + return -EINVAL; + } + +@@ -4443,7 +4443,7 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags) + core->state == VIDC_CORE_INVALID || + core->state == VIDC_CORE_UNINIT) { + dprintk(VIDC_ERR, +- "Core %p and inst %p are in bad state\n", ++ "Core %pK and inst %pK are in bad state\n", + core, inst); + msm_comm_flush_in_invalid_state(inst); + return 0; +@@ -4620,7 +4620,7 @@ int msm_vidc_trigger_ssr(struct msm_vidc_core *core, + int rc = 0; + struct hfi_device *hdev; + if (!core || !core->device) { +- dprintk(VIDC_WARN, "Invalid parameters: %p\n", core); ++ dprintk(VIDC_WARN, "Invalid parameters: %pK\n", core); + return -EINVAL; + } + hdev = core->device; +@@ -4863,7 +4863,7 @@ int msm_comm_kill_session(struct msm_vidc_inst *inst) + change_inst_state(inst, MSM_VIDC_CLOSE_DONE); + } else { + dprintk(VIDC_WARN, +- "Inactive session %p, triggering an internal session error\n", ++ "Inactive session %pK, triggering an internal session error\n", + inst); + msm_comm_generate_session_error(inst); + +@@ -4879,7 +4879,7 @@ struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst, + struct msm_smem *m = NULL; + + if (!inst || !inst->core) { +- dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst); + return NULL; + } + m = msm_smem_alloc(inst->mem_client, size, align, +@@ -4891,7 +4891,7 @@ void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem) + { + if (!inst || !inst->core || !mem) { + dprintk(VIDC_ERR, +- "%s: invalid params: %p %p\n", __func__, inst, mem); ++ "%s: invalid params: %pK %pK\n", __func__, inst, mem); + return; + } + msm_smem_free(inst->mem_client, mem); +@@ -4902,7 +4902,7 @@ int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst, + { + if (!inst || !mem) { + dprintk(VIDC_ERR, +- "%s: invalid params: %p %p\n", __func__, inst, mem); ++ "%s: invalid params: %pK %pK\n", __func__, inst, mem); + return -EINVAL; + } + return msm_smem_cache_operations(inst->mem_client, mem, cache_ops); +@@ -4914,7 +4914,7 @@ struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst, + struct msm_smem *m = NULL; + + if (!inst || !inst->core) { +- dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst); + return NULL; + } + +@@ -5055,7 +5055,7 @@ int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a) + fps = fps - 1; + + if (inst->prop.fps != fps) { +- dprintk(VIDC_PROF, "reported fps changed for %p: %d->%d\n", ++ dprintk(VIDC_PROF, "reported fps changed for %pK: %d->%d\n", + inst, inst->prop.fps, fps); + inst->prop.fps = fps; + frame_rate.frame_rate = inst->prop.fps * BIT(16); +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c b/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c +index 5e29fb9..b474d48 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The 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 +@@ -47,7 +47,7 @@ static inline int msm_dcvs_count_active_instances(struct msm_vidc_core *core) + struct msm_vidc_inst *inst = NULL; + + if (!core) { +- dprintk(VIDC_ERR, "%s: Invalid args: %p\n", __func__, core); ++ dprintk(VIDC_ERR, "%s: Invalid args: %pK\n", __func__, core); + return -EINVAL; + } + +@@ -95,7 +95,7 @@ static void msm_dcvs_update_dcvs_params(int idx, struct msm_vidc_inst *inst) + struct dcvs_table *table = NULL; + + if (!inst || !inst->core) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + +@@ -160,7 +160,7 @@ static void msm_dcvs_dec_check_and_scale_clocks(struct msm_vidc_inst *inst) + void msm_dcvs_check_and_scale_clocks(struct msm_vidc_inst *inst, bool is_etb) + { + if (!inst) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + +@@ -216,7 +216,7 @@ void msm_dcvs_init_load(struct msm_vidc_inst *inst) + dprintk(VIDC_DBG, "Init DCVS Load\n"); + + if (!inst || !inst->core) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + +@@ -289,7 +289,7 @@ void msm_dcvs_init(struct msm_vidc_inst *inst) + dprintk(VIDC_DBG, "Init DCVS Struct\n"); + + if (!inst) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + +@@ -306,7 +306,7 @@ void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst) + struct hal_buffer_requirements *output_buf_req; + + if (!inst) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + dcvs = &inst->dcvs; +@@ -315,7 +315,7 @@ void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst) + output_buf_req = get_buff_req_buffer(inst, + msm_comm_get_hal_output_buffer(inst)); + if (!output_buf_req) { +- dprintk(VIDC_ERR, "%s : Get output buffer req failed %p\n", ++ dprintk(VIDC_ERR, "%s : Get output buffer req failed %pK\n", + __func__, inst); + mutex_unlock(&inst->lock); + return; +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +index ff29d69..4d4acfa 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -77,13 +77,13 @@ static ssize_t core_info_read(struct file *file, char __user *buf, + int i = 0, rc = 0; + + if (!core || !core->device) { +- dprintk(VIDC_ERR, "Invalid params, core: %p\n", core); ++ dprintk(VIDC_ERR, "Invalid params, core: %pK\n", core); + return 0; + } + hdev = core->device; + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); +- write_str(&dbg_buf, "CORE %d: %p\n", core->id, core); ++ write_str(&dbg_buf, "CORE %d: %pK\n", core->id, core); + write_str(&dbg_buf, "===============================\n"); + write_str(&dbg_buf, "Core state: %d\n", core->state); + rc = call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data, &fw_info); +@@ -153,7 +153,7 @@ struct dentry *msm_vidc_debugfs_init_drv(void) + struct dentry *f = debugfs_create_##__type(__name, S_IRUGO | S_IWUSR, \ + dir, __value); \ + if (IS_ERR_OR_NULL(f)) { \ +- dprintk(VIDC_ERR, "Failed creating debugfs file '%pd/%s'\n", \ ++ dprintk(VIDC_ERR, "Failed creating debugfs file '%pKd/%s'\n", \ + dir, __name); \ + f = NULL; \ + } \ +@@ -204,7 +204,7 @@ struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core, + struct dentry *dir = NULL; + char debugfs_name[MAX_DEBUGFS_NAME]; + if (!core) { +- dprintk(VIDC_ERR, "Invalid params, core: %p\n", core); ++ dprintk(VIDC_ERR, "Invalid params, core: %pK\n", core); + goto failed_create_dir; + } + +@@ -268,15 +268,15 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + struct msm_vidc_inst *inst = file->private_data; + int i, j; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid params, core: %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid params, core: %pK\n", inst); + return 0; + } + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); +- write_str(&dbg_buf, "INSTANCE: %p (%s)\n", inst, ++ write_str(&dbg_buf, "INSTANCE: %pK (%s)\n", inst, + inst->session_type == MSM_VIDC_ENCODER ? "Encoder" : "Decoder"); + write_str(&dbg_buf, "===============================\n"); +- write_str(&dbg_buf, "core: %p\n", inst->core); ++ write_str(&dbg_buf, "core: %pK\n", inst->core); + write_str(&dbg_buf, "height: %d\n", inst->prop.height[CAPTURE_PORT]); + write_str(&dbg_buf, "width: %d\n", inst->prop.width[CAPTURE_PORT]); + write_str(&dbg_buf, "fps: %d\n", inst->prop.fps); +@@ -343,10 +343,10 @@ struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst, + struct dentry *dir = NULL; + char debugfs_name[MAX_DEBUGFS_NAME]; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid params, inst: %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid params, inst: %pK\n", inst); + goto failed_create_dir; + } +- snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%p", inst); ++ snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%pK", inst); + dir = debugfs_create_dir(debugfs_name, parent); + if (!dir) { + dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n"); +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +index 6a98cea..9da2c11 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +@@ -1170,7 +1170,7 @@ static int msm_vidc_setup_context_bank(struct context_bank_info *cb, + + dprintk(VIDC_DBG, "Attached %s and created mapping\n", dev_name(dev)); + dprintk(VIDC_DBG, +- "Context bank name:%s, buffer_type: %#x, is_secure: %d, address range start: %#x, size: %#x, dev: %p, mapping: %p", ++ "Context bank name:%s, buffer_type: %#x, is_secure: %d, address range start: %#x, size: %#x, dev: %pK, mapping: %pK", + cb->name, cb->buffer_type, cb->is_secure, cb->addr_range.start, + cb->addr_range.size, cb->dev, cb->mapping); + +@@ -1194,7 +1194,7 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, + enum vidc_ports port; + + if (!domain || !core) { +- dprintk(VIDC_ERR, "%s - invalid param %p %p\n", ++ dprintk(VIDC_ERR, "%s - invalid param %pK %pK\n", + __func__, domain, core); + return -EINVAL; + } +@@ -1216,7 +1216,7 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, + !inst->bit_depth ? "8" : "10"); + + dprintk(VIDC_ERR, +- "---Buffer details for inst: %p of type: %d---\n", ++ "---Buffer details for inst: %pK of type: %d---\n", + inst, inst->session_type); + mutex_lock(&inst->registeredbufs.lock); + dprintk(VIDC_ERR, "registered buffer list:\n"); +diff --git a/drivers/media/platform/msm/vidc/venus_boot.c b/drivers/media/platform/msm/vidc/venus_boot.c +index 6e881ab..925c97a 100644 +--- a/drivers/media/platform/msm/vidc/venus_boot.c ++++ b/drivers/media/platform/msm/vidc/venus_boot.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The 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 +@@ -161,7 +161,7 @@ static int venus_setup_cb(struct device *dev, + return -ENODEV; + } + dprintk(VIDC_DBG, +- "%s Attached device %p and created mapping %p for %s\n", ++ "%s Attached device %pK and created mapping %pK for %s\n", + __func__, dev, venus_data->mapping, dev_name(dev)); + return 0; + } +diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c +index ee4e7ae..b6c1f49 100644 +--- a/drivers/media/platform/msm/vidc/venus_hfi.c ++++ b/drivers/media/platform/msm/vidc/venus_hfi.c +@@ -341,7 +341,7 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet, + } + + if (msm_vidc_debug & VIDC_PKT) { +- dprintk(VIDC_PKT, "%s: %p\n", __func__, qinfo); ++ dprintk(VIDC_PKT, "%s: %pK\n", __func__, qinfo); + __dump_packet(packet); + } + +@@ -547,7 +547,7 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet, + *pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0; + + if (msm_vidc_debug & VIDC_PKT) { +- dprintk(VIDC_PKT, "%s: %p\n", __func__, qinfo); ++ dprintk(VIDC_PKT, "%s: %pK\n", __func__, qinfo); + __dump_packet(packet); + } + +@@ -574,7 +574,7 @@ static int __smem_alloc(struct venus_hfi_device *dev, + goto fail_smem_alloc; + } + +- dprintk(VIDC_DBG, "__smem_alloc: ptr = %p, size = %d\n", ++ dprintk(VIDC_DBG, "__smem_alloc: ptr = %pK, size = %d\n", + alloc->kvaddr, size); + rc = msm_smem_cache_operations(dev->hal_client, alloc, + SMEM_CACHE_CLEAN); +@@ -595,7 +595,7 @@ fail_smem_alloc: + static void __smem_free(struct venus_hfi_device *dev, struct msm_smem *mem) + { + if (!dev || !mem) { +- dprintk(VIDC_ERR, "invalid param %p %p\n", dev, mem); ++ dprintk(VIDC_ERR, "invalid param %pK %pK\n", dev, mem); + return; + } + +@@ -608,7 +608,7 @@ static void __write_register(struct venus_hfi_device *device, + u32 hwiosymaddr = reg; + u8 *base_addr; + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return; + } + +@@ -622,7 +622,7 @@ static void __write_register(struct venus_hfi_device *device, + } + + base_addr = device->hal_data->register_base; +- dprintk(VIDC_DBG, "Base addr: %p, written to: %#x, Value: %#x...\n", ++ dprintk(VIDC_DBG, "Base addr: %pK, written to: %#x, Value: %#x...\n", + base_addr, hwiosymaddr, value); + base_addr += hwiosymaddr; + writel_relaxed(value, base_addr); +@@ -634,7 +634,7 @@ static int __read_register(struct venus_hfi_device *device, u32 reg) + int rc = 0; + u8 *base_addr; + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + +@@ -651,7 +651,7 @@ static int __read_register(struct venus_hfi_device *device, u32 reg) + + rc = readl_relaxed(base_addr + reg); + rmb(); +- dprintk(VIDC_DBG, "Base addr: %p, read from: %#x, value: %#x...\n", ++ dprintk(VIDC_DBG, "Base addr: %pK, read from: %#x, value: %#x...\n", + base_addr, reg, rc); + + return rc; +@@ -699,7 +699,7 @@ static void __iommu_detach(struct venus_hfi_device *device) + struct context_bank_info *cb; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "Invalid paramter: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid parameter: %pK\n", device); + return; + } + +@@ -1024,7 +1024,7 @@ static int __set_imem(struct venus_hfi_device *device, struct imem *imem) + int rc = 0; + + if (!device || !device->res || !imem) { +- dprintk(VIDC_ERR, "Invalid params, core: %p, imem: %p\n", ++ dprintk(VIDC_ERR, "Invalid params, core: %pK, imem: %pK\n", + device, imem); + return -EINVAL; + } +@@ -1263,7 +1263,7 @@ static unsigned long venus_hfi_get_core_clock_rate(void *dev, bool actual_rate) + struct clock_info *vc; + + if (!device) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, device); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, device); + return -EINVAL; + } + +@@ -1328,7 +1328,7 @@ static int __halt_axi(struct venus_hfi_device *device) + u32 reg; + int rc = 0; + if (!device) { +- dprintk(VIDC_ERR, "Invalid input: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid input: %pK\n", device); + return -EINVAL; + } + +@@ -1526,7 +1526,7 @@ static int venus_hfi_scale_clocks(void *dev, int load, + struct venus_hfi_device *device = dev; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid args: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid args: %pK\n", device); + return -EINVAL; + } + +@@ -2173,7 +2173,7 @@ static int venus_hfi_core_init(void *device) + goto err_core_init; + } + +- dprintk(VIDC_DBG, "Dev_Virt: %pa, Reg_Virt: %p\n", ++ dprintk(VIDC_DBG, "Dev_Virt: %pa, Reg_Virt: %pK\n", + &dev->hal_data->firmware_base, + dev->hal_data->register_base); + +@@ -2293,12 +2293,12 @@ static void __core_clear_interrupt(struct venus_hfi_device *device) + device->intr_status |= intr_status; + device->reg_count++; + dprintk(VIDC_DBG, +- "INTERRUPT for device: %p: times: %d interrupt_status: %d\n", ++ "INTERRUPT for device: %pK: times: %d interrupt_status: %d\n", + device, device->reg_count, intr_status); + } else { + device->spur_count++; + dprintk(VIDC_INFO, +- "SPURIOUS_INTR for device: %p: times: %d interrupt_status: %d\n", ++ "SPURIOUS_INTR for device: %pK: times: %d interrupt_status: %d\n", + device, device->spur_count, intr_status); + } + +@@ -2456,7 +2456,7 @@ static void __set_default_sys_properties(struct venus_hfi_device *device) + + static void __session_clean(struct hal_session *session) + { +- dprintk(VIDC_DBG, "deleted the session: %p\n", session); ++ dprintk(VIDC_DBG, "deleted the session: %pK\n", session); + list_del(&session->list); + /* Poison the session handle with zeros */ + *session = (struct hal_session){ {0} }; +@@ -3495,7 +3495,7 @@ static int __response_handler(struct venus_hfi_device *device) + (u32)(uintptr_t)*session_id); + if (!session) { + dprintk(VIDC_ERR, +- "Received a packet (%#x) for an unrecognized session (%p), discarding\n", ++ "Received a packet (%#x) for an unrecognized session (%pK), discarding\n", + info->response_type, + *session_id); + --packet_count; +@@ -3545,7 +3545,7 @@ static void venus_hfi_core_work_handler(struct work_struct *work) + } + + if (!device->callback) { +- dprintk(VIDC_ERR, "No interrupt callback function: %p\n", ++ dprintk(VIDC_ERR, "No interrupt callback function: %pK\n", + device); + goto err_no_work; + } +@@ -3671,7 +3671,7 @@ static inline int __init_clocks(struct venus_hfi_device *device) + struct clock_info *cl = NULL; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + +@@ -3715,7 +3715,7 @@ static inline void __disable_unprepare_clks(struct venus_hfi_device *device) + struct clock_info *cl; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return; + } + +@@ -3732,7 +3732,7 @@ static inline int __prepare_enable_clks(struct venus_hfi_device *device) + struct clock_info *cl = NULL, *cl_fail = NULL; + int rc = 0; + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + +@@ -4192,7 +4192,7 @@ static inline int __suspend(struct venus_hfi_device *device) + int rc = 0; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } else if (!device->power_enabled) { + dprintk(VIDC_DBG, "Power already disabled\n"); +@@ -4223,7 +4223,7 @@ static inline int __resume(struct venus_hfi_device *device) + int rc = 0; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } else if (device->power_enabled) { + dprintk(VIDC_DBG, "Power is already enabled\n"); +@@ -4532,7 +4532,7 @@ static struct venus_hfi_device *__get_device(u32 device_id, + hfi_cmd_response_callback callback) + { + if (!res || !callback) { +- dprintk(VIDC_ERR, "Invalid params: %p %p\n", res, callback); ++ dprintk(VIDC_ERR, "Invalid params: %pK %pK\n", res, callback); + return NULL; + } + +@@ -4610,7 +4610,7 @@ int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id, + int rc = 0; + + if (!hdev || !res || !callback) { +- dprintk(VIDC_ERR, "Invalid params: %p %p %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK %pK %pK\n", + hdev, res, callback); + rc = -EINVAL; + goto err_venus_hfi_init; +diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.c b/drivers/media/platform/msm/vidc/vidc_hfi.c +index 16acc47..2dc892c 100644 +--- a/drivers/media/platform/msm/vidc/vidc_hfi.c ++++ b/drivers/media/platform/msm/vidc/vidc_hfi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -55,7 +55,7 @@ void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type, + struct hfi_device *hdev) + { + if (!hdev) { +- dprintk(VIDC_ERR, "%s invalid device %p", __func__, hdev); ++ dprintk(VIDC_ERR, "%s invalid device %pK", __func__, hdev); + return; + } + +diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.c b/drivers/media/platform/msm/vidc/vmem/vmem.c +index 3a2ac31..506121a 100644 +--- a/drivers/media/platform/msm/vidc/vmem/vmem.c ++++ b/drivers/media/platform/msm/vidc/vmem/vmem.c +@@ -1,5 +1,4 @@ +-/* +- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The 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 +@@ -127,7 +126,7 @@ static inline u32 __readl(void * __iomem addr) + { + u32 value = 0; + +- pr_debug("read %p ", addr); ++ pr_debug("read %pK ", addr); + value = readl_relaxed(addr); + pr_debug("-> %08x\n", value); + +@@ -136,7 +135,7 @@ static inline u32 __readl(void * __iomem addr) + + static inline void __writel(u32 val, void * __iomem addr) + { +- pr_debug("write %08x -> %p\n", val, addr); ++ pr_debug("write %08x -> %pK\n", val, addr); + writel_relaxed(val, addr); + /* + * Commit all writes via a mem barrier, as subsequent __readl() +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6748/1.patch b/Patches/Linux_CVEs/CVE-2016-6748/1.patch new file mode 100644 index 00000000..8e6449ea --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6748/1.patch @@ -0,0 +1,2158 @@ +From be651d020b122a1ba9410d23ca4ebbe9f5598df6 Mon Sep 17 00:00:00 2001 +From: Sanjay Singh +Date: Wed, 10 Aug 2016 12:40:58 +0530 +Subject: msm: vidc: use %pK instead of %p which respects kptr_restrict sysctl + +Hide kernel pointers from unprivileged ussers by using %pK format- +specifier instead of %p. This respects the kptr_restrict sysctl +setting which is by default on. So by default %pK will print zeroes +as address. echo 1 to kptr_restrict to print proper kernel addresses. + +CRs-Fixed: 987018 +Change-Id: I4772257a557c6730ecc0624cbc8e5614e893e9fd +Signed-off-by: Sanjay Singh +--- + .../media/platform/msm/vidc/hfi_packetization.c | 8 +- + .../media/platform/msm/vidc/hfi_response_handler.c | 48 +++---- + drivers/media/platform/msm/vidc/msm_smem.c | 20 +-- + drivers/media/platform/msm/vidc/msm_v4l2_vidc.c | 6 +- + drivers/media/platform/msm/vidc/msm_vdec.c | 40 +++--- + drivers/media/platform/msm/vidc/msm_venc.c | 32 ++--- + drivers/media/platform/msm/vidc/msm_vidc.c | 36 +++--- + drivers/media/platform/msm/vidc/msm_vidc_common.c | 138 ++++++++++----------- + drivers/media/platform/msm/vidc/msm_vidc_dcvs.c | 14 +-- + drivers/media/platform/msm/vidc/msm_vidc_debug.c | 18 +-- + drivers/media/platform/msm/vidc/q6_hfi.c | 22 ++-- + drivers/media/platform/msm/vidc/venus_hfi.c | 96 +++++++------- + drivers/media/platform/msm/vidc/vidc_hfi.c | 4 +- + drivers/media/platform/msm/vidc/vmem/vmem.c | 6 +- + 14 files changed, 244 insertions(+), 244 deletions(-) + +diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c +index 06ac913..86239e2 100644 +--- a/drivers/media/platform/msm/vidc/hfi_packetization.c ++++ b/drivers/media/platform/msm/vidc/hfi_packetization.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -1402,7 +1402,7 @@ int create_pkt_cmd_session_set_property( + break; + default: + dprintk(VIDC_ERR, +- "Invalid Rate control setting: 0x%p\n", ++ "Invalid Rate control setting: 0x%pK\n", + pdata); + break; + } +@@ -2084,7 +2084,7 @@ int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type, + struct hfi_cmd_sys_test_ssr_packet *pkt) + { + if (!pkt) { +- dprintk(VIDC_ERR, "Invalid params, device: %p\n", pkt); ++ dprintk(VIDC_ERR, "Invalid params, device: %pK\n", pkt); + return -EINVAL; + } + pkt->size = sizeof(struct hfi_cmd_sys_test_ssr_packet); +@@ -2097,7 +2097,7 @@ int create_pkt_cmd_sys_image_version( + struct hfi_cmd_sys_get_property_packet *pkt) + { + if (!pkt) { +- dprintk(VIDC_ERR, "%s invalid param :%p\n", __func__, pkt); ++ dprintk(VIDC_ERR, "%s invalid param :%pK\n", __func__, pkt); + return -EINVAL; + } + pkt->size = sizeof(struct hfi_cmd_sys_get_property_packet); +diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c +index e148f04..c315b6d 100644 +--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c ++++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -255,7 +255,7 @@ static void hfi_process_event_notify(msm_vidc_callback callback, u32 device_id, + hfi_process_sys_error(callback, device_id); + break; + case HFI_EVENT_SESSION_PROPERTY_CHANGED: +- dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED[%p]\n", ++ dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED[%pK]\n", + session); + break; + } +@@ -267,24 +267,24 @@ static void hfi_process_event_notify(msm_vidc_callback callback, u32 device_id, + + switch (pkt->event_id) { + case HFI_EVENT_SESSION_ERROR: +- dprintk(VIDC_INFO, "HFI_EVENT_SESSION_ERROR[%p]\n", session); ++ dprintk(VIDC_INFO, "HFI_EVENT_SESSION_ERROR[%pK]\n", session); + hfi_process_session_error(callback, device_id, session, pkt); + break; + case HFI_EVENT_SESSION_SEQUENCE_CHANGED: +- dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED[%p]\n", ++ dprintk(VIDC_INFO, "HFI_EVENT_SESSION_SEQUENCE_CHANGED[%pK]\n", + session); + hfi_process_sess_evt_seq_changed(callback, device_id, + session, pkt); + break; + case HFI_EVENT_RELEASE_BUFFER_REFERENCE: +- dprintk(VIDC_INFO, "HFI_EVENT_RELEASE_BUFFER_REFERENCE[%p]\n", ++ dprintk(VIDC_INFO, "HFI_EVENT_RELEASE_BUFFER_REFERENCE[%pK]\n", + session); + hfi_process_evt_release_buffer_ref(callback, device_id, + session, pkt); + break; + default: + dprintk(VIDC_WARN, +- "hal_process_event_notify: unknown_event_id[%p]\n", ++ "hal_process_event_notify: unknown_event_id[%pK]\n", + session); + break; + } +@@ -887,7 +887,7 @@ static enum vidc_status hfi_parse_init_done_properties( + } + default: + dprintk(VIDC_DBG, +- "%s: default case - data_ptr %p, prop_id 0x%x\n", ++ "%s: default case - data_ptr %pK, prop_id 0x%x\n", + __func__, data_ptr, prop_id); + break; + } +@@ -925,7 +925,7 @@ enum vidc_status hfi_process_sys_init_done_prop_read( + data_ptr = (u8 *) &pkt->rg_property_data[0]; + num_properties = pkt->num_properties; + dprintk(VIDC_DBG, +- "%s: data_start %p, num_properties %#x\n", ++ "%s: data_start %pK, num_properties %#x\n", + __func__, data_ptr, num_properties); + + bytes_read = hfi_fill_codec_info(data_ptr, sys_init_done); +@@ -955,7 +955,7 @@ static void hfi_process_sess_get_prop_profile_level( + dprintk(VIDC_DBG, "Entered %s\n", __func__); + if (!prop) { + dprintk(VIDC_ERR, +- "hal_process_sess_get_profile_level: bad_prop: %p\n", ++ "hal_process_sess_get_profile_level: bad_prop: %pK\n", + prop); + return; + } +@@ -986,7 +986,7 @@ static void hfi_process_sess_get_prop_buf_req( + + if (!prop) { + dprintk(VIDC_ERR, +- "hal_process_sess_get_prop_buf_req: bad_prop: %p\n", ++ "hal_process_sess_get_prop_buf_req: bad_prop: %pK\n", + prop); + return; + } +@@ -1105,7 +1105,7 @@ static void hfi_process_session_prop_info(msm_vidc_callback callback, + struct buffer_requirements buff_req; + + memset(&buff_req, 0, sizeof(struct buffer_requirements)); +- dprintk(VIDC_DBG, "Received SESSION_PROPERTY_INFO[%p]\n", session); ++ dprintk(VIDC_DBG, "Received SESSION_PROPERTY_INFO[%pK]\n", session); + + if (pkt->size < sizeof(struct hfi_msg_session_property_info_packet)) { + dprintk(VIDC_ERR, +@@ -1161,7 +1161,7 @@ static void hfi_process_session_init_done( + + memset(&session_init_done, 0, sizeof(struct + vidc_hal_session_init_done)); +- dprintk(VIDC_DBG, "RECEIVED: SESSION_INIT_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_INIT_DONE[%pK]\n", session); + + if (sizeof(struct hfi_msg_sys_session_init_done_packet) + > pkt->size) { +@@ -1181,7 +1181,7 @@ static void hfi_process_session_init_done( + pkt, &session_init_done); + } else { + dprintk(VIDC_WARN, +- "Sess init failed: 0x%p, 0x%p\n", ++ "Sess init failed: 0x%pK, 0x%pK\n", + session->session_id, session); + } + cmd_done.size = sizeof(struct vidc_hal_session_init_done); +@@ -1193,7 +1193,7 @@ static void hfi_process_session_load_res_done(msm_vidc_callback callback, + struct hfi_msg_session_load_resources_done_packet *pkt) + { + struct msm_vidc_cb_cmd_done cmd_done = {0}; +- dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%p]\n", ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_LOAD_RESOURCES_DONE[%pK]\n", + session); + + if (sizeof(struct hfi_msg_session_load_resources_done_packet) != +@@ -1218,7 +1218,7 @@ static void hfi_process_session_flush_done(msm_vidc_callback callback, + { + struct msm_vidc_cb_cmd_done cmd_done = {0}; + +- dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_FLUSH_DONE[%pK]\n", session); + + if (sizeof(struct hfi_msg_session_flush_done_packet) != pkt->size) { + dprintk(VIDC_ERR, +@@ -1241,7 +1241,7 @@ static void hfi_process_session_etb_done(msm_vidc_callback callback, + { + struct msm_vidc_cb_data_done data_done = {0}; + +- dprintk(VIDC_DBG, "RECEIVED: SESSION_ETB_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_ETB_DONE[%pK]\n", session); + + if (!pkt || pkt->size < + sizeof(struct hfi_msg_session_empty_buffer_done_packet)) { +@@ -1282,7 +1282,7 @@ static void hfi_process_session_ftb_done(msm_vidc_callback callback, + return; + } + +- dprintk(VIDC_DBG, "RECEIVED: SESSION_FTB_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_FTB_DONE[%pK]\n", session); + + if (is_decoder == 0) { + struct hfi_msg_session_fill_buffer_done_compressed_packet *pkt = +@@ -1382,7 +1382,7 @@ static void hfi_process_session_start_done(msm_vidc_callback callback, + { + struct msm_vidc_cb_cmd_done cmd_done = {0}; + +- dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_START_DONE[%pK]\n", session); + + if (!pkt || pkt->size != + sizeof(struct hfi_msg_session_start_done_packet)) { +@@ -1405,7 +1405,7 @@ static void hfi_process_session_stop_done(msm_vidc_callback callback, + { + struct msm_vidc_cb_cmd_done cmd_done = {0}; + +- dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_STOP_DONE[%pK]\n", session); + + if (!pkt || pkt->size != + sizeof(struct hfi_msg_session_stop_done_packet)) { +@@ -1428,7 +1428,7 @@ static void hfi_process_session_rel_res_done(msm_vidc_callback callback, + { + struct msm_vidc_cb_cmd_done cmd_done = {0}; + +- dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%p]\n", ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_RELEASE_RESOURCES_DONE[%pK]\n", + session); + + if (!pkt || pkt->size != +@@ -1459,7 +1459,7 @@ static void hfi_process_session_rel_buf_done(msm_vidc_callback callback, + pkt ? pkt->size : 0); + return; + } +- dprintk(VIDC_DBG, "RECEIVED:SESSION_RELEASE_BUFFER_DONE[%p]\n", ++ dprintk(VIDC_DBG, "RECEIVED:SESSION_RELEASE_BUFFER_DONE[%pK]\n", + session); + + cmd_done.device_id = device_id; +@@ -1481,7 +1481,7 @@ static void hfi_process_session_end_done(msm_vidc_callback callback, + { + struct msm_vidc_cb_cmd_done cmd_done = {0}; + +- dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_END_DONE[%pK]\n", session); + + if (!pkt || pkt->size != + sizeof(struct hfi_msg_sys_session_end_done_packet)) { +@@ -1503,7 +1503,7 @@ static void hfi_process_session_abort_done(msm_vidc_callback callback, + { + struct msm_vidc_cb_cmd_done cmd_done = {0}; + +- dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED: SESSION_ABORT_DONE[%pK]\n", session); + + if (!pkt || pkt->size != + sizeof(struct hfi_msg_sys_session_abort_done_packet)) { +@@ -1540,7 +1540,7 @@ static void hfi_process_session_get_seq_hdr_done(msm_vidc_callback callback, + __func__); + return; + } +- dprintk(VIDC_DBG, "RECEIVED:SESSION_GET_SEQ_HDR_DONE[%p]\n", session); ++ dprintk(VIDC_DBG, "RECEIVED:SESSION_GET_SEQ_HDR_DONE[%pK]\n", session); + + data_done.device_id = device_id; + data_done.size = sizeof(struct msm_vidc_cb_data_done); +diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c +index 47d3ca5..8ab44a1 100644 +--- a/drivers/media/platform/msm/vidc/msm_smem.c ++++ b/drivers/media/platform/msm/vidc/msm_smem.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -34,7 +34,7 @@ static int get_device_address(struct smem_client *smem_client, + struct ion_client *clnt = NULL; + + if (!iova || !buffer_size || !hndl || !smem_client) { +- dprintk(VIDC_ERR, "Invalid params: %p, %p, %p, %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK, %pK, %pK, %pK\n", + smem_client, hndl, iova, buffer_size); + return -EINVAL; + } +@@ -86,7 +86,7 @@ static void put_device_address(struct smem_client *smem_client, + struct ion_client *clnt = NULL; + + if (!hndl || !smem_client) { +- dprintk(VIDC_WARN, "Invalid params: %p, %p\n", ++ dprintk(VIDC_WARN, "Invalid params: %pK, %pK\n", + smem_client, hndl); + return; + } +@@ -120,7 +120,7 @@ static int ion_user_to_kernel(struct smem_client *client, int fd, u32 offset, + + hndl = ion_import_dma_buf(client->clnt, fd); + if (IS_ERR_OR_NULL(hndl)) { +- dprintk(VIDC_ERR, "Failed to get handle: %p, %d, %d, %p\n", ++ dprintk(VIDC_ERR, "Failed to get handle: %pK, %d, %d, %pK\n", + client, fd, offset, hndl); + rc = -ENOMEM; + goto fail_import_fd; +@@ -153,7 +153,7 @@ static int ion_user_to_kernel(struct smem_client *client, int fd, u32 offset, + goto fail_device_address; + } + dprintk(VIDC_DBG, +- "%s: ion_handle = 0x%p, fd = %d, device_addr = 0x%pa, size = %zx, kvaddr = 0x%p, buffer_type = %d, flags = 0x%lx\n", ++ "%s: ion_handle = 0x%pK, fd = %d, device_addr = 0x%pa, size = %zx, kvaddr = 0x%pK, buffer_type = %d, flags = 0x%lx\n", + __func__, mem->smem_priv, fd, &mem->device_addr, mem->size, + mem->kvaddr, mem->buffer_type, mem->flags); + return rc; +@@ -199,7 +199,7 @@ static int alloc_ion_mem(struct smem_client *client, size_t size, u32 align, + hndl = ion_alloc(client->clnt, size, align, heap_mask, flags); + if (IS_ERR_OR_NULL(hndl)) { + dprintk(VIDC_ERR, +- "Failed to allocate shared memory = %p, %zx, %d, 0x%x\n", ++ "Failed to allocate shared memory = %pK, %zx, %d, 0x%x\n", + client, size, align, flags); + rc = -ENOMEM; + goto fail_shared_mem_alloc; +@@ -237,7 +237,7 @@ static int alloc_ion_mem(struct smem_client *client, size_t size, u32 align, + } + mem->size = size; + dprintk(VIDC_DBG, +- "%s: ion_handle = 0x%p, device_addr = 0x%pa, size = 0x%zx, kvaddr = 0x%p, buffer_type = 0x%x, flags = 0x%lx\n", ++ "%s: ion_handle = 0x%pK, device_addr = 0x%pa, size = 0x%zx, kvaddr = 0x%pK, buffer_type = 0x%x, flags = 0x%lx\n", + __func__, mem->smem_priv, &mem->device_addr, + mem->size, mem->kvaddr, + mem->buffer_type, mem->flags); +@@ -255,7 +255,7 @@ static void free_ion_mem(struct smem_client *client, struct msm_smem *mem) + int domain, partition, rc; + + dprintk(VIDC_DBG, +- "%s: ion_handle = 0x%p, device_addr = 0x%pa, size = 0x%zx, kvaddr = 0x%p, buffer_type = 0x%x\n", ++ "%s: ion_handle = 0x%pK, device_addr = 0x%pa, size = 0x%zx, kvaddr = 0x%pK, buffer_type = 0x%x\n", + __func__, mem->smem_priv, &mem->device_addr, + mem->size, mem->kvaddr, mem->buffer_type); + rc = msm_smem_get_domain_partition((void *)client, mem->flags, +@@ -333,7 +333,7 @@ static int ion_cache_operations(struct smem_client *client, + int rc = 0; + int msm_cache_ops = 0; + if (!mem || !client) { +- dprintk(VIDC_ERR, "Invalid params: %p, %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK, %pK\n", + mem, client); + return -EINVAL; + } +@@ -380,7 +380,7 @@ int msm_smem_cache_operations(void *clt, struct msm_smem *mem, + struct smem_client *client = clt; + int rc = 0; + if (!client) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", + client); + return -EINVAL; + } +diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +index 309979c..c43c64c 100644 +--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c ++++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -307,7 +307,7 @@ static int read_platform_resources(struct msm_vidc_core *core, + struct platform_device *pdev) + { + if (!core || !pdev) { +- dprintk(VIDC_ERR, "%s: Invalid params %p %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid params %pK %pK\n", + __func__, core, pdev); + return -EINVAL; + } +@@ -696,7 +696,7 @@ static int msm_vidc_remove(struct platform_device *pdev) + struct msm_vidc_core *core; + + if (!pdev) { +- dprintk(VIDC_ERR, "%s invalid input %p", __func__, pdev); ++ dprintk(VIDC_ERR, "%s invalid input %pK", __func__, pdev); + return -EINVAL; + } + core = pdev->dev.platform_data; +diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c +index c92d655..dd512ad 100644 +--- a/drivers/media/platform/msm/vidc/msm_vdec.c ++++ b/drivers/media/platform/msm/vidc/msm_vdec.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -835,7 +835,7 @@ int msm_vdec_prepare_buf(struct msm_vidc_inst *inst, + if (inst->state == MSM_VIDC_CORE_INVALID || + inst->core->state == VIDC_CORE_INVALID) { + dprintk(VIDC_ERR, +- "Core %p in bad state, ignoring prepare buf\n", ++ "Core %pK in bad state, ignoring prepare buf\n", + inst->core); + goto exit; + } +@@ -914,7 +914,7 @@ int msm_vdec_release_buf(struct msm_vidc_inst *inst, + if (inst->state == MSM_VIDC_CORE_INVALID || + core->state == VIDC_CORE_INVALID) { + dprintk(VIDC_ERR, +- "Core %p in bad state, ignoring release output buf\n", ++ "Core %pK in bad state, ignoring release output buf\n", + core); + goto exit; + } +@@ -1007,7 +1007,7 @@ int msm_vdec_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b) + int rc = 0; + if (!inst || !b) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, buffer = %p\n", inst, b); ++ "Invalid input, inst = %pK, buffer = %pK\n", inst, b); + return -EINVAL; + } + q = msm_comm_get_vb2q(inst, b->type); +@@ -1038,7 +1038,7 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) + + if (!inst || !f || !inst->core || !inst->core->device) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, format = %p\n", inst, f); ++ "Invalid input, inst = %pK, format = %pK\n", inst, f); + return -EINVAL; + } + +@@ -1215,7 +1215,7 @@ int msm_vdec_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a) + fps = fps - 1; + + if (inst->prop.fps != fps) { +- dprintk(VIDC_PROF, "reported fps changed for %p: %d->%d\n", ++ dprintk(VIDC_PROF, "reported fps changed for %pK: %d->%d\n", + inst, inst->prop.fps, fps); + inst->prop.fps = fps; + msm_dcvs_init_load(inst); +@@ -1381,7 +1381,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) + + if (!f || !inst || !inst->core || !inst->core->device) { + dprintk(VIDC_ERR, +- "%s: invalid parameters, format %p, inst %p\n", ++ "%s: invalid parameters, format %pK, inst %pK\n", + __func__, f, inst); + return -EINVAL; + } +@@ -1562,7 +1562,7 @@ int msm_vdec_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap) + { + if (!inst || !cap) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, cap = %p\n", inst, cap); ++ "Invalid input, inst = %pK, cap = %pK\n", inst, cap); + return -EINVAL; + } + strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver)); +@@ -1582,7 +1582,7 @@ int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) + int rc = 0; + if (!inst || !f) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, f = %p\n", inst, f); ++ "Invalid input, inst = %pK, f = %pK\n", inst, f); + return -EINVAL; + } + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { +@@ -1640,7 +1640,7 @@ static int msm_vdec_queue_setup(struct vb2_queue *q, + + if (!q || !num_buffers || !num_planes + || !sizes || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n", ++ dprintk(VIDC_ERR, "Invalid input, q = %pK, %pK, %pK\n", + q, num_buffers, num_planes); + return -EINVAL; + } +@@ -1829,7 +1829,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) + rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto fail_start; + } + msm_dcvs_init_load(inst); +@@ -1866,7 +1866,7 @@ static inline int stop_streaming(struct msm_vidc_inst *inst) + rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE); + if (rc) + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + return rc; + } + +@@ -1876,7 +1876,7 @@ static int msm_vdec_start_streaming(struct vb2_queue *q, unsigned int count) + int rc = 0; + struct hfi_device *hdev; + if (!q || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p\n", q); ++ dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); + return -EINVAL; + } + inst = q->drv_priv; +@@ -1909,7 +1909,7 @@ static int msm_vdec_stop_streaming(struct vb2_queue *q) + struct msm_vidc_inst *inst; + int rc = 0; + if (!q || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p\n", q); ++ dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); + return -EINVAL; + } + inst = q->drv_priv; +@@ -1934,7 +1934,7 @@ static int msm_vdec_stop_streaming(struct vb2_queue *q) + + if (rc) + dprintk(VIDC_ERR, +- "Failed to move inst: %p, cap = %d to state: %d\n", ++ "Failed to move inst: %pK, cap = %d to state: %d\n", + inst, q->type, MSM_VIDC_RELEASE_RESOURCES_DONE); + return rc; + } +@@ -1992,7 +1992,7 @@ int msm_vdec_cmd(struct msm_vidc_inst *inst, struct v4l2_decoder_cmd *dec) + if (inst->state == MSM_VIDC_CORE_INVALID || + core->state == VIDC_CORE_INVALID) { + dprintk(VIDC_ERR, +- "Core %p in bad state, Sending CLOSE event\n", ++ "Core %pK in bad state, Sending CLOSE event\n", + core); + msm_vidc_queue_v4l2_event(inst, + V4L2_EVENT_MSM_VIDC_CLOSE_DONE); +@@ -2034,7 +2034,7 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) + { + int rc = 0; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid input = %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid input = %pK\n", inst); + return -EINVAL; + } + inst->fmts[OUTPUT_PORT] = &vdec_formats[1]; +@@ -2575,7 +2575,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) + case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE: + property_id = 0; + inst->operating_rate = ctrl->val; +- dprintk(VIDC_DBG, "inst(%p) operating rate changed to %d", ++ dprintk(VIDC_DBG, "inst(%pK) operating rate changed to %d", + inst, inst->operating_rate >> 16); + msm_comm_scale_clocks_and_bus(inst); + break; +@@ -2607,7 +2607,7 @@ static int msm_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl) + rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto failed_open_done; + } + +@@ -2639,7 +2639,7 @@ static int msm_vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl) + rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto failed_open_done; + } + for (c = 0; c < master->ncontrols; ++c) { +diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c +index 932c980..d3f176d 100644 +--- a/drivers/media/platform/msm/vidc/msm_venc.c ++++ b/drivers/media/platform/msm/vidc/msm_venc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -1520,7 +1520,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) + rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto fail_start; + } + msm_dcvs_init_load(inst); +@@ -1547,7 +1547,7 @@ static int msm_venc_start_streaming(struct vb2_queue *q, unsigned int count) + struct msm_vidc_inst *inst; + int rc = 0; + if (!q || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p\n", q); ++ dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); + return -EINVAL; + } + inst = q->drv_priv; +@@ -1574,7 +1574,7 @@ static int msm_venc_stop_streaming(struct vb2_queue *q) + struct msm_vidc_inst *inst; + int rc = 0; + if (!q || !q->drv_priv) { +- dprintk(VIDC_ERR, "Invalid input, q = %p\n", q); ++ dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); + return -EINVAL; + } + inst = q->drv_priv; +@@ -1595,7 +1595,7 @@ static int msm_venc_stop_streaming(struct vb2_queue *q) + + if (rc) + dprintk(VIDC_ERR, +- "Failed to move inst: %p, cap = %d to state: %d\n", ++ "Failed to move inst: %pK, cap = %d to state: %d\n", + inst, q->type, MSM_VIDC_CLOSE_DONE); + return rc; + } +@@ -2835,7 +2835,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) + case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE: + property_id = 0; + inst->operating_rate = ctrl->val; +- dprintk(VIDC_DBG, "inst(%p) operating rate changed to %d", ++ dprintk(VIDC_DBG, "inst(%pK) operating rate changed to %d", + inst, inst->operating_rate >> 16); + msm_comm_scale_clocks_and_bus(inst); + break; +@@ -3054,7 +3054,7 @@ static int msm_venc_op_s_ctrl(struct v4l2_ctrl *ctrl) + + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to start done state\n", inst); ++ "Failed to move inst: %pK to start done state\n", inst); + goto failed_open_done; + } + +@@ -3098,7 +3098,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) + { + int rc = 0; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid input = %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid input = %pK\n", inst); + return -EINVAL; + } + inst->fmts[CAPTURE_PORT] = &venc_formats[1]; +@@ -3181,7 +3181,7 @@ int msm_venc_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap) + { + if (!inst || !cap) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, cap = %p\n", inst, cap); ++ "Invalid input, inst = %pK, cap = %pK\n", inst, cap); + return -EINVAL; + } + strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver)); +@@ -3201,7 +3201,7 @@ int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) + int rc = 0; + if (!inst || !f) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, f = %p\n", inst, f); ++ "Invalid input, inst = %pK, f = %pK\n", inst, f); + return -EINVAL; + } + if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { +@@ -3275,7 +3275,7 @@ int msm_venc_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a) + fps = fps - 1; + + if (inst->prop.fps != fps) { +- dprintk(VIDC_PROF, "reported fps changed for %p: %d->%d\n", ++ dprintk(VIDC_PROF, "reported fps changed for %pK: %d->%d\n", + inst, inst->prop.fps, fps); + inst->prop.fps = fps; + frame_rate.frame_rate = inst->prop.fps * (0x1<<16); +@@ -3329,7 +3329,7 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) + struct hfi_device *hdev; + if (!inst || !f) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, format = %p\n", inst, f); ++ "Invalid input, inst = %pK, format = %pK\n", inst, f); + return -EINVAL; + } + +@@ -3512,7 +3512,7 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) + + if (!inst || !f) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, format = %p\n", inst, f); ++ "Invalid input, inst = %pK, format = %pK\n", inst, f); + return -EINVAL; + } + +@@ -3577,7 +3577,7 @@ int msm_venc_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b) + int rc = 0; + if (!inst || !b) { + dprintk(VIDC_ERR, +- "Invalid input, inst = %p, buffer = %p\n", inst, b); ++ "Invalid input, inst = %pK, buffer = %pK\n", inst, b); + return -EINVAL; + } + q = msm_comm_get_vb2q(inst, b->type); +@@ -3614,7 +3614,7 @@ int msm_venc_prepare_buf(struct msm_vidc_inst *inst, + if (inst->state == MSM_VIDC_CORE_INVALID || + inst->core->state == VIDC_CORE_INVALID) { + dprintk(VIDC_ERR, +- "Core %p in bad state, ignoring prepare buf\n", ++ "Core %pK in bad state, ignoring prepare buf\n", + inst->core); + goto exit; + } +@@ -3685,7 +3685,7 @@ int msm_venc_release_buf(struct msm_vidc_inst *inst, + rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to release res done state\n", ++ "Failed to move inst: %pK to release res done state\n", + inst); + goto exit; + } +diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c +index 38ccaa3..8f4b6b6 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -331,7 +331,7 @@ struct buffer_info *device_to_uvaddr(struct msm_vidc_list *buf_list, + + if (!buf_list || !device_addr) { + dprintk(VIDC_ERR, +- "Invalid input- device_addr: 0x%pa buf_list: %p\n", ++ "Invalid input- device_addr: 0x%pa buf_list: %pK\n", + &device_addr, buf_list); + goto err_invalid_input; + } +@@ -487,7 +487,7 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b) + goto exit; + } + +- dprintk(VIDC_DBG, "[MAP] Create binfo = %p fd = %d type = %d\n", ++ dprintk(VIDC_DBG, "[MAP] Create binfo = %pK fd = %d type = %d\n", + binfo, b->m.planes[0].reserved[0], b->type); + + for (i = 0; i < b->length; ++i) { +@@ -570,7 +570,7 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b) + goto exit; + } + dprintk(VIDC_DBG, +- "%s: [MAP] binfo = %p, handle[%d] = %p, device_addr = 0x%pa, fd = %d, offset = %d, mapped = %d\n", ++ "%s: [MAP] binfo = %pK, handle[%d] = %pK, device_addr = 0x%pa, fd = %d, offset = %d, mapped = %d\n", + __func__, binfo, i, binfo->handle[i], + &binfo->device_addr[i], binfo->fd[i], + binfo->buff_off[i], binfo->mapped[i]); +@@ -593,7 +593,7 @@ int unmap_and_deregister_buf(struct msm_vidc_inst *inst, + bool found = false, keep_node = false; + + if (!inst || !binfo) { +- dprintk(VIDC_ERR, "%s invalid param: %p %p\n", ++ dprintk(VIDC_ERR, "%s invalid param: %pK %pK\n", + __func__, inst, binfo); + return -EINVAL; + } +@@ -623,7 +623,7 @@ int unmap_and_deregister_buf(struct msm_vidc_inst *inst, + + for (i = 0; i < temp->num_planes; i++) { + dprintk(VIDC_DBG, +- "%s: [UNMAP] binfo = %p, handle[%d] = %p, device_addr = 0x%pa, fd = %d, offset = %d, mapped = %d\n", ++ "%s: [UNMAP] binfo = %pK, handle[%d] = %pK, device_addr = 0x%pKa, fd = %d, offset = %d, mapped = %d\n", + __func__, temp, i, temp->handle[i], + &temp->device_addr[i], temp->fd[i], + temp->buff_off[i], temp->mapped[i]); +@@ -652,12 +652,12 @@ int unmap_and_deregister_buf(struct msm_vidc_inst *inst, + } + } + if (!keep_node) { +- dprintk(VIDC_DBG, "[UNMAP] AND-FREED binfo: %p\n", temp); ++ dprintk(VIDC_DBG, "[UNMAP] AND-FREED binfo: %pK\n", temp); + list_del(&temp->list); + kfree(temp); + } else { + temp->inactive = true; +- dprintk(VIDC_DBG, "[UNMAP] NOT-FREED binfo: %p\n", temp); ++ dprintk(VIDC_DBG, "[UNMAP] NOT-FREED binfo: %pK\n", temp); + } + exit: + return 0; +@@ -671,7 +671,7 @@ int qbuf_dynamic_buf(struct msm_vidc_inst *inst, + struct v4l2_plane plane[VIDEO_MAX_PLANES] = { {0} }; + + if (!binfo) { +- dprintk(VIDC_ERR, "%s invalid param: %p\n", __func__, binfo); ++ dprintk(VIDC_ERR, "%s invalid param: %pK\n", __func__, binfo); + return -EINVAL; + } + dprintk(VIDC_DBG, "%s fd[0] = %d\n", __func__, binfo->fd[0]); +@@ -694,7 +694,7 @@ int output_buffer_cache_invalidate(struct msm_vidc_inst *inst, + int rc = 0; + + if (!inst) { +- dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst); + return -EINVAL; + } + +@@ -702,7 +702,7 @@ int output_buffer_cache_invalidate(struct msm_vidc_inst *inst, + return 0; + + if (!binfo) { +- dprintk(VIDC_ERR, "%s: invalid buffer info: %p\n", ++ dprintk(VIDC_ERR, "%s: invalid buffer info: %pK\n", + __func__, inst); + return -EINVAL; + } +@@ -780,7 +780,7 @@ int msm_vidc_release_buffers(void *instance, int buffer_type) + rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE); + if (rc) { + dprintk(VIDC_ERR, +- "Failed to move inst: %p to release res done\n", ++ "Failed to move inst: %pK to release res done\n", + inst); + } + } +@@ -862,7 +862,7 @@ int msm_vidc_free_buffers(void *instance, int buffer_type) + for (i = 0; i < bi->num_planes; i++) { + if (bi->handle[i] && bi->mapped[i]) { + dprintk(VIDC_DBG, +- "%s: binfo = 0x%p, handle[%d] = %p, device_addr = %pa, fd = %d, offset = %d, buffer_type 0x%x, mapped = %d\n", ++ "%s: binfo = 0x%pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, buffer_type 0x%x, mapped = %d\n", + __func__, bi, i, bi->handle[i], + &bi->device_addr[i], bi->fd[i], + bi->buff_off[i], bi->type, +@@ -1089,7 +1089,7 @@ int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize) + struct msm_vidc_capability *capability = NULL; + + if (!inst || !fsize) { +- dprintk(VIDC_ERR, "%s: invalid parameter: %p %p\n", ++ dprintk(VIDC_ERR, "%s: invalid parameter: %pK %pK\n", + __func__, inst, fsize); + return -EINVAL; + } +@@ -1156,7 +1156,7 @@ void *msm_vidc_smem_get_client(void *instance) + struct msm_vidc_inst *inst = instance; + + if (!inst || !inst->mem_client) { +- dprintk(VIDC_ERR, "%s: invalid instance or client = %p\n", ++ dprintk(VIDC_ERR, "%s: invalid instance or client = %pK\n", + __func__, inst); + return NULL; + } +@@ -1214,7 +1214,7 @@ static int setup_event_queue(void *inst, + struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst; + + if (!inst || !pvdev) { +- dprintk(VIDC_ERR, "%s Invalid params inst %p pvdev %p\n", ++ dprintk(VIDC_ERR, "%s Invalid params inst %pK pvdev %pK\n", + __func__, inst, pvdev); + return -EINVAL; + } +@@ -1290,7 +1290,7 @@ void *msm_vidc_open(int core_id, int session_type) + goto err_invalid_core; + } + +- pr_info(VIDC_DBG_TAG "Opening video instance: %p, %d\n", ++ pr_info(VIDC_DBG_TAG "Opening video instance: %pK, %d\n", + VIDC_MSG_PRIO2STRING(VIDC_INFO), inst, session_type); + mutex_init(&inst->sync_lock); + mutex_init(&inst->bufq[CAPTURE_PORT].lock); +@@ -1493,7 +1493,7 @@ int msm_vidc_close(void *instance) + + msm_smem_delete_client(inst->mem_client); + +- pr_info(VIDC_DBG_TAG "Closed video instance: %p\n", ++ pr_info(VIDC_DBG_TAG "Closed video instance: %pK\n", + VIDC_MSG_PRIO2STRING(VIDC_INFO), inst); + kfree(inst); + +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c +index f001290..48192b3 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -159,7 +159,7 @@ int msm_comm_get_inst_load(struct msm_vidc_inst *inst, + if (!is_thumbnail_session(inst) && !is_realtime_session(inst) && + (quirks & LOAD_CALC_IGNORE_NON_REALTIME_LOAD)) { + if (!inst->prop.fps) { +- dprintk(VIDC_INFO, "%s: instance:%p prop->fps is set 0\n", __func__, inst); ++ dprintk(VIDC_INFO, "%s: instance:%pK prop->fps is set 0\n", __func__, inst); + load = 0; + } else { + load = msm_comm_get_mbs_per_sec(inst) / inst->prop.fps; +@@ -167,7 +167,7 @@ int msm_comm_get_inst_load(struct msm_vidc_inst *inst, + } + + dprintk(VIDC_DBG, +- "inst[%p]: load %d, wxh %dx%d, fps %d, operating_rate %d, flags 0x%x, quirks 0x%x\n", ++ "inst[%pK]: load %d, wxh %dx%d, fps %d, operating_rate %d, flags 0x%x, quirks 0x%x\n", + inst, load, inst->prop.width[OUTPUT_PORT], + inst->prop.height[OUTPUT_PORT], inst->prop.fps, + inst->operating_rate >> 16, inst->flags, quirks); +@@ -182,7 +182,7 @@ int msm_comm_get_load(struct msm_vidc_core *core, + int num_mbs_per_sec = 0; + + if (!core) { +- dprintk(VIDC_ERR, "Invalid args: %p\n", core); ++ dprintk(VIDC_ERR, "Invalid args: %pK\n", core); + return -EINVAL; + } + +@@ -280,13 +280,13 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core) + struct vidc_bus_vote_data *vote_data = NULL; + + if (!core) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, core); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, core); + return -EINVAL; + } + + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "%s Invalid device handle: %p\n", ++ dprintk(VIDC_ERR, "%s Invalid device handle: %pK\n", + __func__, hdev); + return -EINVAL; + } +@@ -387,7 +387,7 @@ const struct msm_vidc_format *msm_comm_get_pixel_fmt_index( + { + int i, k = 0; + if (!fmt || index < 0) { +- dprintk(VIDC_ERR, "Invalid inputs, fmt = %p, index = %d\n", ++ dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK, index = %d\n", + fmt, index); + return NULL; + } +@@ -409,7 +409,7 @@ struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc( + { + int i; + if (!fmt) { +- dprintk(VIDC_ERR, "Invalid inputs, fmt = %p\n", fmt); ++ dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK\n", fmt); + return NULL; + } + for (i = 0; i < size; i++) { +@@ -572,11 +572,11 @@ static void change_inst_state(struct msm_vidc_inst *inst, + mutex_lock(&inst->lock); + if (inst->state == MSM_VIDC_CORE_INVALID) { + dprintk(VIDC_DBG, +- "Inst: %p is in bad state can't change state to %d\n", ++ "Inst: %pK is in bad state can't change state to %d\n", + inst, state); + goto exit; + } +- dprintk(VIDC_DBG, "Moved inst: %p from state: %d to state: %d\n", ++ dprintk(VIDC_DBG, "Moved inst: %pK from state: %d to state: %d\n", + inst, inst->state, state); + inst->state = state; + exit: +@@ -587,7 +587,7 @@ static int signal_session_msg_receipt(enum command_response cmd, + struct msm_vidc_inst *inst) + { + if (!inst) { +- dprintk(VIDC_ERR, "Invalid(%p) instance id\n", inst); ++ dprintk(VIDC_ERR, "Invalid(%pK) instance id\n", inst); + return -EINVAL; + } + if (IS_SESSION_CMD_VALID(cmd)) { +@@ -628,7 +628,7 @@ static int wait_for_state(struct msm_vidc_inst *inst, + { + int rc = 0; + if (IS_ALREADY_IN_STATE(flipped_state, desired_state)) { +- dprintk(VIDC_INFO, "inst: %p is already in state: %d\n", ++ dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n", + inst, inst->state); + goto err_same_state; + } +@@ -689,7 +689,7 @@ static void handle_session_init_done(enum command_response cmd, void *data) + inst = response->session_id; + if (!inst || !inst->core || !inst->core->device) { + dprintk(VIDC_ERR, +- "%s: invalid parameters, inst %p\n", __func__, inst); ++ "%s: invalid parameters, inst %pK\n", __func__, inst); + return; + } + core = inst->core; +@@ -813,7 +813,7 @@ static void handle_event_change(enum command_response cmd, void *data) + struct buffer_info *binfo = NULL, *temp = NULL; + u32 *ptr = NULL; + +- dprintk(VIDC_DBG, "%s - inst: %p buffer: 0x%pa extra: 0x%pa\n", ++ dprintk(VIDC_DBG, "%s - inst: %pK buffer: 0x%pa extra: 0x%pa\n", + __func__, inst, &event_notify->packet_buffer, + &event_notify->extra_data_buffer); + +@@ -1149,7 +1149,7 @@ static void handle_sys_idle(enum command_response cmd, void *data) + goto exit; + } + +- dprintk(VIDC_DBG, "SYS_IDLE received for core %p\n", core); ++ dprintk(VIDC_DBG, "SYS_IDLE received for core %pK\n", core); + if (core->resources.dynamic_bw_update) { + mutex_lock(&core->lock); + core->idle_stats.start_time = ktime_get(); +@@ -1182,23 +1182,23 @@ static void handle_session_error(enum command_response cmd, void *data) + + if (!inst || !inst->session || !inst->core->device) { + dprintk(VIDC_ERR, +- "Session (%p) not in a stable enough state to handle session error\n", ++ "Session (%pK) not in a stable enough state to handle session error\n", + inst); + return; + } + + hdev = inst->core->device; +- dprintk(VIDC_WARN, "Session error received for session %p\n", inst); ++ dprintk(VIDC_WARN, "Session error received for session %pK\n", inst); + change_inst_state(inst, MSM_VIDC_CORE_INVALID); + + if (response->status == VIDC_ERR_MAX_CLIENTS) { +- dprintk(VIDC_WARN, "Too many clients, rejecting %p", inst); ++ dprintk(VIDC_WARN, "Too many clients, rejecting %pK", inst); + event = V4L2_EVENT_MSM_VIDC_MAX_CLIENTS; + } else if (response->status == VIDC_ERR_NOT_SUPPORTED) { +- dprintk(VIDC_WARN, "Unsupported error for %p", inst); ++ dprintk(VIDC_WARN, "Unsupported error for %pK", inst); + event = V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED; + } else { +- dprintk(VIDC_WARN, "Unknown session error (%d) for %p\n", ++ dprintk(VIDC_WARN, "Unknown session error (%d) for %pK\n", + response->status, inst); + event = V4L2_EVENT_MSM_VIDC_SYS_ERROR; + } +@@ -1213,7 +1213,7 @@ static void msm_comm_clean_notify_client(struct msm_vidc_core *core) + return; + } + +- dprintk(VIDC_WARN, "%s: Core %p\n", __func__, core); ++ dprintk(VIDC_WARN, "%s: Core %pK\n", __func__, core); + mutex_lock(&core->lock); + core->state = VIDC_CORE_INVALID; + +@@ -1222,7 +1222,7 @@ static void msm_comm_clean_notify_client(struct msm_vidc_core *core) + inst->state = MSM_VIDC_CORE_INVALID; + mutex_unlock(&inst->lock); + dprintk(VIDC_WARN, +- "%s Send sys error for inst %p\n", __func__, inst); ++ "%s Send sys error for inst %pK\n", __func__, inst); + msm_vidc_queue_v4l2_event(inst, + V4L2_EVENT_MSM_VIDC_SYS_ERROR); + } +@@ -1255,7 +1255,7 @@ static void handle_sys_error(enum command_response cmd, void *data) + return; + } + +- dprintk(VIDC_WARN, "SYS_ERROR %d received for core %p\n", cmd, core); ++ dprintk(VIDC_WARN, "SYS_ERROR %d received for core %pK\n", cmd, core); + msm_comm_clean_notify_client(core); + hdev = core->device; + mutex_lock(&core->lock); +@@ -1290,12 +1290,12 @@ void msm_comm_session_clean(struct msm_vidc_inst *inst) + + hdev = inst->core->device; + if (hdev && inst->session) { +- dprintk(VIDC_DBG, "cleaning up instance: 0x%p\n", inst); ++ dprintk(VIDC_DBG, "cleaning up instance: 0x%pK\n", inst); + rc = call_hfi_op(hdev, session_clean, + (void *) inst->session); + if (rc) { + dprintk(VIDC_ERR, +- "Session clean failed :%p\n", inst); ++ "Session clean failed :%pK\n", inst); + } + inst->session = NULL; + } +@@ -1696,7 +1696,7 @@ static void handle_fbd(enum command_response cmd, void *data) + + if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { + dprintk(VIDC_DBG, +- "extradata: userptr = %p;" ++ "extradata: userptr = %pK;" + " bytesused = %d; length = %d\n", + (u8 *)vb->v4l2_planes[extra_idx].m.userptr, + vb->v4l2_planes[extra_idx].bytesused, +@@ -1838,13 +1838,13 @@ int msm_comm_scale_clocks_load(struct msm_vidc_core *core, int num_mbs_per_sec) + int codec = 0; + + if (!core) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, core); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, core); + return -EINVAL; + } + + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "%s Invalid device handle: %p\n", ++ dprintk(VIDC_ERR, "%s Invalid device handle: %pK\n", + __func__, hdev); + return -EINVAL; + } +@@ -1996,7 +1996,7 @@ static int msm_comm_session_abort(struct msm_vidc_inst *inst) + msecs_to_jiffies(msm_vidc_hw_rsp_timeout)); + if (!rc) { + dprintk(VIDC_ERR, +- "%s: Wait interrupted or timed out [%p]: %d\n", ++ "%s: Wait interrupted or timed out [%pK]: %d\n", + __func__, inst, abort_completion); + rc = -EBUSY; + } else { +@@ -2023,7 +2023,7 @@ static void handle_thermal_event(struct msm_vidc_core *core) + mutex_unlock(&core->lock); + if (inst->state >= MSM_VIDC_OPEN_DONE && + inst->state < MSM_VIDC_CLOSE_DONE) { +- dprintk(VIDC_WARN, "%s: abort inst %p\n", ++ dprintk(VIDC_WARN, "%s: abort inst %pK\n", + __func__, inst); + + change_inst_state(inst, MSM_VIDC_CORE_INVALID); +@@ -2035,7 +2035,7 @@ static void handle_thermal_event(struct msm_vidc_core *core) + goto err_sess_abort; + } + dprintk(VIDC_WARN, +- "%s Send sys error for inst %p\n", ++ "%s Send sys error for inst %pK\n", + __func__, inst); + msm_vidc_queue_v4l2_event(inst, + V4L2_EVENT_MSM_VIDC_SYS_ERROR); +@@ -2290,7 +2290,7 @@ static int msm_comm_session_init(int flipped_state, + hdev = inst->core->device; + + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_OPEN)) { +- dprintk(VIDC_INFO, "inst: %p is already in state: %d\n", ++ dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2311,7 +2311,7 @@ static int msm_comm_session_init(int flipped_state, + + if (!inst->session) { + dprintk(VIDC_ERR, +- "Failed to call session init for: %p, %p, %d, %d\n", ++ "Failed to call session init for: %pK, %pK, %d, %d\n", + inst->core->device, inst, + inst->session_type, fourcc); + rc = -EINVAL; +@@ -2405,7 +2405,7 @@ static int msm_vidc_load_resources(int flipped_state, + + hdev = core->device; + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) { +- dprintk(VIDC_INFO, "inst: %p is already in state: %d\n", ++ dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2441,7 +2441,7 @@ static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst) + + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) { + dprintk(VIDC_INFO, +- "inst: %p is already in state: %d\n", ++ "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2471,7 +2471,7 @@ static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst) + + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) { + dprintk(VIDC_INFO, +- "inst: %p is already in state: %d\n", ++ "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2501,7 +2501,7 @@ static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst) + + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) { + dprintk(VIDC_INFO, +- "inst: %p is already in state: %d\n", ++ "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2533,7 +2533,7 @@ static int msm_comm_session_close(int flipped_state, + hdev = inst->core->device; + if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) { + dprintk(VIDC_INFO, +- "inst: %p is already in state: %d\n", ++ "inst: %pK is already in state: %d\n", + inst, inst->state); + goto exit; + } +@@ -2939,16 +2939,16 @@ int msm_comm_try_state(struct msm_vidc_inst *inst, int state) + struct msm_vidc_core *core; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + dprintk(VIDC_DBG, +- "Trying to move inst: %p from: 0x%x to 0x%x\n", ++ "Trying to move inst: %pK from: 0x%x to 0x%x\n", + inst, inst->state, state); + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", inst); ++ "Invalid core pointer = %pK\n", inst); + return -EINVAL; + } + mutex_lock(&inst->sync_lock); +@@ -3117,7 +3117,7 @@ int msm_comm_qbuf(struct vb2_buffer *vb) + int extra_idx = 0; + + if (!vb || !vb->vb2_queue) { +- dprintk(VIDC_ERR, "%s: Invalid input: %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid input: %pK\n", + __func__, vb); + return -EINVAL; + } +@@ -3125,7 +3125,7 @@ int msm_comm_qbuf(struct vb2_buffer *vb) + q = vb->vb2_queue; + inst = q->drv_priv; + if (!inst) { +- dprintk(VIDC_ERR, "%s: Invalid input: %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid input: %pK\n", + __func__, vb); + return -EINVAL; + } +@@ -3133,12 +3133,12 @@ int msm_comm_qbuf(struct vb2_buffer *vb) + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid input: %p, %p, %p\n", inst, core, vb); ++ "Invalid input: %pK, %pK, %pK\n", inst, core, vb); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "%s: Invalid input: %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid input: %pK\n", + __func__, hdev); + return -EINVAL; + } +@@ -3292,7 +3292,7 @@ int msm_comm_qbuf(struct vb2_buffer *vb) + (void *) inst->session, &seq_hdr); + if (!rc) { + inst->vb2_seq_hdr = vb; +- dprintk(VIDC_DBG, "Seq_hdr: %p\n", ++ dprintk(VIDC_DBG, "Seq_hdr: %pK\n", + inst->vb2_seq_hdr); + } + atomic_dec(&inst->seq_hdr_reqs); +@@ -3406,7 +3406,7 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype, + msecs_to_jiffies(msm_vidc_hw_rsp_timeout)); + if (!rc) { + dprintk(VIDC_ERR, +- "%s: Wait interrupted or timed out [%p]: %d\n", ++ "%s: Wait interrupted or timed out [%pK]: %d\n", + __func__, inst, + SESSION_MSG_INDEX(SESSION_PROPERTY_INFO)); + inst->state = MSM_VIDC_CORE_INVALID; +@@ -3444,18 +3444,18 @@ int msm_comm_release_output_buffers(struct msm_vidc_inst *inst) + struct hfi_device *hdev; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", core); ++ "Invalid core pointer = %pK\n", core); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev); ++ dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev); + return -EINVAL; + } + mutex_lock(&inst->outputbufs.lock); +@@ -3551,18 +3551,18 @@ int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst, + enum hal_buffer sufficiency = HAL_BUFFER_NONE; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", core); ++ "Invalid core pointer = %pK\n", core); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev); ++ dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev); + return -EINVAL; + } + +@@ -3639,18 +3639,18 @@ int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst) + struct hfi_device *hdev; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", core); ++ "Invalid core pointer = %pK\n", core); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev); ++ dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev); + return -EINVAL; + } + +@@ -3699,7 +3699,7 @@ int msm_comm_try_set_prop(struct msm_vidc_inst *inst, + int rc = 0; + struct hfi_device *hdev; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid input: %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid input: %pK\n", inst); + return -EINVAL; + } + +@@ -3913,7 +3913,7 @@ void msm_comm_flush_pending_dynamic_buffers(struct msm_vidc_inst *inst) + list_for_each_entry(binfo, &inst->registeredbufs.list, list) { + if (binfo->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + dprintk(VIDC_DBG, +- "%s: binfo = %p device_addr = 0x%pa\n", ++ "%s: binfo = %pK device_addr = 0x%pa\n", + __func__, binfo, &binfo->device_addr[0]); + buf_ref_put(inst, binfo); + } +@@ -3933,18 +3933,18 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags) + struct hfi_device *hdev; + if (!inst) { + dprintk(VIDC_ERR, +- "Invalid instance pointer = %p\n", inst); ++ "Invalid instance pointer = %pK\n", inst); + return -EINVAL; + } + core = inst->core; + if (!core) { + dprintk(VIDC_ERR, +- "Invalid core pointer = %p\n", core); ++ "Invalid core pointer = %pK\n", core); + return -EINVAL; + } + hdev = core->device; + if (!hdev) { +- dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev); ++ dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev); + return -EINVAL; + } + +@@ -3961,7 +3961,7 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags) + core->state == VIDC_CORE_UNINIT || + core->state == VIDC_CORE_INVALID) { + dprintk(VIDC_ERR, +- "Core %p and inst %p are in bad state\n", ++ "Core %pK and inst %pK are in bad state\n", + core, inst); + msm_comm_flush_in_invalid_state(inst); + return 0; +@@ -4153,7 +4153,7 @@ int msm_vidc_trigger_ssr(struct msm_vidc_core *core, + int rc = 0; + struct hfi_device *hdev; + if (!core || !core->device) { +- dprintk(VIDC_WARN, "Invalid parameters: %p\n", core); ++ dprintk(VIDC_WARN, "Invalid parameters: %pK\n", core); + return -EINVAL; + } + hdev = core->device; +@@ -4389,7 +4389,7 @@ int msm_comm_kill_session(struct msm_vidc_inst *inst) + change_inst_state(inst, MSM_VIDC_CLOSE_DONE); + } else { + dprintk(VIDC_WARN, +- "Inactive session %p, triggering an internal session error\n", ++ "Inactive session %pK, triggering an internal session error\n", + inst); + msm_comm_generate_session_error(inst); + +@@ -4421,7 +4421,7 @@ struct msm_smem *msm_comm_smem_alloc(struct msm_vidc_inst *inst, + struct msm_smem *m = NULL; + + if (!inst || !inst->core) { +- dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst); + return NULL; + } + mutex_lock(&inst->core->lock); +@@ -4439,7 +4439,7 @@ void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem) + { + if (!inst || !inst->core || !mem) { + dprintk(VIDC_ERR, +- "%s: invalid params: %p %p\n", __func__, inst, mem); ++ "%s: invalid params: %pK %pK\n", __func__, inst, mem); + return; + } + +@@ -4458,7 +4458,7 @@ int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst, + { + if (!inst || !mem) { + dprintk(VIDC_ERR, +- "%s: invalid params: %p %p\n", __func__, inst, mem); ++ "%s: invalid params: %pK %pK\n", __func__, inst, mem); + return -EINVAL; + } + return msm_smem_cache_operations(inst->mem_client, mem, cache_ops); +@@ -4470,7 +4470,7 @@ struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst, + struct msm_smem *m = NULL; + + if (!inst || !inst->core) { +- dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst); + return NULL; + } + +@@ -4496,7 +4496,7 @@ int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst, + int *domain_num, int *partition_num) + { + if (!inst || !domain_num || !partition_num) { +- dprintk(VIDC_ERR, "%s: invalid params: %p %p %p\n", ++ dprintk(VIDC_ERR, "%s: invalid params: %pK %pK %pK\n", + __func__, inst, domain_num, partition_num); + return -EINVAL; + } +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c b/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c +index 708b44a..231ec66 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014 - 2016, The 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 +@@ -40,7 +40,7 @@ static inline int msm_dcvs_count_active_instances(struct msm_vidc_core *core) + struct msm_vidc_inst *inst = NULL; + + if (!core) { +- dprintk(VIDC_ERR, "%s: Invalid args: %p\n", __func__, core); ++ dprintk(VIDC_ERR, "%s: Invalid args: %pK\n", __func__, core); + return -EINVAL; + } + +@@ -116,7 +116,7 @@ static void msm_dcvs_dec_check_and_scale_clocks(struct msm_vidc_inst *inst) + void msm_dcvs_check_and_scale_clocks(struct msm_vidc_inst *inst, bool is_etb) + { + if (!inst) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + +@@ -168,7 +168,7 @@ void msm_dcvs_init_load(struct msm_vidc_inst *inst) + dprintk(VIDC_DBG, "Init DCVS Load\n"); + + if (!inst || !inst->core) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + +@@ -217,7 +217,7 @@ void msm_dcvs_init(struct msm_vidc_inst *inst) + dprintk(VIDC_DBG, "Init DCVS Struct\n"); + + if (!inst) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + +@@ -234,7 +234,7 @@ void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst) + struct hal_buffer_requirements *output_buf_req; + + if (!inst) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, inst); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst); + return; + } + dcvs = &inst->dcvs; +@@ -243,7 +243,7 @@ void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst) + output_buf_req = get_buff_req_buffer(inst, + msm_comm_get_hal_output_buffer(inst)); + if (!output_buf_req) { +- dprintk(VIDC_ERR, "%s : Get output buffer req failed %p\n", ++ dprintk(VIDC_ERR, "%s : Get output buffer req failed %pK\n", + __func__, inst); + mutex_unlock(&inst->lock); + return; +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +index c422ed7..5cf5e81 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -76,13 +76,13 @@ static ssize_t core_info_read(struct file *file, char __user *buf, + int i = 0, rc = 0; + + if (!core || !core->device) { +- dprintk(VIDC_ERR, "Invalid params, core: %p\n", core); ++ dprintk(VIDC_ERR, "Invalid params, core: %pK\n", core); + return 0; + } + hdev = core->device; + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); +- write_str(&dbg_buf, "CORE %d: 0x%p\n", core->id, core); ++ write_str(&dbg_buf, "CORE %d: 0x%pK\n", core->id, core); + write_str(&dbg_buf, "===============================\n"); + write_str(&dbg_buf, "Core state: %d\n", core->state); + rc = call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data, &fw_info); +@@ -242,7 +242,7 @@ struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core, + struct dentry *dir = NULL; + char debugfs_name[MAX_DEBUGFS_NAME]; + if (!core) { +- dprintk(VIDC_ERR, "Invalid params, core: %p\n", core); ++ dprintk(VIDC_ERR, "Invalid params, core: %pK\n", core); + goto failed_create_dir; + } + +@@ -306,15 +306,15 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + struct msm_vidc_inst *inst = file->private_data; + int i, j; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid params, core: %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid params, core: %pK\n", inst); + return 0; + } + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); +- write_str(&dbg_buf, "INSTANCE: 0x%p (%s)\n", inst, ++ write_str(&dbg_buf, "INSTANCE: 0x%pK (%s)\n", inst, + inst->session_type == MSM_VIDC_ENCODER ? "Encoder" : "Decoder"); + write_str(&dbg_buf, "===============================\n"); +- write_str(&dbg_buf, "core: 0x%p\n", inst->core); ++ write_str(&dbg_buf, "core: 0x%pK\n", inst->core); + write_str(&dbg_buf, "height: %d\n", inst->prop.height[CAPTURE_PORT]); + write_str(&dbg_buf, "width: %d\n", inst->prop.width[CAPTURE_PORT]); + write_str(&dbg_buf, "fps: %d\n", inst->prop.fps); +@@ -381,10 +381,10 @@ struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst, + struct dentry *dir = NULL; + char debugfs_name[MAX_DEBUGFS_NAME]; + if (!inst) { +- dprintk(VIDC_ERR, "Invalid params, inst: %p\n", inst); ++ dprintk(VIDC_ERR, "Invalid params, inst: %pK\n", inst); + goto failed_create_dir; + } +- snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%p", inst); ++ snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%pK", inst); + dir = debugfs_create_dir(debugfs_name, parent); + if (!dir) { + dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n"); +diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c +index 10f4baa..31f6263 100644 +--- a/drivers/media/platform/msm/vidc/q6_hfi.c ++++ b/drivers/media/platform/msm/vidc/q6_hfi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2016, The 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 +@@ -202,7 +202,7 @@ static int q6_hfi_register_iommu_domains(struct q6_hfi_device *device) + struct iommu_info *iommu_map; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "Invalid parameter: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid parameter: %pK\n", device); + return -EINVAL; + } + +@@ -220,7 +220,7 @@ static int q6_hfi_register_iommu_domains(struct q6_hfi_device *device) + domain = iommu_group_get_iommudata(iommu_map->group); + if (IS_ERR_OR_NULL(domain)) { + dprintk(VIDC_ERR, +- "Failed to get domain data for group %p\n", ++ "Failed to get domain data for group %pK\n", + iommu_map->group); + rc = -EINVAL; + goto fail_group; +@@ -228,7 +228,7 @@ static int q6_hfi_register_iommu_domains(struct q6_hfi_device *device) + iommu_map->domain = msm_find_domain_no(domain); + if (iommu_map->domain < 0) { + dprintk(VIDC_ERR, +- "Failed to get domain index for domain %p\n", ++ "Failed to get domain index for domain %pK\n", + domain); + rc = -EINVAL; + goto fail_group; +@@ -254,7 +254,7 @@ static void q6_hfi_deregister_iommu_domains(struct q6_hfi_device *device) + int i = 0; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "Invalid parameter: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid parameter: %pK\n", device); + return; + } + +@@ -347,7 +347,7 @@ static void *q6_hfi_get_device(u32 device_id, + int rc = 0; + + if (!callback) { +- dprintk(VIDC_ERR, "%s Invalid params: %p\n", ++ dprintk(VIDC_ERR, "%s Invalid params: %pK\n", + __func__, callback); + return NULL; + } +@@ -663,7 +663,7 @@ static int q6_hfi_session_clean(void *session) + return -EINVAL; + } + sess_close = session; +- dprintk(VIDC_DBG, "deleted the session: 0x%p\n", ++ dprintk(VIDC_DBG, "deleted the session: 0x%pK\n", + sess_close->session_id); + mutex_lock(&((struct q6_hfi_device *) + sess_close->device)->session_lock); +@@ -1207,7 +1207,7 @@ static int q6_hfi_iommu_attach(struct q6_hfi_device *device) + struct iommu_info *iommu_map; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "Invalid parameter: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid parameter: %pK\n", device); + return -EINVAL; + } + +@@ -1222,7 +1222,7 @@ static int q6_hfi_iommu_attach(struct q6_hfi_device *device) + rc = PTR_ERR(domain) ?: -EINVAL; + break; + } +- dprintk(VIDC_DBG, "Attaching domain(id:%d) %p to group %p\n", ++ dprintk(VIDC_DBG, "Attaching domain(id:%d) %pK to group %pK\n", + iommu_map->domain, domain, group); + rc = iommu_attach_group(domain, group); + if (rc) { +@@ -1253,7 +1253,7 @@ static void q6_hfi_iommu_detach(struct q6_hfi_device *device) + int i; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "Invalid parameter: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid parameter: %pK\n", device); + return; + } + +@@ -1382,7 +1382,7 @@ int q6_hfi_initialize(struct hfi_device *hdev, u32 device_id, + int rc = 0; + + if (!hdev || !res || !callback) { +- dprintk(VIDC_ERR, "Invalid params: %p %p %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK %pK %pK\n", + hdev, res, callback); + rc = -EINVAL; + goto err_hfi_init; +diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c +index 76ad1bc..0015c84 100644 +--- a/drivers/media/platform/msm/vidc/venus_hfi.c ++++ b/drivers/media/platform/msm/vidc/venus_hfi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -370,7 +370,7 @@ static int venus_hfi_write_queue(void *info, u8 *packet, u32 *rx_req_is_set) + } + + if (msm_vidc_debug & VIDC_PKT) { +- dprintk(VIDC_PKT, "%s: %p\n", __func__, qinfo); ++ dprintk(VIDC_PKT, "%s: %pK\n", __func__, qinfo); + venus_hfi_dump_packet(packet); + } + +@@ -580,7 +580,7 @@ static int venus_hfi_read_queue(void *info, u8 *packet, u32 *pb_tx_req_is_set) + + if ((msm_vidc_debug & VIDC_PKT) && + (queue->qhdr_type & HFI_Q_ID_CTRL_TO_HOST_MSG_Q)) { +- dprintk(VIDC_PKT, "%s: %p\n", __func__, qinfo); ++ dprintk(VIDC_PKT, "%s: %pK\n", __func__, qinfo); + venus_hfi_dump_packet(packet); + } + +@@ -611,7 +611,7 @@ static int venus_hfi_alloc(struct venus_hfi_device *dev, void *mem, + rc = -ENOMEM; + goto fail_smem_alloc; + } +- dprintk(VIDC_DBG, "venus_hfi_alloc: ptr = %p, size = %d\n", ++ dprintk(VIDC_DBG, "venus_hfi_alloc: ptr = %pK, size = %d\n", + alloc->kvaddr, size); + rc = msm_smem_cache_operations(dev->hal_client, alloc, + SMEM_CACHE_CLEAN); +@@ -631,7 +631,7 @@ fail_smem_alloc: + static void venus_hfi_free(struct venus_hfi_device *dev, struct msm_smem *mem) + { + if (!dev || !mem) { +- dprintk(VIDC_ERR, "invalid param %p %p\n", dev, mem); ++ dprintk(VIDC_ERR, "invalid param %pK %pK\n", dev, mem); + return; + } + +@@ -647,7 +647,7 @@ static void venus_hfi_write_register( + u32 hwiosymaddr = reg; + u8 *base_addr; + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return; + } + if (device->clk_state != ENABLED_PREPARED) { +@@ -657,7 +657,7 @@ static void venus_hfi_write_register( + } + + base_addr = device->hal_data->register_base; +- dprintk(VIDC_DBG, "Base addr: 0x%p, written to: 0x%x, Value: 0x%x...\n", ++ dprintk(VIDC_DBG, "Base addr: 0x%pK, written to: 0x%x, Value: 0x%x...\n", + base_addr, hwiosymaddr, value); + base_addr += hwiosymaddr; + writel_relaxed(value, base_addr); +@@ -669,7 +669,7 @@ static int venus_hfi_read_register(struct venus_hfi_device *device, u32 reg) + int rc = 0; + u8 *base_addr; + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + if (device->clk_state != ENABLED_PREPARED) { +@@ -681,7 +681,7 @@ static int venus_hfi_read_register(struct venus_hfi_device *device, u32 reg) + + rc = readl_relaxed(base_addr + reg); + rmb(); +- dprintk(VIDC_DBG, "Base addr: 0x%p, read from: 0x%x, value: 0x%x...\n", ++ dprintk(VIDC_DBG, "Base addr: 0x%pK, read from: 0x%x, value: 0x%x...\n", + base_addr, reg, rc); + + return rc; +@@ -783,7 +783,7 @@ static void venus_hfi_iommu_detach(struct venus_hfi_device *device) + int i; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "Invalid paramter: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid paramter: %pK\n", device); + return; + } + +@@ -1209,7 +1209,7 @@ static int __alloc_ocmem(struct venus_hfi_device *device) + unsigned long size; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n", ++ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%pK\n", + __func__, device); + return -EINVAL; + } +@@ -1244,7 +1244,7 @@ static int __free_ocmem(struct venus_hfi_device *device) + int rc = 0; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n", ++ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%pK\n", + __func__, device); + return -EINVAL; + } +@@ -1268,14 +1268,14 @@ static int __set_ocmem(struct venus_hfi_device *device, bool locked) + struct on_chip_mem *ocmem; + + if (!device) { +- dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n", ++ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%pK\n", + __func__, device); + return -EINVAL; + } + + ocmem = &device->resources.ocmem; + if (!ocmem->buf) { +- dprintk(VIDC_ERR, "Invalid params, ocmem_buffer: 0x%p\n", ++ dprintk(VIDC_ERR, "Invalid params, ocmem_buffer: 0x%pK\n", + ocmem->buf); + return -EINVAL; + } +@@ -1304,7 +1304,7 @@ static int __unset_ocmem(struct venus_hfi_device *device) + int rc = 0; + + if (!device) { +- dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n", ++ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%pK\n", + __func__, device); + rc = -EINVAL; + goto ocmem_unset_failed; +@@ -1335,7 +1335,7 @@ static int __alloc_set_ocmem(struct venus_hfi_device *device, bool locked) + int rc = 0; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n", ++ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%pK\n", + __func__, device); + return -EINVAL; + } +@@ -1375,7 +1375,7 @@ static int __unset_free_ocmem(struct venus_hfi_device *device) + int rc = 0; + + if (!device || !device->res) { +- dprintk(VIDC_ERR, "%s Invalid param, device: 0x%p\n", ++ dprintk(VIDC_ERR, "%s Invalid param, device: 0x%pK\n", + __func__, device); + return -EINVAL; + } +@@ -1551,7 +1551,7 @@ static unsigned long venus_hfi_get_core_clock_rate(void *dev) + struct clock_info *vc; + + if (!device) { +- dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, device); ++ dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, device); + return -EINVAL; + } + +@@ -1607,7 +1607,7 @@ static int venus_hfi_halt_axi(struct venus_hfi_device *device) + u32 reg; + int rc = 0; + if (!device) { +- dprintk(VIDC_ERR, "Invalid input: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid input: %pK\n", device); + return -EINVAL; + } + /* +@@ -1642,7 +1642,7 @@ static inline int venus_hfi_power_off(struct venus_hfi_device *device) + int rc = 0; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + if (!device->power_enabled) { +@@ -1709,7 +1709,7 @@ static inline int venus_hfi_power_on(struct venus_hfi_device *device) + int rc = 0; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + if (device->power_enabled) +@@ -1825,7 +1825,7 @@ static int venus_hfi_power_enable(void *dev) + int rc = 0; + struct venus_hfi_device *device = dev; + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + mutex_lock(&device->write_lock); +@@ -1845,7 +1845,7 @@ static int venus_hfi_regulator_set_voltage( + struct regulator_info *rinfo = NULL; + + if (!device || !cv_info) { +- dprintk(VIDC_WARN, "%s: invalid args %p %p\n", ++ dprintk(VIDC_WARN, "%s: invalid args %pK %pK\n", + __func__, device, cv_info); + return -EINVAL; + } +@@ -1893,7 +1893,7 @@ static int venus_hfi_scale_regulators(struct venus_hfi_device *device, + bool matches = false; + + if (!device || !data) { +- dprintk(VIDC_ERR, "%s: Invalid args %p, %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid args %pK, %pK\n", + __func__, device, data); + return -EINVAL; + } +@@ -1968,7 +1968,7 @@ static int venus_hfi_scale_clocks(void *dev, int load, + struct venus_hfi_device *device = dev; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid args: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid args: %pK\n", device); + return -EINVAL; + } + +@@ -2566,7 +2566,7 @@ static int venus_hfi_core_init(void *device) + goto err_core_init; + } + +- dprintk(VIDC_DBG, "Dev_Virt: 0x%pa, Reg_Virt: 0x%p\n", ++ dprintk(VIDC_DBG, "Dev_Virt: 0x%pa, Reg_Virt: 0x%pK\n", + &dev->hal_data->firmware_base, + dev->hal_data->register_base); + +@@ -2718,12 +2718,12 @@ static void venus_hfi_core_clear_interrupt(struct venus_hfi_device *device) + device->intr_status |= intr_status; + device->reg_count++; + dprintk(VIDC_DBG, +- "INTERRUPT for device: 0x%p: times: %d interrupt_status: %d\n", ++ "INTERRUPT for device: 0x%pK: times: %d interrupt_status: %d\n", + device, device->reg_count, intr_status); + } else { + device->spur_count++; + dprintk(VIDC_INFO, +- "SPURIOUS_INTR for device: 0x%p: times: %d interrupt_status: %d\n", ++ "SPURIOUS_INTR for device: 0x%pK: times: %d interrupt_status: %d\n", + device, device->spur_count, intr_status); + } + +@@ -2876,7 +2876,7 @@ static int venus_hfi_session_clean(void *session) + sess_close = session; + device = sess_close->device; + venus_hfi_flush_debug_queue(sess_close->device, NULL); +- dprintk(VIDC_DBG, "deleted the session: 0x%p\n", ++ dprintk(VIDC_DBG, "deleted the session: 0x%pK\n", + sess_close); + mutex_lock(&device->session_lock); + list_del(&sess_close->list); +@@ -2914,7 +2914,7 @@ static void *venus_hfi_session_init(void *device, void *session_id, + new_session->codec = codec_type; + new_session->domain = session_type; + dprintk(VIDC_DBG, +- "%s: inst %p, session %p, codec 0x%x, domain 0x%x\n", ++ "%s: inst %pK, session %pK, codec 0x%x, domain 0x%x\n", + __func__, session_id, new_session, + new_session->codec, new_session->domain); + +@@ -2992,7 +2992,7 @@ static int venus_hfi_session_abort(void *sess) + struct hal_session *session; + session = sess; + if (!session || !session->device) { +- dprintk(VIDC_ERR, "%s: Invalid Params %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid Params %pK\n", + __func__, session); + return -EINVAL; + } +@@ -3012,7 +3012,7 @@ static int venus_hfi_session_set_buffers(void *sess, + struct venus_hfi_device *device; + + if (!session || !session->device || !buffer_info) { +- dprintk(VIDC_ERR, "%s: Invalid Params, %p %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid Params, %pK %pK\n", + __func__, session, buffer_info); + return -EINVAL; + } +@@ -3047,7 +3047,7 @@ static int venus_hfi_session_release_buffers(void *sess, + struct venus_hfi_device *device; + + if (!session || !session->device || !buffer_info) { +- dprintk(VIDC_ERR, "%s: Invalid Params %p, %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid Params %pK, %pK\n", + __func__, session, buffer_info); + return -EINVAL; + } +@@ -3738,7 +3738,7 @@ static void venus_hfi_response_handler(struct venus_hfi_device *device) + } + venus_hfi_flush_debug_queue(device, packet); + } else { +- dprintk(VIDC_DBG, "device (%p) is in deinit state\n", device); ++ dprintk(VIDC_DBG, "device (%pK) is in deinit state\n", device); + } + kfree(packet); + } +@@ -3750,7 +3750,7 @@ static void venus_hfi_core_work_handler(struct work_struct *work) + + dprintk(VIDC_INFO, "GOT INTERRUPT\n"); + if (!device->callback) { +- dprintk(VIDC_ERR, "No interrupt callback function: %p\n", ++ dprintk(VIDC_ERR, "No interrupt callback function: %pK\n", + device); + return; + } +@@ -3850,7 +3850,7 @@ static inline int venus_hfi_init_clocks(struct msm_vidc_platform_resources *res, + struct clock_info *cl = NULL; + + if (!res || !device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + +@@ -3921,7 +3921,7 @@ static inline void venus_hfi_disable_unprepare_clks( + struct clock_info *cl; + + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return; + } + +@@ -3957,7 +3957,7 @@ static inline int venus_hfi_prepare_enable_clks(struct venus_hfi_device *device) + struct clock_info *cl = NULL, *cl_fail = NULL; + int rc = 0; + if (!device) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", device); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", device); + return -EINVAL; + } + +@@ -4026,7 +4026,7 @@ static int venus_hfi_register_iommu_domains(struct venus_hfi_device *device, + domain = iommu_group_get_iommudata(iommu_map->group); + if (!domain) { + dprintk(VIDC_ERR, +- "Failed to get domain data for group %p\n", ++ "Failed to get domain data for group %pK\n", + iommu_map->group); + rc = -EINVAL; + goto fail_group; +@@ -4034,7 +4034,7 @@ static int venus_hfi_register_iommu_domains(struct venus_hfi_device *device, + iommu_map->domain = msm_find_domain_no(domain); + if (iommu_map->domain < 0) { + dprintk(VIDC_ERR, +- "Failed to get domain index for domain %p\n", ++ "Failed to get domain index for domain %pK\n", + domain); + rc = -EINVAL; + goto fail_group; +@@ -4180,7 +4180,7 @@ static int venus_hfi_init_resources(struct venus_hfi_device *device, + + device->res = res; + if (!res) { +- dprintk(VIDC_ERR, "Invalid params: %p\n", res); ++ dprintk(VIDC_ERR, "Invalid params: %pK\n", res); + return -ENODEV; + } + +@@ -4237,7 +4237,7 @@ static int venus_hfi_iommu_get_domain_partition(void *dev, u32 flags, + struct venus_hfi_device *device = dev; + + if (!device) { +- dprintk(VIDC_ERR, "%s: Invalid param device: %p\n", ++ dprintk(VIDC_ERR, "%s: Invalid param device: %pK\n", + __func__, device); + return -EINVAL; + } +@@ -4262,7 +4262,7 @@ static int protect_cp_mem(struct venus_hfi_device *device) + + iommu_group_set = &device->res->iommu_group_set; + if (!iommu_group_set) { +- dprintk(VIDC_ERR, "invalid params: %p\n", iommu_group_set); ++ dprintk(VIDC_ERR, "invalid params: %pK\n", iommu_group_set); + return -EINVAL; + } + +@@ -4430,7 +4430,7 @@ static int venus_hfi_load_fw(void *dev) + struct venus_hfi_device *device = dev; + + if (!device) { +- dprintk(VIDC_ERR, "%s Invalid paramter: %p\n", ++ dprintk(VIDC_ERR, "%s Invalid paramter: %pK\n", + __func__, device); + return -EINVAL; + } +@@ -4520,7 +4520,7 @@ static void venus_hfi_unload_fw(void *dev) + { + struct venus_hfi_device *device = dev; + if (!device) { +- dprintk(VIDC_ERR, "%s Invalid paramter: %p\n", ++ dprintk(VIDC_ERR, "%s Invalid paramter: %pK\n", + __func__, device); + return; + } +@@ -4556,7 +4556,7 @@ static int venus_hfi_get_fw_info(void *dev, struct hal_fw_info *fw_info) + + if (!device || !fw_info) { + dprintk(VIDC_ERR, +- "%s Invalid paramter: device = %p fw_info = %p\n", ++ "%s Invalid paramter: device = %pK fw_info = %pK\n", + __func__, device, fw_info); + return -EINVAL; + } +@@ -4745,7 +4745,7 @@ static void *venus_hfi_get_device(u32 device_id, + int rc = 0; + + if (!res || !callback) { +- dprintk(VIDC_ERR, "Invalid params: %p %p\n", res, callback); ++ dprintk(VIDC_ERR, "Invalid params: %pK %pK\n", res, callback); + return NULL; + } + +@@ -4845,7 +4845,7 @@ int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id, + int rc = 0; + + if (!hdev || !res || !callback) { +- dprintk(VIDC_ERR, "Invalid params: %p %p %p\n", ++ dprintk(VIDC_ERR, "Invalid params: %pK %pK %pK\n", + hdev, res, callback); + rc = -EINVAL; + goto err_venus_hfi_init; +diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.c b/drivers/media/platform/msm/vidc/vidc_hfi.c +index ef0de37..193b42f 100644 +--- a/drivers/media/platform/msm/vidc/vidc_hfi.c ++++ b/drivers/media/platform/msm/vidc/vidc_hfi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -61,7 +61,7 @@ void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type, + struct hfi_device *hdev) + { + if (!hdev) { +- dprintk(VIDC_ERR, "%s invalid device %p", __func__, hdev); ++ dprintk(VIDC_ERR, "%s invalid device %pK", __func__, hdev); + return; + } + +diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.c b/drivers/media/platform/msm/vidc/vmem/vmem.c +index 81e5b08..fb733fb 100644 +--- a/drivers/media/platform/msm/vidc/vmem/vmem.c ++++ b/drivers/media/platform/msm/vidc/vmem/vmem.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2016, The 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 +@@ -115,7 +115,7 @@ static inline u32 __readl(void * __iomem addr) + { + u32 value = 0; + +- pr_debug("read %p ", addr); ++ pr_debug("read %pK ", addr); + value = readl_relaxed(addr); + pr_debug("-> %08x\n", value); + +@@ -124,7 +124,7 @@ static inline u32 __readl(void * __iomem addr) + + static inline void __writel(u32 val, void * __iomem addr) + { +- pr_debug("write %08x -> %p\n", val, addr); ++ pr_debug("write %08x -> %pK\n", val, addr); + writel_relaxed(val, addr); + /* + * Commit all writes via a mem barrier, as subsequent __readl() +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6750/0.patch b/Patches/Linux_CVEs/CVE-2016-6750/0.patch new file mode 100644 index 00000000..f492aa47 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6750/0.patch @@ -0,0 +1,101 @@ +From 34bda711a1c7bc7f9fd7bea3a5be439ed00577e5 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Ramasubramanian +Date: Tue, 16 Aug 2016 11:24:00 -0600 +Subject: soc: qcom: smp2p: Fix kernel address leak + +Change format string to %pK instead of %p in the debug statements. This +change fixes kernel address leaks from the usage of %p. + +CRs-Fixed: 1052825 +Change-Id: Ib95f691919a2977f5436cd4c6ac4a002d70dd729 +Signed-off-by: Chris Lew +Signed-off-by: Karthikeyan Ramasubramanian +--- + drivers/gpio/gpio-msm-smp2p.c | 2 +- + drivers/soc/qcom/smp2p.c | 6 +++--- + drivers/soc/qcom/smp2p_debug.c | 4 ++-- + drivers/soc/qcom/smp2p_test_common.h | 5 +++-- + 4 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpio/gpio-msm-smp2p.c b/drivers/gpio/gpio-msm-smp2p.c +index bde81f0..b426a80 100644 +--- a/drivers/gpio/gpio-msm-smp2p.c ++++ b/drivers/gpio/gpio-msm-smp2p.c +@@ -368,7 +368,7 @@ static int smp2p_irq_map(struct irq_domain *domain_ptr, unsigned int virq, + + chip = domain_ptr->host_data; + if (!chip) { +- SMP2P_ERR("%s: invalid domain ptr %p\n", __func__, domain_ptr); ++ SMP2P_ERR("%s: invalid domain ptr\n", __func__); + return -ENODEV; + } + +diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c +index fc5688b..79b8ffb 100644 +--- a/drivers/soc/qcom/smp2p.c ++++ b/drivers/soc/qcom/smp2p.c +@@ -1,6 +1,6 @@ + /* drivers/soc/qcom/smp2p.c + * +- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2016, The 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 +@@ -519,8 +519,8 @@ static void smp2p_find_entry_v1(struct smp2p_smem __iomem *item, + char entry_name[SMP2P_MAX_ENTRY_NAME]; + + if (!item || !name || !entry_ptr) { +- SMP2P_ERR("%s: invalid arguments %p, %p, %p\n", +- __func__, item, name, entry_ptr); ++ SMP2P_ERR("%s: invalid arguments %d %d %d\n", ++ __func__, !item, !name, !entry_ptr); + return; + } + +diff --git a/drivers/soc/qcom/smp2p_debug.c b/drivers/soc/qcom/smp2p_debug.c +index 4deb05a..8d98d07 100644 +--- a/drivers/soc/qcom/smp2p_debug.c ++++ b/drivers/soc/qcom/smp2p_debug.c +@@ -1,6 +1,6 @@ + /* drivers/soc/qcom/smp2p_debug.c + * +- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2014,2016 The 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 +@@ -41,7 +41,7 @@ static void smp2p_int_stats(struct seq_file *s) + pid != SMP2P_REMOTE_MOCK_PROC) + continue; + +- seq_printf(s, "| %5s (%d) | %11u | %10u | %10u | %p | %08x |\n", ++ seq_printf(s, "| %5s (%d) | %11u | %10u | %10u | %pK | %08x |\n", + int_cfg[pid].name, + pid, int_cfg[pid].in_int_id, + int_cfg[pid].in_interrupt_count, +diff --git a/drivers/soc/qcom/smp2p_test_common.h b/drivers/soc/qcom/smp2p_test_common.h +index 747a812..3be519b 100644 +--- a/drivers/soc/qcom/smp2p_test_common.h ++++ b/drivers/soc/qcom/smp2p_test_common.h +@@ -1,6 +1,6 @@ + /* drivers/soc/qcom/smp2p_test_common.h + * +- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2014,2016 The 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 +@@ -49,7 +49,8 @@ + void *a_tmp = (a); \ + void *b_tmp = (b); \ + if (!((a_tmp)cmp(b_tmp))) { \ +- seq_printf(s, "%s:%d Fail: " #a "(%p) " #cmp " " #b "(%p)\n", \ ++ seq_printf(s, "%s:%d Fail: " #a "(%pK) " #cmp \ ++ " " #b "(%pK)\n", \ + __func__, __LINE__, \ + a_tmp, b_tmp); \ + failed = 1; \ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6751/0.patch b/Patches/Linux_CVEs/CVE-2016-6751/0.patch new file mode 100644 index 00000000..0f1fdc01 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6751/0.patch @@ -0,0 +1,35 @@ +From 38ddb9427aa96bdfcdc5fe1877f439d2f7bdd87b Mon Sep 17 00:00:00 2001 +From: vivek mehta +Date: Mon, 12 Sep 2016 17:27:06 -0700 +Subject: [PATCH] ASoC: msm: initialize the params array before using it + +The params array is used without initialization, which may cause +security issues. Initialize it as all zero after the definition. + +bug: 30902162 +Change-Id: If462fe3d82f139d72547f82dc7eb564f83cb35bf +Signed-off-by: vivek mehta +--- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +index cec79eaa81e4c..0d957246459ad 100644 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +@@ -1036,6 +1036,7 @@ static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream, + struct snd_dec_ddp *ddp = + &compr->info.codec_param.codec.options.ddp; + uint32_t params_length = 0; ++ memset(params_value, 0, MAX_AC3_PARAM_SIZE); + /* check integer overflow */ + if (ddp->params_length > UINT_MAX/sizeof(int)) { + pr_err("%s: Integer overflow ddp->params_length %d\n", +@@ -1076,6 +1077,7 @@ static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream, + struct snd_dec_ddp *ddp = + &compr->info.codec_param.codec.options.ddp; + uint32_t params_length = 0; ++ memset(params_value, 0, MAX_AC3_PARAM_SIZE); + /* check integer overflow */ + if (ddp->params_length > UINT_MAX/sizeof(int)) { + pr_err("%s: Integer overflow ddp->params_length %d\n", diff --git a/Patches/Linux_CVEs/CVE-2016-6752/0.patch b/Patches/Linux_CVEs/CVE-2016-6752/0.patch new file mode 100644 index 00000000..fdeef302 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6752/0.patch @@ -0,0 +1,109 @@ +From 0de2c7600c8f1f0152a2f421c6593f931186400a Mon Sep 17 00:00:00 2001 +From: Mallikarjuna Reddy Amireddy +Date: Mon, 25 Jul 2016 18:14:39 +0530 +Subject: qseecom: Change format specifier %p to %pK + +Format specifier %p can leak kernel addresses while not valuing the +kptr_restrict system settings. When kptr_restrict is set to (1), kernel +pointers printed using the %pK format specifier will be replaced with 0's. +So that %pK will not leak kernel pointers to unprivileged users. +So change the format specifier from %p to %pK. + +Debugging Note : &pK prints only Zeros as address. if you need actual +address information, pls echo 0 to kptr_restrict. +$ echo 0 > /proc/sys/kernel/kptr_restrict + +Change-Id: I0baf2be2d5a476e2e4267f20b99d0ddf5492469e +Signed-off-by: Mallikarjuna Reddy Amireddy +--- + drivers/misc/qseecom.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 52034c7..4fab447 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -1133,7 +1133,7 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data, + + if ((req.ifd_data_fd <= 0) || (req.virt_sb_base == NULL) || + (req.sb_len == 0)) { +- pr_err("Inavlid input(s)ion_fd(%d), sb_len(%d), vaddr(0x%p)\n", ++ pr_err("Inavlid input(s)ion_fd(%d), sb_len(%d), vaddr(0x%pK)\n", + req.ifd_data_fd, req.sb_len, req.virt_sb_base); + return -EFAULT; + } +@@ -1653,7 +1653,7 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, + 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", ++ pr_err("Error with pointer: req_ptr = %pK, send_svc_ptr = %pK\n", + req_ptr, send_svc_ireq_ptr); + return -EINVAL; + } +@@ -1700,7 +1700,7 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, + uint32_t reqd_len_sb_in = 0; + + if ((req_ptr == NULL) || (send_svc_ireq_ptr == NULL)) { +- pr_err("Error with pointer: req_ptr = %p, send_svc_ptr = %p\n", ++ pr_err("Error with pointer: req_ptr = %pK, send_svc_ptr = %pK\n", + req_ptr, send_svc_ireq_ptr); + return -EINVAL; + } +@@ -3025,7 +3025,7 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, + if (ret) + return ret; + +- pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%p\n", ++ pr_debug("sending cmd_req->rsp size: %u, ptr: 0x%pK\n", + req.resp_len, req.resp_buf); + return ret; + } +@@ -4844,7 +4844,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + ret = -EINVAL; + break; + } +- pr_debug("SET_MEM_PARAM: qseecom addr = 0x%p\n", data); ++ pr_debug("SET_MEM_PARAM: qseecom addr = 0x%pK\n", data); + ret = qseecom_set_client_mem_param(data, argp); + if (ret) + pr_err("failed Qqseecom_set_mem_param request: %d\n", +@@ -4860,7 +4860,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + break; + } + data->type = QSEECOM_CLIENT_APP; +- pr_debug("LOAD_APP_REQ: qseecom_addr = 0x%p\n", data); ++ pr_debug("LOAD_APP_REQ: qseecom_addr = 0x%pK\n", data); + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); + if (qseecom.qsee_version > QSEEE_VERSION_00) { +@@ -4886,7 +4886,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + ret = -EINVAL; + break; + } +- pr_debug("UNLOAD_APP: qseecom_addr = 0x%p\n", data); ++ pr_debug("UNLOAD_APP: qseecom_addr = 0x%pK\n", data); + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); + ret = qseecom_unload_app(data, false); +@@ -5017,7 +5017,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + data->type = QSEECOM_CLIENT_APP; + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); +- pr_debug("APP_LOAD_QUERY: qseecom_addr = 0x%p\n", data); ++ pr_debug("APP_LOAD_QUERY: qseecom_addr = 0x%pK\n", data); + ret = qseecom_query_app_loaded(data, argp); + atomic_dec(&data->ioctl_count); + mutex_unlock(&app_access_lock); +@@ -5288,7 +5288,7 @@ static int qseecom_release(struct inode *inode, struct file *file) + int ret = 0; + + if (data->released == false) { +- pr_debug("data: released=false, type=%d, mode=%d, data=0x%p\n", ++ pr_debug("data: released=false, type=%d, mode=%d, data=0x%pK\n", + data->type, data->mode, data); + switch (data->type) { + case QSEECOM_LISTENER_SERVICE: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6753/0.patch b/Patches/Linux_CVEs/CVE-2016-6753/0.patch new file mode 100644 index 00000000..94530915 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6753/0.patch @@ -0,0 +1,32 @@ +From 5ee75a32931dc70a7af2be42650ac5f14db99674 Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Mon, 12 Sep 2016 15:47:42 -0700 +Subject: cgroup: prefer %pK to %p + +Prevents leaking kernel pointers when using kptr_restrict. + +Bug: 30149174 +Change-Id: I0fa3cd8d4a0d9ea76d085bba6020f1eda073c09b +Git-repo: https://android.googlesource.com/kernel/msm.git +Git-commit: 505e48f32f1321ed7cf80d49dd5f31b16da445a8 +Signed-off-by: Srinivasa Rao Kuppala +--- + kernel/cgroup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/cgroup.c b/kernel/cgroup.c +index 05b36e7..1e2c358 100644 +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -5449,7 +5449,7 @@ static int cgroup_css_links_read(struct cgroup *cont, + struct css_set *cg = link->cg; + struct task_struct *task; + int count = 0; +- seq_printf(seq, "css_set %p\n", cg); ++ seq_printf(seq, "css_set %pK\n", cg); + list_for_each_entry(task, &cg->tasks, cg_list) { + if (count++ > MAX_TASKS_SHOWN_PER_CSS) { + seq_puts(seq, " ...\n"); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6755/0.patch b/Patches/Linux_CVEs/CVE-2016-6755/0.patch new file mode 100644 index 00000000..63320d9e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6755/0.patch @@ -0,0 +1,58 @@ +From b5df02edbcdf53dbbab77903d28162772edcf6e0 Mon Sep 17 00:00:00 2001 +From: Suman Mukherjee +Date: Thu, 22 Sep 2016 09:06:48 +0530 +Subject: msm: sensor: validate the i2c table index before use + +Verifying the i2c table index value before accessing +the i2c table to avoid memory corruption issues. +CRs-Fixed: 1065916 + +Change-Id: I0e31c22f90006f27a77cd420288334b8355cee95 +Signed-off-by: Sureshnaidu Laveti +Signed-off-by: Suman Mukherjee +--- + .../platform/msm/camera_v2/sensor/actuator/msm_actuator.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 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 1f4eaa1..bebe691 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 +@@ -91,11 +91,6 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl, + struct msm_camera_i2c_reg_array *i2c_tbl = a_ctrl->i2c_reg_tbl; + CDBG("Enter\n"); + for (i = 0; i < size; i++) { +- /* check that the index into i2c_tbl cannot grow larger that +- the allocated size of i2c_tbl */ +- if ((a_ctrl->total_steps + 1) < (a_ctrl->i2c_tbl_index)) { +- break; +- } + if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) { + value = (next_lens_position << + write_arr[i].data_shift) | +@@ -109,6 +104,11 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl, + i2c_byte2 = value & 0xFF; + CDBG("byte1:0x%x, byte2:0x%x\n", + i2c_byte1, i2c_byte2); ++ if (a_ctrl->i2c_tbl_index > ++ a_ctrl->total_steps) { ++ pr_err("failed:i2c table index out of bound\n"); ++ break; ++ } + i2c_tbl[a_ctrl->i2c_tbl_index]. + reg_addr = i2c_byte1; + i2c_tbl[a_ctrl->i2c_tbl_index]. +@@ -129,6 +129,10 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl, + i2c_byte2 = (hw_dword & write_arr[i].hw_mask) >> + write_arr[i].hw_shift; + } ++ if (a_ctrl->i2c_tbl_index > a_ctrl->total_steps) { ++ pr_err("failed: i2c table index out of bound\n"); ++ break; ++ } + CDBG("i2c_byte1:0x%x, i2c_byte2:0x%x\n", i2c_byte1, i2c_byte2); + i2c_tbl[a_ctrl->i2c_tbl_index].reg_addr = i2c_byte1; + i2c_tbl[a_ctrl->i2c_tbl_index].reg_data = i2c_byte2; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6756/0.patch b/Patches/Linux_CVEs/CVE-2016-6756/0.patch new file mode 100644 index 00000000..c1d409fc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6756/0.patch @@ -0,0 +1,53 @@ +From f91d28dcba304c9f3af35b5bebaa26233c8c13a5 Mon Sep 17 00:00:00 2001 +From: Suman Mukherjee +Date: Thu, 29 Sep 2016 09:19:05 +0530 +Subject: msm: camera: cpp: Add validation for v4l2 ioctl arguments + +In CPP v4l2 ioctl command is made, if _IOC_DIR(cmd) is +_IOC_NONE, then the user-supplied argument arg is not checked +and an information disclosure is possible +CRs-Fixed: 1042068 + +Change-Id: Iddb291b10cdcb5c42ab8497e06c2ce47885cd5ab +Signed-off-by: Suman Mukherjee +Signed-off-by: Sunid Wilson +--- + drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 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 ac0ba8e..964703c 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 +@@ -2495,14 +2495,14 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg, + break; + default: + if (ioctl_ptr == NULL) { +- pr_err("Wrong ioctl_ptr %pK\n", ioctl_ptr); ++ pr_err("Wrong ioctl_ptr for cmd %u\n", cmd); + return -EINVAL; + } + + *ioctl_ptr = arg; + if ((*ioctl_ptr == NULL) || +- ((*ioctl_ptr)->ioctl_ptr == NULL)) { +- pr_err("Wrong arg %pK\n", arg); ++ (*ioctl_ptr)->ioctl_ptr == NULL) { ++ pr_err("Error invalid ioctl argument cmd %u\n", cmd); + return -EINVAL; + } + break; +@@ -2542,6 +2542,10 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, + pr_err("cpp_dev is null\n"); + return -EINVAL; + } ++ if (_IOC_DIR(cmd) == _IOC_NONE) { ++ pr_err("Invalid ioctl/subdev cmd %u", cmd); ++ return -EINVAL; ++ } + rc = msm_cpp_validate_input(cmd, arg, &ioctl_ptr); + if (rc != 0) { + pr_err("input validation failed\n"); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6757/0.patch b/Patches/Linux_CVEs/CVE-2016-6757/0.patch new file mode 100644 index 00000000..c6534b4b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6757/0.patch @@ -0,0 +1,683 @@ +From cd99d3bbdb16899a425716e672485e0cdc283245 Mon Sep 17 00:00:00 2001 +From: Abhijit Kulkarni +Date: Wed, 15 Jun 2016 10:30:50 -0700 +Subject: msm: mdss: hide kernel addresses from unprevileged users + +for printing kernel pointers which should be hidden from unprivileged +users, use %pK which evaluates whether kptr_restrict is set. + +CRs-Fixed: 987021 +Change-Id: Ie49eee9478f4657cfb2a994ba60da1ec4c356339 +Signed-off-by: Abhijit Kulkarni +Signed-off-by: Nirmal Abraham +--- + drivers/video/msm/mdss/mdp3.c | 16 ++++++++-------- + drivers/video/msm/mdss/mdp3_ppp_hwio.c | 8 +++++--- + drivers/video/msm/mdss/mdss_debug.c | 8 ++++---- + drivers/video/msm/mdss/mdss_dsi.c | 14 +++++++------- + drivers/video/msm/mdss/mdss_dsi_host.c | 2 +- + drivers/video/msm/mdss/mdss_dsi_panel.c | 12 ++++++------ + drivers/video/msm/mdss/mdss_fb.c | 6 +++--- + drivers/video/msm/mdss/mdss_hdmi_tx.c | 6 +++--- + drivers/video/msm/mdss/mdss_hdmi_util.c | 4 ++-- + drivers/video/msm/mdss/mdss_mdp.c | 4 ++-- + drivers/video/msm/mdss/mdss_mdp_debug.c | 6 +++--- + drivers/video/msm/mdss/mdss_mdp_intf_cmd.c | 6 +++--- + drivers/video/msm/mdss/mdss_mdp_intf_video.c | 6 +++--- + drivers/video/msm/mdss/mdss_mdp_pipe.c | 2 +- + drivers/video/msm/mdss/mdss_mdp_pp.c | 14 +++++++------- + drivers/video/msm/mdss/mdss_mdp_util.c | 8 ++++---- + drivers/video/msm/mdss/mdss_mdp_wb.c | 10 +++++----- + drivers/video/msm/mdss/mdss_util.c | 5 ++--- + 18 files changed, 69 insertions(+), 68 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c +index 2a9c915..521eb7e 100644 +--- a/drivers/video/msm/mdss/mdp3.c ++++ b/drivers/video/msm/mdss/mdp3.c +@@ -1096,7 +1096,7 @@ static int mdp3_res_init(void) + + mdp3_res->ion_client = msm_ion_client_create(mdp3_res->pdev->name); + if (IS_ERR_OR_NULL(mdp3_res->ion_client)) { +- pr_err("msm_ion_client_create() return error (%p)\n", ++ pr_err("msm_ion_client_create() return error (%pK)\n", + mdp3_res->ion_client); + mdp3_res->ion_client = NULL; + return -EINVAL; +@@ -1528,7 +1528,7 @@ void mdp3_unmap_iommu(struct ion_client *client, struct ion_handle *handle) + mutex_lock(&mdp3_res->iommu_lock); + meta = mdp3_iommu_meta_lookup(table); + if (!meta) { +- WARN(1, "%s: buffer was never mapped for %p\n", __func__, ++ WARN(1, "%s: buffer was never mapped for %pK\n", __func__, + handle); + mutex_unlock(&mdp3_res->iommu_lock); + goto out; +@@ -1556,7 +1556,7 @@ static void mdp3_iommu_meta_add(struct mdp3_iommu_meta *meta) + } else if (meta->table > entry->table) { + p = &(*p)->rb_right; + } else { +- pr_err("%s: handle %p already exists\n", __func__, ++ pr_err("%s: handle %pK already exists\n", __func__, + entry->handle); + BUG(); + } +@@ -1618,7 +1618,7 @@ static int mdp3_iommu_map_iommu(struct mdp3_iommu_meta *meta, + ret = iommu_map_range(domain, meta->iova_addr + padding, + table->sgl, size, prot); + if (ret) { +- pr_err("%s: could not map %pa in domain %p\n", ++ pr_err("%s: could not map %pa in domain %pK\n", + __func__, &meta->iova_addr, domain); + unmap_size = padding; + goto out2; +@@ -1741,12 +1741,12 @@ int mdp3_self_map_iommu(struct ion_client *client, struct ion_handle *handle, + } + } else { + if (iommu_meta->flags != iommu_flags) { +- pr_err("%s: handle %p is already mapped with diff flag\n", ++ pr_err("%s: handle %pK is already mapped with diff flag\n", + __func__, handle); + ret = -EINVAL; + goto out_unlock; + } else if (iommu_meta->mapped_size != iova_length) { +- pr_err("%s: handle %p is already mapped with diff len\n", ++ pr_err("%s: handle %pK is already mapped with diff len\n", + __func__, handle); + ret = -EINVAL; + goto out_unlock; +@@ -1868,7 +1868,7 @@ done: + data->addr += img->offset; + data->len -= img->offset; + +- pr_debug("mem=%d ihdl=%p buf=0x%pa len=0x%x\n", img->memory_id, ++ pr_debug("mem=%d ihdl=%pK buf=0x%pa len=0x%x\n", img->memory_id, + data->srcp_ihdl, &data->addr, data->len); + } else { + mdp3_put_img(data, client); +@@ -2101,7 +2101,7 @@ static int mdp3_alloc(struct msm_fb_data_type *mfd) + return ret; + } + +- pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n", ++ pr_info("allocating %u bytes at %pK (%lx phys) for fb %d\n", + size, virt, phys, mfd->index); + + mfd->fbi->screen_base = virt; +diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c +index d8c4168..4317726 100644 +--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c ++++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c +@@ -1291,7 +1291,8 @@ int config_ppp_op_mode(struct ppp_blit_op *blit_op) + bg_mdp_ops = 0; + } + pr_debug("BLIT FG Param Fmt %d (x %d,y %d,w %d,h %d), ROI(x %d,y %d, w\ +- %d, h %d) Addr_P0 %p, Stride S0 %d Addr_P1 %p, Stride S1 %d\n", ++ %d, h %d) Addr_P0 %pK, Stride S0 %d Addr_P1 %pK,\ ++ Stride S1 %d\n", + blit_op->src.color_fmt, blit_op->src.prop.x, blit_op->src.prop.y, + blit_op->src.prop.width, blit_op->src.prop.height, + blit_op->src.roi.x, blit_op->src.roi.y, blit_op->src.roi.width, +@@ -1299,14 +1300,15 @@ int config_ppp_op_mode(struct ppp_blit_op *blit_op) + blit_op->src.p1, blit_op->src.stride1); + if (blit_op->bg.p0 != blit_op->dst.p0) + pr_debug("BLIT BG Param Fmt %d (x %d,y %d,w %d,h %d), ROI(x %d,y %d, w\ +- %d, h %d) Addr %p, Stride S0 %d Addr_P1 %p, Stride S1 %d\n", ++ %d, h %d) Addr %pK, Stride S0 %d Addr_P1 %pK,\ ++ Stride S1 %d\n", + blit_op->bg.color_fmt, blit_op->bg.prop.x, blit_op->bg.prop.y, + blit_op->bg.prop.width, blit_op->bg.prop.height, + blit_op->bg.roi.x, blit_op->bg.roi.y, blit_op->bg.roi.width, + blit_op->bg.roi.height, blit_op->bg.p0, blit_op->bg.stride0, + blit_op->bg.p1, blit_op->bg.stride1); + pr_debug("BLIT FB Param Fmt %d (x %d,y %d,w %d,h %d), ROI(x %d,y %d, w\ +- %d, h %d) Addr %p, Stride S0 %d Addr_P1 %p, Stride S1 %d\n", ++ %d, h %d) Addr %pK, Stride S0 %d Addr_P1 %pK, Stride S1 %d\n", + blit_op->dst.color_fmt, blit_op->dst.prop.x, blit_op->dst.prop.y, + blit_op->dst.prop.width, blit_op->dst.prop.height, + blit_op->dst.roi.x, blit_op->dst.roi.y, blit_op->dst.roi.width, +diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c +index 3513540..15d7dea 100644 +--- a/drivers/video/msm/mdss/mdss_debug.c ++++ b/drivers/video/msm/mdss/mdss_debug.c +@@ -178,7 +178,7 @@ static ssize_t panel_debug_base_reg_write(struct file *file, + for (i = 0; i < len; i++) { + p = buf + i * 3; + p[2] = 0; +- pr_debug("p[%d] = %p:%s\n", i, p, p); ++ pr_debug("p[%d] = %pK:%s\n", i, p, p); + cnt = sscanf(p, "%x", &tmp); + reg[i] = tmp; + pr_debug("reg[%d] = %x\n", i, (int)reg[i]); +@@ -1072,7 +1072,7 @@ void mdss_dump_reg(char __iomem *base, int len) + x4 = readl_relaxed(addr+0x4); + x8 = readl_relaxed(addr+0x8); + xc = readl_relaxed(addr+0xc); +- pr_info("%p : %08x %08x %08x %08x\n", addr, x0, x4, x8, xc); ++ pr_info("%pK : %08x %08x %08x %08x\n", addr, x0, x4, x8, xc); + addr += 16; + } + mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF); +@@ -1192,7 +1192,7 @@ static inline struct mdss_mdp_misr_map *mdss_misr_get_map(u32 block_id, + return NULL; + } + +- pr_debug("MISR Module(%d) CTRL(0x%x) SIG(0x%x) intf_base(0x%p)\n", ++ pr_debug("MISR Module(%d) CTRL(0x%x) SIG(0x%x) intf_base(0x%pK)\n", + block_id, map->ctrl_reg, map->value_reg, intf_base); + return map; + } +@@ -1235,7 +1235,7 @@ int mdss_misr_set(struct mdss_data_type *mdata, + bool use_mdp_up_misr = false; + + if (!mdata || !req || !ctl) { +- pr_err("Invalid input params: mdata = %p req = %p ctl = %p", ++ pr_err("Invalid input params: mdata = %pK req = %pK ctl = %pK", + mdata, req, ctl); + return -EINVAL; + } +diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c +index 9d12dfb..62c6f12 100644 +--- a/drivers/video/msm/mdss/mdss_dsi.c ++++ b/drivers/video/msm/mdss/mdss_dsi.c +@@ -471,7 +471,7 @@ static int mdss_dsi_off(struct mdss_panel_data *pdata, int power_state) + + panel_info = &ctrl_pdata->panel_data.panel_info; + +- pr_debug("%s+: ctrl=%p ndx=%d power_state=%d\n", ++ pr_debug("%s+: ctrl=%pK ndx=%d power_state=%d\n", + __func__, ctrl_pdata, ctrl_pdata->ndx, power_state); + + if (power_state == panel_info->panel_power_state) { +@@ -559,7 +559,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) + panel_data); + + cur_power_state = pdata->panel_info.panel_power_state; +- pr_debug("%s+: ctrl=%p ndx=%d cur_power_state=%d\n", __func__, ++ pr_debug("%s+: ctrl=%pK ndx=%d cur_power_state=%d\n", __func__, + ctrl_pdata, ctrl_pdata->ndx, cur_power_state); + + pinfo = &pdata->panel_info; +@@ -703,7 +703,7 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) + panel_data); + mipi = &pdata->panel_info.mipi; + +- pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d\n", __func__, ++ pr_debug("%s+: ctrl=%pK ndx=%d cur_blank_state=%d\n", __func__, + ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state); + + mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); +@@ -756,7 +756,7 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state) + panel_data); + mipi = &pdata->panel_info.mipi; + +- pr_debug("%s+: ctrl=%p ndx=%d power_state=%d\n", ++ pr_debug("%s+: ctrl=%pK ndx=%d power_state=%d\n", + __func__, ctrl_pdata, ctrl_pdata->ndx, power_state); + + mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); +@@ -826,7 +826,7 @@ static int mdss_dsi_post_panel_on(struct mdss_panel_data *pdata) + ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + +- pr_debug("%s+: ctrl=%p ndx=%d\n", __func__, ++ pr_debug("%s+: ctrl=%pK ndx=%d\n", __func__, + ctrl_pdata, ctrl_pdata->ndx); + + mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1); +@@ -858,7 +858,7 @@ int mdss_dsi_cont_splash_on(struct mdss_panel_data *pdata) + ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + +- pr_debug("%s+: ctrl=%p ndx=%d\n", __func__, ++ pr_debug("%s+: ctrl=%pK ndx=%d\n", __func__, + ctrl_pdata, ctrl_pdata->ndx); + + WARN((ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT), +@@ -1700,7 +1700,7 @@ int mdss_dsi_retrieve_ctrl_resources(struct platform_device *pdev, int mode, + return rc; + } + +- pr_info("%s: ctrl_base=%p ctrl_size=%x phy_base=%p phy_size=%x\n", ++ pr_info("%s: ctrl_base=%pK ctrl_size=%x phy_base=%pK phy_size=%x\n", + __func__, ctrl->ctrl_base, ctrl->reg_size, ctrl->phy_io.base, + ctrl->phy_io.len); + +diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c +index ace2895..762cb55 100644 +--- a/drivers/video/msm/mdss/mdss_dsi_host.c ++++ b/drivers/video/msm/mdss/mdss_dsi_host.c +@@ -97,7 +97,7 @@ void mdss_dsi_ctrl_init(struct device *ctrl_dev, + if (ctrl->mdss_util->register_irq(ctrl->dsi_hw)) + pr_err("%s: mdss_register_irq failed.\n", __func__); + +- pr_debug("%s: ndx=%d base=%p\n", __func__, ctrl->ndx, ctrl->ctrl_base); ++ pr_debug("%s: ndx=%d base=%pK\n", __func__, ctrl->ndx, ctrl->ctrl_base); + + init_completion(&ctrl->dma_comp); + init_completion(&ctrl->mdp_comp); +diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c +index 8c57c9b..b168769 100644 +--- a/drivers/video/msm/mdss/mdss_dsi_panel.c ++++ b/drivers/video/msm/mdss/mdss_dsi_panel.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -611,7 +611,7 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) + ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + +- pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx); ++ pr_debug("%s: ctrl=%pK ndx=%d\n", __func__, ctrl, ctrl->ndx); + + if (pinfo->dcs_cmd_by_left) { + if (ctrl->ndx != DSI_CTRL_LEFT) +@@ -641,7 +641,7 @@ static int mdss_dsi_post_panel_on(struct mdss_panel_data *pdata) + ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + +- pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx); ++ pr_debug("%s: ctrl=%pK ndx=%d\n", __func__, ctrl, ctrl->ndx); + + pinfo = &pdata->panel_info; + if (pinfo->dcs_cmd_by_left) { +@@ -651,7 +651,7 @@ static int mdss_dsi_post_panel_on(struct mdss_panel_data *pdata) + + on_cmds = &ctrl->post_panel_on_cmds; + +- pr_debug("%s: ctrl=%p cmd_cnt=%d\n", __func__, ctrl, on_cmds->cmd_cnt); ++ pr_debug("%s: ctrl=%pK cmd_cnt=%d\n", __func__, ctrl, on_cmds->cmd_cnt); + + if (on_cmds->cmd_cnt) { + msleep(50); /* wait for 3 vsync passed */ +@@ -677,7 +677,7 @@ static int mdss_dsi_panel_off(struct mdss_panel_data *pdata) + ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + +- pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx); ++ pr_debug("%s: ctrl=%pK ndx=%d\n", __func__, ctrl, ctrl->ndx); + + if (pinfo->dcs_cmd_by_left) { + if (ctrl->ndx != DSI_CTRL_LEFT) +@@ -708,7 +708,7 @@ static int mdss_dsi_panel_low_power_config(struct mdss_panel_data *pdata, + ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + +- pr_debug("%s: ctrl=%p ndx=%d enable=%d\n", __func__, ctrl, ctrl->ndx, ++ pr_debug("%s: ctrl=%pK ndx=%d enable=%d\n", __func__, ctrl, ctrl->ndx, + enable); + + /* Any panel specific low power commands/config */ +diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c +index c06abd3..6f09747 100644 +--- a/drivers/video/msm/mdss/mdss_fb.c ++++ b/drivers/video/msm/mdss/mdss_fb.c +@@ -1642,7 +1642,7 @@ int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd, size_t fb_size) + goto fb_mmap_failed; + } + +- pr_debug("alloc 0x%zuB vaddr = %p (%pa iova) for fb%d\n", fb_size, ++ pr_debug("alloc 0x%zuB vaddr = %pK (%pa iova) for fb%d\n", fb_size, + vaddr, &mfd->iova, mfd->index); + + mfd->fbi->screen_base = (char *) vaddr; +@@ -1735,7 +1735,7 @@ static int mdss_fb_fbmem_ion_mmap(struct fb_info *info, + vma->vm_page_prot = + pgprot_writecombine(vma->vm_page_prot); + +- pr_debug("vma=%p, addr=%x len=%ld\n", ++ pr_debug("vma=%pK, addr=%x len=%ld\n", + vma, (unsigned int)addr, len); + pr_debug("vm_start=%x vm_end=%x vm_page_prot=%ld\n", + (unsigned int)vma->vm_start, +@@ -1905,7 +1905,7 @@ static int mdss_fb_alloc_fbmem_iommu(struct msm_fb_data_type *mfd, int dom) + if (rc) + pr_warn("Cannot map fb_mem %pa to IOMMU. rc=%d\n", &phys, rc); + +- pr_debug("alloc 0x%zxB @ (%pa phys) (0x%p virt) (%pa iova) for fb%d\n", ++ pr_debug("alloc 0x%zxB @ (%pa phys) (0x%pK virt) (%pa iova) for fb%d\n", + size, &phys, virt, &mfd->iova, mfd->index); + + mfd->fbi->screen_base = virt; +diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c +index 90f9267..140a460 100644 +--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c ++++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2014,2016 The 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 +@@ -1035,7 +1035,7 @@ static int hdmi_tx_sysfs_create(struct hdmi_tx_ctrl *hdmi_ctrl, + return rc; + } + hdmi_ctrl->kobj = &fbi->dev->kobj; +- DEV_DBG("%s: sysfs group %p\n", __func__, hdmi_ctrl->kobj); ++ DEV_DBG("%s: sysfs group %pK\n", __func__, hdmi_ctrl->kobj); + + return 0; + } /* hdmi_tx_sysfs_create */ +@@ -3556,7 +3556,7 @@ static int hdmi_tx_init_resource(struct hdmi_tx_ctrl *hdmi_ctrl) + DEV_DBG("%s: '%s' remap failed or not available\n", + __func__, hdmi_tx_io_name(i)); + } +- DEV_INFO("%s: '%s': start = 0x%p, len=0x%x\n", __func__, ++ DEV_INFO("%s: '%s': start = 0x%pK, len=0x%x\n", __func__, + hdmi_tx_io_name(i), pdata->io[i].base, + pdata->io[i].len); + } +diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c +index b40ff28..b50aee3 100644 +--- a/drivers/video/msm/mdss/mdss_hdmi_util.c ++++ b/drivers/video/msm/mdss/mdss_hdmi_util.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2014,2016 The 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 +@@ -178,7 +178,7 @@ static void hdmi_ddc_print_data(struct hdmi_tx_ddc_data *ddc_data, + return; + } + +- DEV_DBG("%s: buf=%p, d_len=0x%x, d_addr=0x%x, no_align=%d\n", ++ DEV_DBG("%s: buf=%pK, d_len=0x%x, d_addr=0x%x, no_align=%d\n", + caller, ddc_data->data_buf, ddc_data->data_len, + ddc_data->dev_addr, ddc_data->no_align); + DEV_DBG("%s: offset=0x%x, req_len=0x%x, retry=%d, what=%s\n", +diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c +index 14514f3..3a53359 100644 +--- a/drivers/video/msm/mdss/mdss_mdp.c ++++ b/drivers/video/msm/mdss/mdss_mdp.c +@@ -1207,7 +1207,7 @@ static u32 mdss_mdp_res_init(struct mdss_data_type *mdata) + + mdata->iclient = msm_ion_client_create(mdata->pdev->name); + if (IS_ERR_OR_NULL(mdata->iclient)) { +- pr_err("msm_ion_client_create() return error (%p)\n", ++ pr_err("msm_ion_client_create() return error (%pK)\n", + mdata->iclient); + mdata->iclient = NULL; + } +@@ -1526,7 +1526,7 @@ static int mdss_mdp_probe(struct platform_device *pdev) + if (rc) + pr_debug("unable to map MDSS VBIF non-realtime base\n"); + else +- pr_debug("MDSS VBIF NRT HW Base addr=%p len=0x%x\n", ++ pr_debug("MDSS VBIF NRT HW Base addr=%pK len=0x%x\n", + mdata->vbif_nrt_io.base, mdata->vbif_nrt_io.len); + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +diff --git a/drivers/video/msm/mdss/mdss_mdp_debug.c b/drivers/video/msm/mdss/mdss_mdp_debug.c +index 39230d1..9b1ab8d 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_debug.c ++++ b/drivers/video/msm/mdss/mdss_mdp_debug.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014,2016 The 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 +@@ -57,13 +57,13 @@ static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe) + seq_puts(s, "Data:\n"); + if (pipe->front_buf.num_planes) { + buf = pipe->front_buf.p; +- seq_printf(s, "\tfront_buf ihdl=0x%p addr=%pa size=%lu\n", ++ seq_printf(s, "\tfront_buf ihdl=0x%pK addr=%pa size=%lu\n", + buf->srcp_ihdl, &buf->addr, buf->len); + } + + if (pipe->back_buf.num_planes) { + buf = pipe->back_buf.p; +- seq_printf(s, "\tback_buf ihdl=0x%p addr=%pa size=%lu\n", ++ seq_printf(s, "\tback_buf ihdl=0x%pK addr=%pa size=%lu\n", + buf->srcp_ihdl, &buf->addr, buf->len); + } + } +diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c +index 6f6fc91..b07b3c5 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c ++++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2016, The 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 +@@ -581,7 +581,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) + ctx->rdptr_enabled, ctl->roi_bkup.w, + ctl->roi_bkup.h); + +- pr_debug("%s: intf_num=%d ctx=%p koff_cnt=%d\n", __func__, ++ pr_debug("%s: intf_num=%d ctx=%pK koff_cnt=%d\n", __func__, + ctl->intf_num, ctx, atomic_read(&ctx->koff_cnt)); + + rc = wait_event_timeout(ctx->pp_waitq, +@@ -1164,7 +1164,7 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl, + + ctx->intf_stopped = 0; + +- pr_debug("%s: ctx=%p num=%d mixer=%d\n", __func__, ++ pr_debug("%s: ctx=%pK num=%d mixer=%d\n", __func__, + ctx, ctx->pp_num, mixer->num); + MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->clk_enabled, + ctx->rdptr_enabled); +diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c +index 2bc8a1d..9ce6885 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c ++++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c +@@ -116,7 +116,7 @@ int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata, + + for (i = 0; i < count; i++) { + head[i].base = mdata->mdss_io.base + offsets[i]; +- pr_debug("adding Video Intf #%d offset=0x%x virt=%p\n", i, ++ pr_debug("adding Video Intf #%d offset=0x%x virt=%pK\n", i, + offsets[i], head[i].base); + head[i].ref_cnt = 0; + head[i].intf_num = i + MDSS_MDP_INTF0; +@@ -442,7 +442,7 @@ static int mdss_mdp_video_intfs_stop(struct mdss_mdp_ctl *ctl, + pr_err("Intf %d not in use\n", (inum + MDSS_MDP_INTF0)); + return -ENODEV; + } +- pr_debug("stop ctl=%d video Intf #%d base=%p", ctl->num, ++ pr_debug("stop ctl=%d video Intf #%d base=%pK", ctl->num, + ctx->intf_num, ctx->base); + } else { + pr_err("Invalid intf number: %d\n", (inum + MDSS_MDP_INTF0)); +@@ -1158,7 +1158,7 @@ static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl, + (inum + MDSS_MDP_INTF0)); + return -EBUSY; + } +- pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base); ++ pr_debug("video Intf #%d base=%pK", ctx->intf_num, ctx->base); + ctx->ref_cnt++; + } else { + pr_err("Invalid intf number: %d\n", (inum + MDSS_MDP_INTF0)); +diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c +index b747670..d8d01af 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c ++++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c +@@ -1739,7 +1739,7 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe, + } + + if (src_data == NULL) { +- pr_debug("src_data=%p pipe num=%dx\n", ++ pr_debug("src_data=%pK pipe num=%dx\n", + src_data, pipe->num); + goto update_nobuf; + } +diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c +index 3cfa926..5065bc8 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_pp.c ++++ b/drivers/video/msm/mdss/mdss_mdp_pp.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012-2016, The 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 +@@ -2224,7 +2224,7 @@ static int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, + pr_debug("AD not supported on device.\n"); + return ret; + } else if (ret || !ad) { +- pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n", ++ pr_err("Failed to get ad info: ret = %d, ad = 0x%pK.\n", + ret, ad); + return ret; + } +@@ -2240,7 +2240,7 @@ static int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out, + + if (!ad->bl_mfd || !ad->bl_mfd->panel_info || + !ad->bl_att_lut) { +- pr_err("Invalid ad info: bl_mfd = 0x%p, ad->bl_mfd->panel_info = 0x%p, bl_att_lut = 0x%p\n", ++ pr_err("Invalid ad info: bl_mfd = 0x%pK, ad->bl_mfd->panel_info = 0x%pK, bl_att_lut = 0x%pK\n", + ad->bl_mfd, + (!ad->bl_mfd) ? NULL : ad->bl_mfd->panel_info, + ad->bl_att_lut); +@@ -3507,7 +3507,7 @@ static int pp_hist_enable(struct pp_hist_col_info *hist_info, + spin_lock_irqsave(&hist_info->hist_lock, flag); + if (hist_info->col_en) { + spin_unlock_irqrestore(&hist_info->hist_lock, flag); +- pr_info("%s Hist collection has already been enabled %p\n", ++ pr_info("%s Hist collection has already been enabled %pK\n", + __func__, hist_info->base); + goto exit; + } +@@ -3644,7 +3644,7 @@ static int pp_hist_disable(struct pp_hist_col_info *hist_info) + spin_lock_irqsave(&hist_info->hist_lock, flag); + if (hist_info->col_en == false) { + spin_unlock_irqrestore(&hist_info->hist_lock, flag); +- pr_debug("Histogram already disabled (%p)\n", hist_info->base); ++ pr_debug("Histogram already disabled (%pK)\n", hist_info->base); + ret = -EINVAL; + goto exit; + } +@@ -3758,7 +3758,7 @@ int mdss_mdp_hist_intr_req(struct mdss_intr *intr, u32 bits, bool en) + unsigned long flag; + int ret = 0; + if (!intr) { +- pr_err("NULL addr passed, %p\n", intr); ++ pr_err("NULL addr passed, %pK\n", intr); + return -EINVAL; + } + +@@ -4512,7 +4512,7 @@ static int pp_ad_invalidate_input(struct msm_fb_data_type *mfd) + + ret = mdss_mdp_get_ad(mfd, &ad); + if (ret || !ad) { +- pr_err("Fail to get ad: ret = %d, ad = 0x%p\n", ret, ad); ++ pr_err("Fail to get ad: ret = %d, ad = 0x%pK\n", ret, ad); + return -EINVAL; + } + pr_debug("AD backlight level changed (%d), trigger update to AD\n", +diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c +index c62acf3..926dfde 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_util.c ++++ b/drivers/video/msm/mdss/mdss_mdp_util.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -507,7 +507,7 @@ static int mdss_mdp_put_img(struct mdss_mdp_img_data *data) + pr_debug("pmem buf=0x%pa\n", &data->addr); + data->srcp_file = NULL; + } else if (!IS_ERR_OR_NULL(data->srcp_ihdl)) { +- pr_debug("ion hdl=%p buf=0x%pa\n", data->srcp_ihdl, ++ pr_debug("ion hdl=%pK buf=0x%pa\n", data->srcp_ihdl, + &data->addr); + if (!iclient) { + pr_err("invalid ion client\n"); +@@ -599,7 +599,7 @@ static int mdss_mdp_get_img(struct msmfb_data *img, + data->addr += data->offset; + data->len -= data->offset; + +- pr_debug("mem=%d ihdl=%p buf=0x%pa len=0x%lu\n", img->memory_id, ++ pr_debug("mem=%d ihdl=%pK buf=0x%pa len=0x%lu\n", img->memory_id, + data->srcp_ihdl, &data->addr, data->len); + } else { + mdss_mdp_put_img(data); +@@ -653,7 +653,7 @@ static int mdss_mdp_map_buffer(struct mdss_mdp_img_data *data) + data->addr += data->offset; + data->len -= data->offset; + +- pr_debug("ihdl=%p buf=0x%pa len=0x%lu\n", ++ pr_debug("ihdl=%pK buf=0x%pa len=0x%lu\n", + data->srcp_ihdl, &data->addr, data->len); + } else { + mdss_mdp_put_img(data); +diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c +index def90eb..da6587e 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_wb.c ++++ b/drivers/video/msm/mdss/mdss_mdp_wb.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -95,7 +95,7 @@ struct mdss_mdp_data *mdss_mdp_wb_debug_buffer(struct msm_fb_data_type *mfd) + ihdl = ion_alloc(iclient, img_size, SZ_4K, + ION_HEAP(ION_SF_HEAP_ID), 0); + if (IS_ERR_OR_NULL(ihdl)) { +- pr_err("unable to alloc fbmem from ion (%p)\n", ihdl); ++ pr_err("unable to alloc fbmem from ion (%pK)\n", ihdl); + return NULL; + } + +@@ -122,7 +122,7 @@ struct mdss_mdp_data *mdss_mdp_wb_debug_buffer(struct msm_fb_data_type *mfd) + img->len = img_size; + } + +- pr_debug("ihdl=%p virt=%p phys=0x%pa iova=0x%pa size=%u\n", ++ pr_debug("ihdl=%pK virt=%pK phys=0x%pa iova=0x%pa size=%u\n", + ihdl, videomemory, &mdss_wb_mem, &img->addr, img_size); + } + return &mdss_wb_buffer; +@@ -435,7 +435,7 @@ static struct mdss_mdp_wb_data *get_user_node(struct msm_fb_data_type *mfd, + list_for_each_entry(node, &wb->register_queue, registered_entry) + if ((node->buf_data.p[0].srcp_ihdl == ihdl) && + (node->buf_info.offset == data->offset)) { +- pr_debug("found fd=%d hdl=%p off=%x addr=%pa\n", ++ pr_debug("found fd=%d hdl=%pK off=%x addr=%pa\n", + data->memory_id, ihdl, + data->offset, + &node->buf_data.p[0].addr); +@@ -501,7 +501,7 @@ static void mdss_mdp_wb_free_node(struct mdss_mdp_wb_data *node) + if (node->user_alloc) { + buf = &node->buf_data.p[0]; + +- pr_debug("free user mem_id=%d ihdl=%p, offset=%u addr=0x%pa\n", ++ pr_debug("free user mem_id=%d ihdl=%pK, offset=%u addr=0x%pa\n", + node->buf_info.memory_id, + buf->srcp_ihdl, + node->buf_info.offset, +diff --git a/drivers/video/msm/mdss/mdss_util.c b/drivers/video/msm/mdss/mdss_util.c +index 587db41..345b0927 100644 +--- a/drivers/video/msm/mdss/mdss_util.c ++++ b/drivers/video/msm/mdss/mdss_util.c +@@ -1,5 +1,4 @@ +- +-/* Copyright (c) 2007-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2007-2014,2016 The 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 +@@ -33,7 +32,7 @@ int mdss_register_irq(struct mdss_hw *hw) + if (!mdss_irq_handlers[hw->hw_ndx]) + mdss_irq_handlers[hw->hw_ndx] = hw; + else +- pr_err("panel %d's irq at %p is already registered\n", ++ pr_err("panel %d's irq at %pK is already registered\n", + hw->hw_ndx, hw->irq_handler); + spin_unlock_irqrestore(&mdss_lock, irq_flags); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6786/0.patch b/Patches/Linux_CVEs/CVE-2016-6786/0.patch new file mode 100644 index 00000000..280b6064 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6786/0.patch @@ -0,0 +1,505 @@ +From f63a8daa5812afef4f06c962351687e1ff9ccb2b Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra +Date: Fri, 23 Jan 2015 12:24:14 +0100 +Subject: perf: Fix event->ctx locking + +There have been a few reported issues wrt. the lack of locking around +changing event->ctx. This patch tries to address those. + +It avoids the whole rwsem thing; and while it appears to work, please +give it some thought in review. + +What I did fail at is sensible runtime checks on the use of +event->ctx, the RCU use makes it very hard. + +Signed-off-by: Peter Zijlstra (Intel) +Cc: Paul E. McKenney +Cc: Jiri Olsa +Cc: Arnaldo Carvalho de Melo +Cc: Linus Torvalds +Link: http://lkml.kernel.org/r/20150123125834.209535886@infradead.org +Signed-off-by: Ingo Molnar +--- + kernel/events/core.c | 244 +++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 207 insertions(+), 37 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index b358cb3..417a96b 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -907,6 +907,77 @@ static void put_ctx(struct perf_event_context *ctx) + } + + /* ++ * Because of perf_event::ctx migration in sys_perf_event_open::move_group and ++ * perf_pmu_migrate_context() we need some magic. ++ * ++ * Those places that change perf_event::ctx will hold both ++ * perf_event_ctx::mutex of the 'old' and 'new' ctx value. ++ * ++ * Lock ordering is by mutex address. There is one other site where ++ * perf_event_context::mutex nests and that is put_event(). But remember that ++ * that is a parent<->child context relation, and migration does not affect ++ * children, therefore these two orderings should not interact. ++ * ++ * The change in perf_event::ctx does not affect children (as claimed above) ++ * because the sys_perf_event_open() case will install a new event and break ++ * the ctx parent<->child relation, and perf_pmu_migrate_context() is only ++ * concerned with cpuctx and that doesn't have children. ++ * ++ * The places that change perf_event::ctx will issue: ++ * ++ * perf_remove_from_context(); ++ * synchronize_rcu(); ++ * perf_install_in_context(); ++ * ++ * to affect the change. The remove_from_context() + synchronize_rcu() should ++ * quiesce the event, after which we can install it in the new location. This ++ * means that only external vectors (perf_fops, prctl) can perturb the event ++ * while in transit. Therefore all such accessors should also acquire ++ * perf_event_context::mutex to serialize against this. ++ * ++ * However; because event->ctx can change while we're waiting to acquire ++ * ctx->mutex we must be careful and use the below perf_event_ctx_lock() ++ * function. ++ * ++ * Lock order: ++ * task_struct::perf_event_mutex ++ * perf_event_context::mutex ++ * perf_event_context::lock ++ * perf_event::child_mutex; ++ * perf_event::mmap_mutex ++ * mmap_sem ++ */ ++static struct perf_event_context *perf_event_ctx_lock(struct perf_event *event) ++{ ++ struct perf_event_context *ctx; ++ ++again: ++ rcu_read_lock(); ++ ctx = ACCESS_ONCE(event->ctx); ++ if (!atomic_inc_not_zero(&ctx->refcount)) { ++ rcu_read_unlock(); ++ goto again; ++ } ++ rcu_read_unlock(); ++ ++ mutex_lock(&ctx->mutex); ++ if (event->ctx != ctx) { ++ mutex_unlock(&ctx->mutex); ++ put_ctx(ctx); ++ goto again; ++ } ++ ++ return ctx; ++} ++ ++static void perf_event_ctx_unlock(struct perf_event *event, ++ struct perf_event_context *ctx) ++{ ++ mutex_unlock(&ctx->mutex); ++ put_ctx(ctx); ++} ++ ++/* + * This must be done under the ctx->lock, such as to serialize against + * context_equiv(), therefore we cannot call put_ctx() since that might end up + * calling scheduler related locks and ctx->lock nests inside those. +@@ -1666,7 +1737,7 @@ int __perf_event_disable(void *info) + * is the current context on this CPU and preemption is disabled, + * hence we can't get into perf_event_task_sched_out for this context. + */ +-void perf_event_disable(struct perf_event *event) ++static void _perf_event_disable(struct perf_event *event) + { + struct perf_event_context *ctx = event->ctx; + struct task_struct *task = ctx->task; +@@ -1707,6 +1778,19 @@ retry: + } + raw_spin_unlock_irq(&ctx->lock); + } ++ ++/* ++ * Strictly speaking kernel users cannot create groups and therefore this ++ * interface does not need the perf_event_ctx_lock() magic. ++ */ ++void perf_event_disable(struct perf_event *event) ++{ ++ struct perf_event_context *ctx; ++ ++ ctx = perf_event_ctx_lock(event); ++ _perf_event_disable(event); ++ perf_event_ctx_unlock(event, ctx); ++} + EXPORT_SYMBOL_GPL(perf_event_disable); + + static void perf_set_shadow_time(struct perf_event *event, +@@ -2170,7 +2254,7 @@ unlock: + * perf_event_for_each_child or perf_event_for_each as described + * for perf_event_disable. + */ +-void perf_event_enable(struct perf_event *event) ++static void _perf_event_enable(struct perf_event *event) + { + struct perf_event_context *ctx = event->ctx; + struct task_struct *task = ctx->task; +@@ -2226,9 +2310,21 @@ retry: + out: + raw_spin_unlock_irq(&ctx->lock); + } ++ ++/* ++ * See perf_event_disable(); ++ */ ++void perf_event_enable(struct perf_event *event) ++{ ++ struct perf_event_context *ctx; ++ ++ ctx = perf_event_ctx_lock(event); ++ _perf_event_enable(event); ++ perf_event_ctx_unlock(event, ctx); ++} + EXPORT_SYMBOL_GPL(perf_event_enable); + +-int perf_event_refresh(struct perf_event *event, int refresh) ++static int _perf_event_refresh(struct perf_event *event, int refresh) + { + /* + * not supported on inherited events +@@ -2237,10 +2333,25 @@ int perf_event_refresh(struct perf_event *event, int refresh) + return -EINVAL; + + atomic_add(refresh, &event->event_limit); +- perf_event_enable(event); ++ _perf_event_enable(event); + + return 0; + } ++ ++/* ++ * See perf_event_disable() ++ */ ++int perf_event_refresh(struct perf_event *event, int refresh) ++{ ++ struct perf_event_context *ctx; ++ int ret; ++ ++ ctx = perf_event_ctx_lock(event); ++ ret = _perf_event_refresh(event, refresh); ++ perf_event_ctx_unlock(event, ctx); ++ ++ return ret; ++} + EXPORT_SYMBOL_GPL(perf_event_refresh); + + static void ctx_sched_out(struct perf_event_context *ctx, +@@ -3433,7 +3544,16 @@ static void perf_remove_from_owner(struct perf_event *event) + rcu_read_unlock(); + + if (owner) { +- mutex_lock(&owner->perf_event_mutex); ++ /* ++ * If we're here through perf_event_exit_task() we're already ++ * holding ctx->mutex which would be an inversion wrt. the ++ * normal lock order. ++ * ++ * However we can safely take this lock because its the child ++ * ctx->mutex. ++ */ ++ mutex_lock_nested(&owner->perf_event_mutex, SINGLE_DEPTH_NESTING); ++ + /* + * We have to re-check the event->owner field, if it is cleared + * we raced with perf_event_exit_task(), acquiring the mutex +@@ -3559,12 +3679,13 @@ static int perf_event_read_group(struct perf_event *event, + u64 read_format, char __user *buf) + { + struct perf_event *leader = event->group_leader, *sub; +- int n = 0, size = 0, ret = -EFAULT; + struct perf_event_context *ctx = leader->ctx; +- u64 values[5]; ++ int n = 0, size = 0, ret; + u64 count, enabled, running; ++ u64 values[5]; ++ ++ lockdep_assert_held(&ctx->mutex); + +- mutex_lock(&ctx->mutex); + count = perf_event_read_value(leader, &enabled, &running); + + values[n++] = 1 + leader->nr_siblings; +@@ -3579,7 +3700,7 @@ static int perf_event_read_group(struct perf_event *event, + size = n * sizeof(u64); + + if (copy_to_user(buf, values, size)) +- goto unlock; ++ return -EFAULT; + + ret = size; + +@@ -3593,14 +3714,11 @@ static int perf_event_read_group(struct perf_event *event, + size = n * sizeof(u64); + + if (copy_to_user(buf + ret, values, size)) { +- ret = -EFAULT; +- goto unlock; ++ return -EFAULT; + } + + ret += size; + } +-unlock: +- mutex_unlock(&ctx->mutex); + + return ret; + } +@@ -3672,8 +3790,14 @@ static ssize_t + perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) + { + struct perf_event *event = file->private_data; ++ struct perf_event_context *ctx; ++ int ret; + +- return perf_read_hw(event, buf, count); ++ ctx = perf_event_ctx_lock(event); ++ ret = perf_read_hw(event, buf, count); ++ perf_event_ctx_unlock(event, ctx); ++ ++ return ret; + } + + static unsigned int perf_poll(struct file *file, poll_table *wait) +@@ -3699,7 +3823,7 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) + return events; + } + +-static void perf_event_reset(struct perf_event *event) ++static void _perf_event_reset(struct perf_event *event) + { + (void)perf_event_read(event); + local64_set(&event->count, 0); +@@ -3718,6 +3842,7 @@ static void perf_event_for_each_child(struct perf_event *event, + struct perf_event *child; + + WARN_ON_ONCE(event->ctx->parent_ctx); ++ + mutex_lock(&event->child_mutex); + func(event); + list_for_each_entry(child, &event->child_list, child_list) +@@ -3731,14 +3856,13 @@ static void perf_event_for_each(struct perf_event *event, + struct perf_event_context *ctx = event->ctx; + struct perf_event *sibling; + +- WARN_ON_ONCE(ctx->parent_ctx); +- mutex_lock(&ctx->mutex); ++ lockdep_assert_held(&ctx->mutex); ++ + event = event->group_leader; + + perf_event_for_each_child(event, func); + list_for_each_entry(sibling, &event->sibling_list, group_entry) + perf_event_for_each_child(sibling, func); +- mutex_unlock(&ctx->mutex); + } + + static int perf_event_period(struct perf_event *event, u64 __user *arg) +@@ -3808,25 +3932,24 @@ static int perf_event_set_output(struct perf_event *event, + struct perf_event *output_event); + static int perf_event_set_filter(struct perf_event *event, void __user *arg); + +-static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg) + { +- struct perf_event *event = file->private_data; + void (*func)(struct perf_event *); + u32 flags = arg; + + switch (cmd) { + case PERF_EVENT_IOC_ENABLE: +- func = perf_event_enable; ++ func = _perf_event_enable; + break; + case PERF_EVENT_IOC_DISABLE: +- func = perf_event_disable; ++ func = _perf_event_disable; + break; + case PERF_EVENT_IOC_RESET: +- func = perf_event_reset; ++ func = _perf_event_reset; + break; + + case PERF_EVENT_IOC_REFRESH: +- return perf_event_refresh(event, arg); ++ return _perf_event_refresh(event, arg); + + case PERF_EVENT_IOC_PERIOD: + return perf_event_period(event, (u64 __user *)arg); +@@ -3873,6 +3996,19 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + return 0; + } + ++static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ struct perf_event *event = file->private_data; ++ struct perf_event_context *ctx; ++ long ret; ++ ++ ctx = perf_event_ctx_lock(event); ++ ret = _perf_ioctl(event, cmd, arg); ++ perf_event_ctx_unlock(event, ctx); ++ ++ return ret; ++} ++ + #ifdef CONFIG_COMPAT + static long perf_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +@@ -3895,11 +4031,15 @@ static long perf_compat_ioctl(struct file *file, unsigned int cmd, + + int perf_event_task_enable(void) + { ++ struct perf_event_context *ctx; + struct perf_event *event; + + mutex_lock(¤t->perf_event_mutex); +- list_for_each_entry(event, ¤t->perf_event_list, owner_entry) +- perf_event_for_each_child(event, perf_event_enable); ++ list_for_each_entry(event, ¤t->perf_event_list, owner_entry) { ++ ctx = perf_event_ctx_lock(event); ++ perf_event_for_each_child(event, _perf_event_enable); ++ perf_event_ctx_unlock(event, ctx); ++ } + mutex_unlock(¤t->perf_event_mutex); + + return 0; +@@ -3907,11 +4047,15 @@ int perf_event_task_enable(void) + + int perf_event_task_disable(void) + { ++ struct perf_event_context *ctx; + struct perf_event *event; + + mutex_lock(¤t->perf_event_mutex); +- list_for_each_entry(event, ¤t->perf_event_list, owner_entry) +- perf_event_for_each_child(event, perf_event_disable); ++ list_for_each_entry(event, ¤t->perf_event_list, owner_entry) { ++ ctx = perf_event_ctx_lock(event); ++ perf_event_for_each_child(event, _perf_event_disable); ++ perf_event_ctx_unlock(event, ctx); ++ } + mutex_unlock(¤t->perf_event_mutex); + + return 0; +@@ -7269,6 +7413,15 @@ out: + return ret; + } + ++static void mutex_lock_double(struct mutex *a, struct mutex *b) ++{ ++ if (b < a) ++ swap(a, b); ++ ++ mutex_lock(a); ++ mutex_lock_nested(b, SINGLE_DEPTH_NESTING); ++} ++ + /** + * sys_perf_event_open - open a performance event, associate it to a task/cpu + * +@@ -7284,7 +7437,7 @@ SYSCALL_DEFINE5(perf_event_open, + struct perf_event *group_leader = NULL, *output_event = NULL; + struct perf_event *event, *sibling; + struct perf_event_attr attr; +- struct perf_event_context *ctx; ++ struct perf_event_context *ctx, *uninitialized_var(gctx); + struct file *event_file = NULL; + struct fd group = {NULL, 0}; + struct task_struct *task = NULL; +@@ -7482,9 +7635,14 @@ SYSCALL_DEFINE5(perf_event_open, + } + + if (move_group) { +- struct perf_event_context *gctx = group_leader->ctx; ++ gctx = group_leader->ctx; ++ ++ /* ++ * See perf_event_ctx_lock() for comments on the details ++ * of swizzling perf_event::ctx. ++ */ ++ mutex_lock_double(&gctx->mutex, &ctx->mutex); + +- mutex_lock(&gctx->mutex); + perf_remove_from_context(group_leader, false); + + /* +@@ -7499,15 +7657,19 @@ SYSCALL_DEFINE5(perf_event_open, + perf_event__state_init(sibling); + put_ctx(gctx); + } +- mutex_unlock(&gctx->mutex); +- put_ctx(gctx); ++ } else { ++ mutex_lock(&ctx->mutex); + } + + WARN_ON_ONCE(ctx->parent_ctx); +- mutex_lock(&ctx->mutex); + + if (move_group) { ++ /* ++ * Wait for everybody to stop referencing the events through ++ * the old lists, before installing it on new lists. ++ */ + synchronize_rcu(); ++ + perf_install_in_context(ctx, group_leader, group_leader->cpu); + get_ctx(ctx); + list_for_each_entry(sibling, &group_leader->sibling_list, +@@ -7519,6 +7681,11 @@ SYSCALL_DEFINE5(perf_event_open, + + perf_install_in_context(ctx, event, event->cpu); + perf_unpin_context(ctx); ++ ++ if (move_group) { ++ mutex_unlock(&gctx->mutex); ++ put_ctx(gctx); ++ } + mutex_unlock(&ctx->mutex); + + put_online_cpus(); +@@ -7626,7 +7793,11 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) + src_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, src_cpu)->ctx; + dst_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, dst_cpu)->ctx; + +- mutex_lock(&src_ctx->mutex); ++ /* ++ * See perf_event_ctx_lock() for comments on the details ++ * of swizzling perf_event::ctx. ++ */ ++ mutex_lock_double(&src_ctx->mutex, &dst_ctx->mutex); + list_for_each_entry_safe(event, tmp, &src_ctx->event_list, + event_entry) { + perf_remove_from_context(event, false); +@@ -7634,11 +7805,9 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) + put_ctx(src_ctx); + list_add(&event->migrate_entry, &events); + } +- mutex_unlock(&src_ctx->mutex); + + synchronize_rcu(); + +- mutex_lock(&dst_ctx->mutex); + list_for_each_entry_safe(event, tmp, &events, migrate_entry) { + list_del(&event->migrate_entry); + if (event->state >= PERF_EVENT_STATE_OFF) +@@ -7648,6 +7817,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) + get_ctx(dst_ctx); + } + mutex_unlock(&dst_ctx->mutex); ++ mutex_unlock(&src_ctx->mutex); + } + EXPORT_SYMBOL_GPL(perf_pmu_migrate_context); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6787/0.patch b/Patches/Linux_CVEs/CVE-2016-6787/0.patch new file mode 100644 index 00000000..280b6064 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6787/0.patch @@ -0,0 +1,505 @@ +From f63a8daa5812afef4f06c962351687e1ff9ccb2b Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra +Date: Fri, 23 Jan 2015 12:24:14 +0100 +Subject: perf: Fix event->ctx locking + +There have been a few reported issues wrt. the lack of locking around +changing event->ctx. This patch tries to address those. + +It avoids the whole rwsem thing; and while it appears to work, please +give it some thought in review. + +What I did fail at is sensible runtime checks on the use of +event->ctx, the RCU use makes it very hard. + +Signed-off-by: Peter Zijlstra (Intel) +Cc: Paul E. McKenney +Cc: Jiri Olsa +Cc: Arnaldo Carvalho de Melo +Cc: Linus Torvalds +Link: http://lkml.kernel.org/r/20150123125834.209535886@infradead.org +Signed-off-by: Ingo Molnar +--- + kernel/events/core.c | 244 +++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 207 insertions(+), 37 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index b358cb3..417a96b 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -907,6 +907,77 @@ static void put_ctx(struct perf_event_context *ctx) + } + + /* ++ * Because of perf_event::ctx migration in sys_perf_event_open::move_group and ++ * perf_pmu_migrate_context() we need some magic. ++ * ++ * Those places that change perf_event::ctx will hold both ++ * perf_event_ctx::mutex of the 'old' and 'new' ctx value. ++ * ++ * Lock ordering is by mutex address. There is one other site where ++ * perf_event_context::mutex nests and that is put_event(). But remember that ++ * that is a parent<->child context relation, and migration does not affect ++ * children, therefore these two orderings should not interact. ++ * ++ * The change in perf_event::ctx does not affect children (as claimed above) ++ * because the sys_perf_event_open() case will install a new event and break ++ * the ctx parent<->child relation, and perf_pmu_migrate_context() is only ++ * concerned with cpuctx and that doesn't have children. ++ * ++ * The places that change perf_event::ctx will issue: ++ * ++ * perf_remove_from_context(); ++ * synchronize_rcu(); ++ * perf_install_in_context(); ++ * ++ * to affect the change. The remove_from_context() + synchronize_rcu() should ++ * quiesce the event, after which we can install it in the new location. This ++ * means that only external vectors (perf_fops, prctl) can perturb the event ++ * while in transit. Therefore all such accessors should also acquire ++ * perf_event_context::mutex to serialize against this. ++ * ++ * However; because event->ctx can change while we're waiting to acquire ++ * ctx->mutex we must be careful and use the below perf_event_ctx_lock() ++ * function. ++ * ++ * Lock order: ++ * task_struct::perf_event_mutex ++ * perf_event_context::mutex ++ * perf_event_context::lock ++ * perf_event::child_mutex; ++ * perf_event::mmap_mutex ++ * mmap_sem ++ */ ++static struct perf_event_context *perf_event_ctx_lock(struct perf_event *event) ++{ ++ struct perf_event_context *ctx; ++ ++again: ++ rcu_read_lock(); ++ ctx = ACCESS_ONCE(event->ctx); ++ if (!atomic_inc_not_zero(&ctx->refcount)) { ++ rcu_read_unlock(); ++ goto again; ++ } ++ rcu_read_unlock(); ++ ++ mutex_lock(&ctx->mutex); ++ if (event->ctx != ctx) { ++ mutex_unlock(&ctx->mutex); ++ put_ctx(ctx); ++ goto again; ++ } ++ ++ return ctx; ++} ++ ++static void perf_event_ctx_unlock(struct perf_event *event, ++ struct perf_event_context *ctx) ++{ ++ mutex_unlock(&ctx->mutex); ++ put_ctx(ctx); ++} ++ ++/* + * This must be done under the ctx->lock, such as to serialize against + * context_equiv(), therefore we cannot call put_ctx() since that might end up + * calling scheduler related locks and ctx->lock nests inside those. +@@ -1666,7 +1737,7 @@ int __perf_event_disable(void *info) + * is the current context on this CPU and preemption is disabled, + * hence we can't get into perf_event_task_sched_out for this context. + */ +-void perf_event_disable(struct perf_event *event) ++static void _perf_event_disable(struct perf_event *event) + { + struct perf_event_context *ctx = event->ctx; + struct task_struct *task = ctx->task; +@@ -1707,6 +1778,19 @@ retry: + } + raw_spin_unlock_irq(&ctx->lock); + } ++ ++/* ++ * Strictly speaking kernel users cannot create groups and therefore this ++ * interface does not need the perf_event_ctx_lock() magic. ++ */ ++void perf_event_disable(struct perf_event *event) ++{ ++ struct perf_event_context *ctx; ++ ++ ctx = perf_event_ctx_lock(event); ++ _perf_event_disable(event); ++ perf_event_ctx_unlock(event, ctx); ++} + EXPORT_SYMBOL_GPL(perf_event_disable); + + static void perf_set_shadow_time(struct perf_event *event, +@@ -2170,7 +2254,7 @@ unlock: + * perf_event_for_each_child or perf_event_for_each as described + * for perf_event_disable. + */ +-void perf_event_enable(struct perf_event *event) ++static void _perf_event_enable(struct perf_event *event) + { + struct perf_event_context *ctx = event->ctx; + struct task_struct *task = ctx->task; +@@ -2226,9 +2310,21 @@ retry: + out: + raw_spin_unlock_irq(&ctx->lock); + } ++ ++/* ++ * See perf_event_disable(); ++ */ ++void perf_event_enable(struct perf_event *event) ++{ ++ struct perf_event_context *ctx; ++ ++ ctx = perf_event_ctx_lock(event); ++ _perf_event_enable(event); ++ perf_event_ctx_unlock(event, ctx); ++} + EXPORT_SYMBOL_GPL(perf_event_enable); + +-int perf_event_refresh(struct perf_event *event, int refresh) ++static int _perf_event_refresh(struct perf_event *event, int refresh) + { + /* + * not supported on inherited events +@@ -2237,10 +2333,25 @@ int perf_event_refresh(struct perf_event *event, int refresh) + return -EINVAL; + + atomic_add(refresh, &event->event_limit); +- perf_event_enable(event); ++ _perf_event_enable(event); + + return 0; + } ++ ++/* ++ * See perf_event_disable() ++ */ ++int perf_event_refresh(struct perf_event *event, int refresh) ++{ ++ struct perf_event_context *ctx; ++ int ret; ++ ++ ctx = perf_event_ctx_lock(event); ++ ret = _perf_event_refresh(event, refresh); ++ perf_event_ctx_unlock(event, ctx); ++ ++ return ret; ++} + EXPORT_SYMBOL_GPL(perf_event_refresh); + + static void ctx_sched_out(struct perf_event_context *ctx, +@@ -3433,7 +3544,16 @@ static void perf_remove_from_owner(struct perf_event *event) + rcu_read_unlock(); + + if (owner) { +- mutex_lock(&owner->perf_event_mutex); ++ /* ++ * If we're here through perf_event_exit_task() we're already ++ * holding ctx->mutex which would be an inversion wrt. the ++ * normal lock order. ++ * ++ * However we can safely take this lock because its the child ++ * ctx->mutex. ++ */ ++ mutex_lock_nested(&owner->perf_event_mutex, SINGLE_DEPTH_NESTING); ++ + /* + * We have to re-check the event->owner field, if it is cleared + * we raced with perf_event_exit_task(), acquiring the mutex +@@ -3559,12 +3679,13 @@ static int perf_event_read_group(struct perf_event *event, + u64 read_format, char __user *buf) + { + struct perf_event *leader = event->group_leader, *sub; +- int n = 0, size = 0, ret = -EFAULT; + struct perf_event_context *ctx = leader->ctx; +- u64 values[5]; ++ int n = 0, size = 0, ret; + u64 count, enabled, running; ++ u64 values[5]; ++ ++ lockdep_assert_held(&ctx->mutex); + +- mutex_lock(&ctx->mutex); + count = perf_event_read_value(leader, &enabled, &running); + + values[n++] = 1 + leader->nr_siblings; +@@ -3579,7 +3700,7 @@ static int perf_event_read_group(struct perf_event *event, + size = n * sizeof(u64); + + if (copy_to_user(buf, values, size)) +- goto unlock; ++ return -EFAULT; + + ret = size; + +@@ -3593,14 +3714,11 @@ static int perf_event_read_group(struct perf_event *event, + size = n * sizeof(u64); + + if (copy_to_user(buf + ret, values, size)) { +- ret = -EFAULT; +- goto unlock; ++ return -EFAULT; + } + + ret += size; + } +-unlock: +- mutex_unlock(&ctx->mutex); + + return ret; + } +@@ -3672,8 +3790,14 @@ static ssize_t + perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) + { + struct perf_event *event = file->private_data; ++ struct perf_event_context *ctx; ++ int ret; + +- return perf_read_hw(event, buf, count); ++ ctx = perf_event_ctx_lock(event); ++ ret = perf_read_hw(event, buf, count); ++ perf_event_ctx_unlock(event, ctx); ++ ++ return ret; + } + + static unsigned int perf_poll(struct file *file, poll_table *wait) +@@ -3699,7 +3823,7 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) + return events; + } + +-static void perf_event_reset(struct perf_event *event) ++static void _perf_event_reset(struct perf_event *event) + { + (void)perf_event_read(event); + local64_set(&event->count, 0); +@@ -3718,6 +3842,7 @@ static void perf_event_for_each_child(struct perf_event *event, + struct perf_event *child; + + WARN_ON_ONCE(event->ctx->parent_ctx); ++ + mutex_lock(&event->child_mutex); + func(event); + list_for_each_entry(child, &event->child_list, child_list) +@@ -3731,14 +3856,13 @@ static void perf_event_for_each(struct perf_event *event, + struct perf_event_context *ctx = event->ctx; + struct perf_event *sibling; + +- WARN_ON_ONCE(ctx->parent_ctx); +- mutex_lock(&ctx->mutex); ++ lockdep_assert_held(&ctx->mutex); ++ + event = event->group_leader; + + perf_event_for_each_child(event, func); + list_for_each_entry(sibling, &event->sibling_list, group_entry) + perf_event_for_each_child(sibling, func); +- mutex_unlock(&ctx->mutex); + } + + static int perf_event_period(struct perf_event *event, u64 __user *arg) +@@ -3808,25 +3932,24 @@ static int perf_event_set_output(struct perf_event *event, + struct perf_event *output_event); + static int perf_event_set_filter(struct perf_event *event, void __user *arg); + +-static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg) + { +- struct perf_event *event = file->private_data; + void (*func)(struct perf_event *); + u32 flags = arg; + + switch (cmd) { + case PERF_EVENT_IOC_ENABLE: +- func = perf_event_enable; ++ func = _perf_event_enable; + break; + case PERF_EVENT_IOC_DISABLE: +- func = perf_event_disable; ++ func = _perf_event_disable; + break; + case PERF_EVENT_IOC_RESET: +- func = perf_event_reset; ++ func = _perf_event_reset; + break; + + case PERF_EVENT_IOC_REFRESH: +- return perf_event_refresh(event, arg); ++ return _perf_event_refresh(event, arg); + + case PERF_EVENT_IOC_PERIOD: + return perf_event_period(event, (u64 __user *)arg); +@@ -3873,6 +3996,19 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + return 0; + } + ++static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ struct perf_event *event = file->private_data; ++ struct perf_event_context *ctx; ++ long ret; ++ ++ ctx = perf_event_ctx_lock(event); ++ ret = _perf_ioctl(event, cmd, arg); ++ perf_event_ctx_unlock(event, ctx); ++ ++ return ret; ++} ++ + #ifdef CONFIG_COMPAT + static long perf_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +@@ -3895,11 +4031,15 @@ static long perf_compat_ioctl(struct file *file, unsigned int cmd, + + int perf_event_task_enable(void) + { ++ struct perf_event_context *ctx; + struct perf_event *event; + + mutex_lock(¤t->perf_event_mutex); +- list_for_each_entry(event, ¤t->perf_event_list, owner_entry) +- perf_event_for_each_child(event, perf_event_enable); ++ list_for_each_entry(event, ¤t->perf_event_list, owner_entry) { ++ ctx = perf_event_ctx_lock(event); ++ perf_event_for_each_child(event, _perf_event_enable); ++ perf_event_ctx_unlock(event, ctx); ++ } + mutex_unlock(¤t->perf_event_mutex); + + return 0; +@@ -3907,11 +4047,15 @@ int perf_event_task_enable(void) + + int perf_event_task_disable(void) + { ++ struct perf_event_context *ctx; + struct perf_event *event; + + mutex_lock(¤t->perf_event_mutex); +- list_for_each_entry(event, ¤t->perf_event_list, owner_entry) +- perf_event_for_each_child(event, perf_event_disable); ++ list_for_each_entry(event, ¤t->perf_event_list, owner_entry) { ++ ctx = perf_event_ctx_lock(event); ++ perf_event_for_each_child(event, _perf_event_disable); ++ perf_event_ctx_unlock(event, ctx); ++ } + mutex_unlock(¤t->perf_event_mutex); + + return 0; +@@ -7269,6 +7413,15 @@ out: + return ret; + } + ++static void mutex_lock_double(struct mutex *a, struct mutex *b) ++{ ++ if (b < a) ++ swap(a, b); ++ ++ mutex_lock(a); ++ mutex_lock_nested(b, SINGLE_DEPTH_NESTING); ++} ++ + /** + * sys_perf_event_open - open a performance event, associate it to a task/cpu + * +@@ -7284,7 +7437,7 @@ SYSCALL_DEFINE5(perf_event_open, + struct perf_event *group_leader = NULL, *output_event = NULL; + struct perf_event *event, *sibling; + struct perf_event_attr attr; +- struct perf_event_context *ctx; ++ struct perf_event_context *ctx, *uninitialized_var(gctx); + struct file *event_file = NULL; + struct fd group = {NULL, 0}; + struct task_struct *task = NULL; +@@ -7482,9 +7635,14 @@ SYSCALL_DEFINE5(perf_event_open, + } + + if (move_group) { +- struct perf_event_context *gctx = group_leader->ctx; ++ gctx = group_leader->ctx; ++ ++ /* ++ * See perf_event_ctx_lock() for comments on the details ++ * of swizzling perf_event::ctx. ++ */ ++ mutex_lock_double(&gctx->mutex, &ctx->mutex); + +- mutex_lock(&gctx->mutex); + perf_remove_from_context(group_leader, false); + + /* +@@ -7499,15 +7657,19 @@ SYSCALL_DEFINE5(perf_event_open, + perf_event__state_init(sibling); + put_ctx(gctx); + } +- mutex_unlock(&gctx->mutex); +- put_ctx(gctx); ++ } else { ++ mutex_lock(&ctx->mutex); + } + + WARN_ON_ONCE(ctx->parent_ctx); +- mutex_lock(&ctx->mutex); + + if (move_group) { ++ /* ++ * Wait for everybody to stop referencing the events through ++ * the old lists, before installing it on new lists. ++ */ + synchronize_rcu(); ++ + perf_install_in_context(ctx, group_leader, group_leader->cpu); + get_ctx(ctx); + list_for_each_entry(sibling, &group_leader->sibling_list, +@@ -7519,6 +7681,11 @@ SYSCALL_DEFINE5(perf_event_open, + + perf_install_in_context(ctx, event, event->cpu); + perf_unpin_context(ctx); ++ ++ if (move_group) { ++ mutex_unlock(&gctx->mutex); ++ put_ctx(gctx); ++ } + mutex_unlock(&ctx->mutex); + + put_online_cpus(); +@@ -7626,7 +7793,11 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) + src_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, src_cpu)->ctx; + dst_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, dst_cpu)->ctx; + +- mutex_lock(&src_ctx->mutex); ++ /* ++ * See perf_event_ctx_lock() for comments on the details ++ * of swizzling perf_event::ctx. ++ */ ++ mutex_lock_double(&src_ctx->mutex, &dst_ctx->mutex); + list_for_each_entry_safe(event, tmp, &src_ctx->event_list, + event_entry) { + perf_remove_from_context(event, false); +@@ -7634,11 +7805,9 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) + put_ctx(src_ctx); + list_add(&event->migrate_entry, &events); + } +- mutex_unlock(&src_ctx->mutex); + + synchronize_rcu(); + +- mutex_lock(&dst_ctx->mutex); + list_for_each_entry_safe(event, tmp, &events, migrate_entry) { + list_del(&event->migrate_entry); + if (event->state >= PERF_EVENT_STATE_OFF) +@@ -7648,6 +7817,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) + get_ctx(dst_ctx); + } + mutex_unlock(&dst_ctx->mutex); ++ mutex_unlock(&src_ctx->mutex); + } + EXPORT_SYMBOL_GPL(perf_pmu_migrate_context); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6791/0.patch b/Patches/Linux_CVEs/CVE-2016-6791/0.patch new file mode 100644 index 00000000..01fe5416 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6791/0.patch @@ -0,0 +1,97 @@ +From 62580295210b6c0bd809cde7088b45ebb65ace79 Mon Sep 17 00:00:00 2001 +From: Walter Yang +Date: Wed, 28 Sep 2016 20:11:23 +0800 +Subject: ASoC: msm: lock read/write when add/free audio ion memory + +As read/write get access to ion memory region as well, it's +necessary to lock them when ion memory is about to be added/freed +to avoid racing cases. + +CRs-Fixed: 1071809 +Change-Id: I436ead23c93384961b38ca99b9312a40c50ad03a +Signed-off-by: Walter Yang +--- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index 8041111..7a4bae3 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -1,6 +1,6 @@ + /* Copyright (C) 2008 Google, Inc. + * Copyright (C) 2008 HTC Corporation +- * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -570,6 +570,8 @@ int audio_aio_release(struct inode *inode, struct file *file) + struct q6audio_aio *audio = file->private_data; + pr_debug("%s[%p]\n", __func__, audio); + mutex_lock(&audio->lock); ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + audio->wflush = 1; + if (audio->enabled) + audio_aio_flush(audio); +@@ -584,6 +586,8 @@ int audio_aio_release(struct inode *inode, struct file *file) + wake_up(&audio->event_wait); + audio_aio_reset_event_queue(audio); + q6asm_audio_client_free(audio->ac); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + mutex_unlock(&audio->lock); + mutex_destroy(&audio->lock); + mutex_destroy(&audio->read_lock); +@@ -1679,7 +1683,11 @@ static long audio_aio_ioctl(struct file *file, unsigned int cmd, + __func__); + rc = -EFAULT; + } else { ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + rc = audio_aio_ion_add(audio, &info); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + } + mutex_unlock(&audio->lock); + break; +@@ -1694,7 +1702,11 @@ static long audio_aio_ioctl(struct file *file, unsigned int cmd, + __func__); + rc = -EFAULT; + } else { ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + rc = audio_aio_ion_remove(audio, &info); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + } + mutex_unlock(&audio->lock); + break; +@@ -1996,7 +2008,11 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + } else { + info.fd = info_32.fd; + info.vaddr = compat_ptr(info_32.vaddr); ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + rc = audio_aio_ion_add(audio, &info); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + } + mutex_unlock(&audio->lock); + break; +@@ -2013,7 +2029,11 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + } else { + info.fd = info_32.fd; + info.vaddr = compat_ptr(info_32.vaddr); ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + rc = audio_aio_ion_remove(audio, &info); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + } + mutex_unlock(&audio->lock); + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-6828/0.patch b/Patches/Linux_CVEs/CVE-2016-6828/0.patch new file mode 100644 index 00000000..0d4cfdd4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-6828/0.patch @@ -0,0 +1,55 @@ +From bb1fceca22492109be12640d49f5ea5a544c6bb4 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 17 Aug 2016 05:56:26 -0700 +Subject: tcp: fix use after free in tcp_xmit_retransmit_queue() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When tcp_sendmsg() allocates a fresh and empty skb, it puts it at the +tail of the write queue using tcp_add_write_queue_tail() + +Then it attempts to copy user data into this fresh skb. + +If the copy fails, we undo the work and remove the fresh skb. + +Unfortunately, this undo lacks the change done to tp->highest_sack and +we can leave a dangling pointer (to a freed skb) + +Later, tcp_xmit_retransmit_queue() can dereference this pointer and +access freed memory. For regular kernels where memory is not unmapped, +this might cause SACK bugs because tcp_highest_sack_seq() is buggy, +returning garbage instead of tp->snd_nxt, but with various debug +features like CONFIG_DEBUG_PAGEALLOC, this can crash the kernel. + +This bug was found by Marco Grassi thanks to syzkaller. + +Fixes: 6859d49475d4 ("[TCP]: Abstract tp->highest_sack accessing & point to next skb") +Reported-by: Marco Grassi +Signed-off-by: Eric Dumazet +Cc: Ilpo Järvinen +Cc: Yuchung Cheng +Cc: Neal Cardwell +Acked-by: Neal Cardwell +Reviewed-by: Cong Wang +Signed-off-by: David S. Miller +--- + include/net/tcp.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/net/tcp.h b/include/net/tcp.h +index c00e7d5..7717302 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1523,6 +1523,8 @@ static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unli + { + if (sk->sk_send_head == skb_unlinked) + sk->sk_send_head = NULL; ++ if (tcp_sk(sk)->highest_sack == skb_unlinked) ++ tcp_sk(sk)->highest_sack = NULL; + } + + static inline void tcp_init_send_head(struct sock *sk) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-7042/0.patch b/Patches/Linux_CVEs/CVE-2016-7042/0.patch new file mode 100644 index 00000000..7c96fe4f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7042/0.patch @@ -0,0 +1,74 @@ +From 03dab869b7b239c4e013ec82aea22e181e441cfc Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 26 Oct 2016 15:01:54 +0100 +Subject: KEYS: Fix short sprintf buffer in /proc/keys show function + +This fixes CVE-2016-7042. + +Fix a short sprintf buffer in proc_keys_show(). If the gcc stack protector +is turned on, this can cause a panic due to stack corruption. + +The problem is that xbuf[] is not big enough to hold a 64-bit timeout +rendered as weeks: + + (gdb) p 0xffffffffffffffffULL/(60*60*24*7) + $2 = 30500568904943 + +That's 14 chars plus NUL, not 11 chars plus NUL. + +Expand the buffer to 16 chars. + +I think the unpatched code apparently works if the stack-protector is not +enabled because on a 32-bit machine the buffer won't be overflowed and on a +64-bit machine there's a 64-bit aligned pointer at one side and an int that +isn't checked again on the other side. + +The panic incurred looks something like: + +Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81352ebe +CPU: 0 PID: 1692 Comm: reproducer Not tainted 4.7.2-201.fc24.x86_64 #1 +Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 + 0000000000000086 00000000fbbd2679 ffff8800a044bc00 ffffffff813d941f + ffffffff81a28d58 ffff8800a044bc98 ffff8800a044bc88 ffffffff811b2cb6 + ffff880000000010 ffff8800a044bc98 ffff8800a044bc30 00000000fbbd2679 +Call Trace: + [] dump_stack+0x63/0x84 + [] panic+0xde/0x22a + [] ? proc_keys_show+0x3ce/0x3d0 + [] __stack_chk_fail+0x19/0x30 + [] proc_keys_show+0x3ce/0x3d0 + [] ? key_validate+0x50/0x50 + [] ? key_default_cmp+0x20/0x20 + [] seq_read+0x2cc/0x390 + [] proc_reg_read+0x42/0x70 + [] __vfs_read+0x37/0x150 + [] ? security_file_permission+0xa0/0xc0 + [] vfs_read+0x96/0x130 + [] SyS_read+0x55/0xc0 + [] entry_SYSCALL_64_fastpath+0x1a/0xa4 + +Reported-by: Ondrej Kozina +Signed-off-by: David Howells +Tested-by: Ondrej Kozina +cc: stable@vger.kernel.org +Signed-off-by: James Morris +--- + security/keys/proc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/keys/proc.c b/security/keys/proc.c +index f0611a6..b9f531c 100644 +--- a/security/keys/proc.c ++++ b/security/keys/proc.c +@@ -181,7 +181,7 @@ static int proc_keys_show(struct seq_file *m, void *v) + struct timespec now; + unsigned long timo; + key_ref_t key_ref, skey_ref; +- char xbuf[12]; ++ char xbuf[16]; + int rc; + + struct keyring_search_context ctx = { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-7097/0.patch b/Patches/Linux_CVEs/CVE-2016-7097/0.patch new file mode 100644 index 00000000..94a7cfe6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7097/0.patch @@ -0,0 +1,436 @@ +From 073931017b49d9458aa351605b43a7e34598caef Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Mon, 19 Sep 2016 17:39:09 +0200 +Subject: posix_acl: Clear SGID bit when setting file permissions + +When file permissions are modified via chmod(2) and the user is not in +the owning group or capable of CAP_FSETID, the setgid bit is cleared in +inode_change_ok(). Setting a POSIX ACL via setxattr(2) sets the file +permissions as well as the new ACL, but doesn't clear the setgid bit in +a similar way; this allows to bypass the check in chmod(2). Fix that. + +References: CVE-2016-7097 +Reviewed-by: Christoph Hellwig +Reviewed-by: Jeff Layton +Signed-off-by: Jan Kara +Signed-off-by: Andreas Gruenbacher +--- + fs/9p/acl.c | 40 +++++++++++++++++----------------------- + fs/btrfs/acl.c | 6 ++---- + fs/ceph/acl.c | 6 ++---- + fs/ext2/acl.c | 12 ++++-------- + fs/ext4/acl.c | 12 ++++-------- + fs/f2fs/acl.c | 6 ++---- + fs/gfs2/acl.c | 12 +++--------- + fs/hfsplus/posix_acl.c | 4 ++-- + fs/jffs2/acl.c | 9 ++++----- + fs/jfs/acl.c | 6 ++---- + fs/ocfs2/acl.c | 10 ++++------ + fs/orangefs/acl.c | 15 +++++---------- + fs/posix_acl.c | 31 +++++++++++++++++++++++++++++++ + fs/reiserfs/xattr_acl.c | 8 ++------ + fs/xfs/xfs_acl.c | 13 ++++--------- + include/linux/posix_acl.h | 1 + + 16 files changed, 89 insertions(+), 102 deletions(-) + +diff --git a/fs/9p/acl.c b/fs/9p/acl.c +index 5b6a174..b3c2cc7 100644 +--- a/fs/9p/acl.c ++++ b/fs/9p/acl.c +@@ -276,32 +276,26 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, + switch (handler->flags) { + case ACL_TYPE_ACCESS: + if (acl) { +- umode_t mode = inode->i_mode; +- retval = posix_acl_equiv_mode(acl, &mode); +- if (retval < 0) ++ struct iattr iattr; ++ ++ retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); ++ if (retval) + goto err_out; +- else { +- struct iattr iattr; +- if (retval == 0) { +- /* +- * ACL can be represented +- * by the mode bits. So don't +- * update ACL. +- */ +- acl = NULL; +- value = NULL; +- size = 0; +- } +- /* Updte the mode bits */ +- iattr.ia_mode = ((mode & S_IALLUGO) | +- (inode->i_mode & ~S_IALLUGO)); +- iattr.ia_valid = ATTR_MODE; +- /* FIXME should we update ctime ? +- * What is the following setxattr update the +- * mode ? ++ if (!acl) { ++ /* ++ * ACL can be represented ++ * by the mode bits. So don't ++ * update ACL. + */ +- v9fs_vfs_setattr_dotl(dentry, &iattr); ++ value = NULL; ++ size = 0; + } ++ iattr.ia_valid = ATTR_MODE; ++ /* FIXME should we update ctime ? ++ * What is the following setxattr update the ++ * mode ? ++ */ ++ v9fs_vfs_setattr_dotl(dentry, &iattr); + } + break; + case ACL_TYPE_DEFAULT: +diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c +index 53bb7af..247b8df 100644 +--- a/fs/btrfs/acl.c ++++ b/fs/btrfs/acl.c +@@ -79,11 +79,9 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans, + case ACL_TYPE_ACCESS: + name = XATTR_NAME_POSIX_ACL_ACCESS; + if (acl) { +- ret = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (ret < 0) ++ ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); ++ if (ret) + return ret; +- if (ret == 0) +- acl = NULL; + } + ret = 0; + break; +diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c +index 4f67227..d0b6b342 100644 +--- a/fs/ceph/acl.c ++++ b/fs/ceph/acl.c +@@ -95,11 +95,9 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) + case ACL_TYPE_ACCESS: + name = XATTR_NAME_POSIX_ACL_ACCESS; + if (acl) { +- ret = posix_acl_equiv_mode(acl, &new_mode); +- if (ret < 0) ++ ret = posix_acl_update_mode(inode, &new_mode, &acl); ++ if (ret) + goto out; +- if (ret == 0) +- acl = NULL; + } + break; + case ACL_TYPE_DEFAULT: +diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c +index 42f1d18..e725aa0 100644 +--- a/fs/ext2/acl.c ++++ b/fs/ext2/acl.c +@@ -190,15 +190,11 @@ ext2_set_acl(struct inode *inode, struct posix_acl *acl, int type) + case ACL_TYPE_ACCESS: + name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; + if (acl) { +- error = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (error < 0) ++ error = posix_acl_update_mode(inode, &inode->i_mode, &acl); ++ if (error) + return error; +- else { +- inode->i_ctime = CURRENT_TIME_SEC; +- mark_inode_dirty(inode); +- if (error == 0) +- acl = NULL; +- } ++ inode->i_ctime = CURRENT_TIME_SEC; ++ mark_inode_dirty(inode); + } + break; + +diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c +index c6601a4..dfa5199 100644 +--- a/fs/ext4/acl.c ++++ b/fs/ext4/acl.c +@@ -193,15 +193,11 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int type, + case ACL_TYPE_ACCESS: + name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; + if (acl) { +- error = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (error < 0) ++ error = posix_acl_update_mode(inode, &inode->i_mode, &acl); ++ if (error) + return error; +- else { +- inode->i_ctime = ext4_current_time(inode); +- ext4_mark_inode_dirty(handle, inode); +- if (error == 0) +- acl = NULL; +- } ++ inode->i_ctime = ext4_current_time(inode); ++ ext4_mark_inode_dirty(handle, inode); + } + break; + +diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c +index 4dcc9e2..3134424 100644 +--- a/fs/f2fs/acl.c ++++ b/fs/f2fs/acl.c +@@ -210,12 +210,10 @@ static int __f2fs_set_acl(struct inode *inode, int type, + case ACL_TYPE_ACCESS: + name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; + if (acl) { +- error = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (error < 0) ++ error = posix_acl_update_mode(inode, &inode->i_mode, &acl); ++ if (error) + return error; + set_acl_inode(inode, inode->i_mode); +- if (error == 0) +- acl = NULL; + } + break; + +diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c +index 363ba9e..2524807 100644 +--- a/fs/gfs2/acl.c ++++ b/fs/gfs2/acl.c +@@ -92,17 +92,11 @@ int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) + if (type == ACL_TYPE_ACCESS) { + umode_t mode = inode->i_mode; + +- error = posix_acl_equiv_mode(acl, &mode); +- if (error < 0) ++ error = posix_acl_update_mode(inode, &inode->i_mode, &acl); ++ if (error) + return error; +- +- if (error == 0) +- acl = NULL; +- +- if (mode != inode->i_mode) { +- inode->i_mode = mode; ++ if (mode != inode->i_mode) + mark_inode_dirty(inode); +- } + } + + if (acl) { +diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c +index ab7ea25..9b92058 100644 +--- a/fs/hfsplus/posix_acl.c ++++ b/fs/hfsplus/posix_acl.c +@@ -65,8 +65,8 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, + case ACL_TYPE_ACCESS: + xattr_name = XATTR_NAME_POSIX_ACL_ACCESS; + if (acl) { +- err = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (err < 0) ++ err = posix_acl_update_mode(inode, &inode->i_mode, &acl); ++ if (err) + return err; + } + err = 0; +diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c +index bc2693d..2a0f2a1 100644 +--- a/fs/jffs2/acl.c ++++ b/fs/jffs2/acl.c +@@ -233,9 +233,10 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) + case ACL_TYPE_ACCESS: + xprefix = JFFS2_XPREFIX_ACL_ACCESS; + if (acl) { +- umode_t mode = inode->i_mode; +- rc = posix_acl_equiv_mode(acl, &mode); +- if (rc < 0) ++ umode_t mode; ++ ++ rc = posix_acl_update_mode(inode, &mode, &acl); ++ if (rc) + return rc; + if (inode->i_mode != mode) { + struct iattr attr; +@@ -247,8 +248,6 @@ int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) + if (rc < 0) + return rc; + } +- if (rc == 0) +- acl = NULL; + } + break; + case ACL_TYPE_DEFAULT: +diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c +index 21fa92b..3a1e155 100644 +--- a/fs/jfs/acl.c ++++ b/fs/jfs/acl.c +@@ -78,13 +78,11 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, + case ACL_TYPE_ACCESS: + ea_name = XATTR_NAME_POSIX_ACL_ACCESS; + if (acl) { +- rc = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (rc < 0) ++ rc = posix_acl_update_mode(inode, &inode->i_mode, &acl); ++ if (rc) + return rc; + inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); +- if (rc == 0) +- acl = NULL; + } + break; + case ACL_TYPE_DEFAULT: +diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c +index 2162434..164307b 100644 +--- a/fs/ocfs2/acl.c ++++ b/fs/ocfs2/acl.c +@@ -241,13 +241,11 @@ int ocfs2_set_acl(handle_t *handle, + case ACL_TYPE_ACCESS: + name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; + if (acl) { +- umode_t mode = inode->i_mode; +- ret = posix_acl_equiv_mode(acl, &mode); +- if (ret < 0) +- return ret; ++ umode_t mode; + +- if (ret == 0) +- acl = NULL; ++ ret = posix_acl_update_mode(inode, &mode, &acl); ++ if (ret) ++ return ret; + + ret = ocfs2_acl_set_mode(inode, di_bh, + handle, mode); +diff --git a/fs/orangefs/acl.c b/fs/orangefs/acl.c +index 28f2195..7a37544 100644 +--- a/fs/orangefs/acl.c ++++ b/fs/orangefs/acl.c +@@ -73,14 +73,11 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) + case ACL_TYPE_ACCESS: + name = XATTR_NAME_POSIX_ACL_ACCESS; + if (acl) { +- umode_t mode = inode->i_mode; +- /* +- * can we represent this with the traditional file +- * mode permission bits? +- */ +- error = posix_acl_equiv_mode(acl, &mode); +- if (error < 0) { +- gossip_err("%s: posix_acl_equiv_mode err: %d\n", ++ umode_t mode; ++ ++ error = posix_acl_update_mode(inode, &mode, &acl); ++ if (error) { ++ gossip_err("%s: posix_acl_update_mode err: %d\n", + __func__, + error); + return error; +@@ -90,8 +87,6 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) + SetModeFlag(orangefs_inode); + inode->i_mode = mode; + mark_inode_dirty_sync(inode); +- if (error == 0) +- acl = NULL; + } + break; + case ACL_TYPE_DEFAULT: +diff --git a/fs/posix_acl.c b/fs/posix_acl.c +index 59d47ab0..bfc3ec3 100644 +--- a/fs/posix_acl.c ++++ b/fs/posix_acl.c +@@ -626,6 +626,37 @@ no_mem: + } + EXPORT_SYMBOL_GPL(posix_acl_create); + ++/** ++ * posix_acl_update_mode - update mode in set_acl ++ * ++ * Update the file mode when setting an ACL: compute the new file permission ++ * bits based on the ACL. In addition, if the ACL is equivalent to the new ++ * file mode, set *acl to NULL to indicate that no ACL should be set. ++ * ++ * As with chmod, clear the setgit bit if the caller is not in the owning group ++ * or capable of CAP_FSETID (see inode_change_ok). ++ * ++ * Called from set_acl inode operations. ++ */ ++int posix_acl_update_mode(struct inode *inode, umode_t *mode_p, ++ struct posix_acl **acl) ++{ ++ umode_t mode = inode->i_mode; ++ int error; ++ ++ error = posix_acl_equiv_mode(*acl, &mode); ++ if (error < 0) ++ return error; ++ if (error == 0) ++ *acl = NULL; ++ if (!in_group_p(inode->i_gid) && ++ !capable_wrt_inode_uidgid(inode, CAP_FSETID)) ++ mode &= ~S_ISGID; ++ *mode_p = mode; ++ return 0; ++} ++EXPORT_SYMBOL(posix_acl_update_mode); ++ + /* + * Fix up the uids and gids in posix acl extended attributes in place. + */ +diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c +index dbed42f..2737668 100644 +--- a/fs/reiserfs/xattr_acl.c ++++ b/fs/reiserfs/xattr_acl.c +@@ -242,13 +242,9 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, + case ACL_TYPE_ACCESS: + name = XATTR_NAME_POSIX_ACL_ACCESS; + if (acl) { +- error = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (error < 0) ++ error = posix_acl_update_mode(inode, &inode->i_mode, &acl); ++ if (error) + return error; +- else { +- if (error == 0) +- acl = NULL; +- } + } + break; + case ACL_TYPE_DEFAULT: +diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c +index b6e527b..8a0dec8 100644 +--- a/fs/xfs/xfs_acl.c ++++ b/fs/xfs/xfs_acl.c +@@ -257,16 +257,11 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) + return error; + + if (type == ACL_TYPE_ACCESS) { +- umode_t mode = inode->i_mode; +- error = posix_acl_equiv_mode(acl, &mode); +- +- if (error <= 0) { +- acl = NULL; +- +- if (error < 0) +- return error; +- } ++ umode_t mode; + ++ error = posix_acl_update_mode(inode, &mode, &acl); ++ if (error) ++ return error; + error = xfs_set_mode(inode, mode); + if (error) + return error; +diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h +index d5d3d74..bf1046d 100644 +--- a/include/linux/posix_acl.h ++++ b/include/linux/posix_acl.h +@@ -93,6 +93,7 @@ extern int set_posix_acl(struct inode *, int, struct posix_acl *); + extern int posix_acl_chmod(struct inode *, umode_t); + extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, + struct posix_acl **); ++extern int posix_acl_update_mode(struct inode *, umode_t *, struct posix_acl **); + + extern int simple_set_acl(struct inode *, struct posix_acl *, int); + extern int simple_acl_create(struct inode *, struct inode *); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-7912/0.patch b/Patches/Linux_CVEs/CVE-2016-7912/0.patch new file mode 100644 index 00000000..d439e339 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7912/0.patch @@ -0,0 +1,37 @@ +From 83af063d6dec0439eb5abf3b19df2b4990e88e86 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Thu, 14 Apr 2016 17:01:17 +0200 +Subject: [PATCH] BACKPORT: usb: gadget: f_fs: Fix use-after-free + +(cherry picked from commit 38740a5b87d53ceb89eb2c970150f6e94e00373a) + +When using asynchronous read or write operations on the USB endpoints the +issuer of the IO request is notified by calling the ki_complete() callback +of the submitted kiocb when the URB has been completed. + +Calling this ki_complete() callback will free kiocb. Make sure that the +structure is no longer accessed beyond that point, otherwise undefined +behaviour might occur. + +Fixes: 2e4c7553cd6f ("usb: gadget: f_fs: add aio support") +Cc: # v3.15+ +Signed-off-by: Lars-Peter Clausen +Signed-off-by: Felipe Balbi +Change-Id: I3c7b643f6440c4fb6160a57c1058523030b46a6c +Bug: 30950866 +--- + drivers/usb/gadget/function/f_fs.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c +index e389c27d8e202..599a4273d29d4 100644 +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -689,7 +689,6 @@ static void ffs_user_copy_worker(struct work_struct *work) + + usb_ep_free_request(io_data->ep, io_data->req); + +- io_data->kiocb->private = NULL; + if (io_data->read) + kfree(io_data->iovec); + kfree(io_data->buf); diff --git a/Patches/Linux_CVEs/CVE-2016-7913/0.patch b/Patches/Linux_CVEs/CVE-2016-7913/0.patch new file mode 100644 index 00000000..dc42deea --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7913/0.patch @@ -0,0 +1,162 @@ +From 3240604bf46443d9eff61d1be7c0b9a9b247851b Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Thu, 28 Jan 2016 09:22:44 -0200 +Subject: [PATCH] UPSTREAM: [media] xc2028: avoid use after free + +If struct xc2028_config is passed without a firmware name, +the following trouble may happen: + +[11009.907205] xc2028 5-0061: type set to XCeive xc2028/xc3028 tuner +[11009.907491] ================================================================== +[11009.907750] BUG: KASAN: use-after-free in strcmp+0x96/0xb0 at addr ffff8803bd78ab40 +[11009.907992] Read of size 1 by task modprobe/28992 +[11009.907994] ============================================================================= +[11009.907997] BUG kmalloc-16 (Tainted: G W ): kasan: bad access detected +[11009.907999] ----------------------------------------------------------------------------- + +[11009.908008] INFO: Allocated in xhci_urb_enqueue+0x214/0x14c0 [xhci_hcd] age=0 cpu=3 pid=28992 +[11009.908012] ___slab_alloc+0x581/0x5b0 +[11009.908014] __slab_alloc+0x51/0x90 +[11009.908017] __kmalloc+0x27b/0x350 +[11009.908022] xhci_urb_enqueue+0x214/0x14c0 [xhci_hcd] +[11009.908026] usb_hcd_submit_urb+0x1e8/0x1c60 +[11009.908029] usb_submit_urb+0xb0e/0x1200 +[11009.908032] usb_serial_generic_write_start+0xb6/0x4c0 +[11009.908035] usb_serial_generic_write+0x92/0xc0 +[11009.908039] usb_console_write+0x38a/0x560 +[11009.908045] call_console_drivers.constprop.14+0x1ee/0x2c0 +[11009.908051] console_unlock+0x40d/0x900 +[11009.908056] vprintk_emit+0x4b4/0x830 +[11009.908061] vprintk_default+0x1f/0x30 +[11009.908064] printk+0x99/0xb5 +[11009.908067] kasan_report_error+0x10a/0x550 +[11009.908070] __asan_report_load1_noabort+0x43/0x50 +[11009.908074] INFO: Freed in xc2028_set_config+0x90/0x630 [tuner_xc2028] age=1 cpu=3 pid=28992 +[11009.908077] __slab_free+0x2ec/0x460 +[11009.908080] kfree+0x266/0x280 +[11009.908083] xc2028_set_config+0x90/0x630 [tuner_xc2028] +[11009.908086] xc2028_attach+0x310/0x8a0 [tuner_xc2028] +[11009.908090] em28xx_attach_xc3028.constprop.7+0x1f9/0x30d [em28xx_dvb] +[11009.908094] em28xx_dvb_init.part.3+0x8e4/0x5cf4 [em28xx_dvb] +[11009.908098] em28xx_dvb_init+0x81/0x8a [em28xx_dvb] +[11009.908101] em28xx_register_extension+0xd9/0x190 [em28xx] +[11009.908105] em28xx_dvb_register+0x10/0x1000 [em28xx_dvb] +[11009.908108] do_one_initcall+0x141/0x300 +[11009.908111] do_init_module+0x1d0/0x5ad +[11009.908114] load_module+0x6666/0x9ba0 +[11009.908117] SyS_finit_module+0x108/0x130 +[11009.908120] entry_SYSCALL_64_fastpath+0x16/0x76 +[11009.908123] INFO: Slab 0xffffea000ef5e280 objects=25 used=25 fp=0x (null) flags=0x2ffff8000004080 +[11009.908126] INFO: Object 0xffff8803bd78ab40 @offset=2880 fp=0x0000000000000001 + +[11009.908130] Bytes b4 ffff8803bd78ab30: 01 00 00 00 2a 07 00 00 9d 28 00 00 01 00 00 00 ....*....(...... +[11009.908133] Object ffff8803bd78ab40: 01 00 00 00 00 00 00 00 b0 1d c3 6a 00 88 ff ff ...........j.... +[11009.908137] CPU: 3 PID: 28992 Comm: modprobe Tainted: G B W 4.5.0-rc1+ #43 +[11009.908140] Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 +[11009.908142] ffff8803bd78a000 ffff8802c273f1b8 ffffffff81932007 ffff8803c6407a80 +[11009.908148] ffff8802c273f1e8 ffffffff81556759 ffff8803c6407a80 ffffea000ef5e280 +[11009.908153] ffff8803bd78ab40 dffffc0000000000 ffff8802c273f210 ffffffff8155ccb4 +[11009.908158] Call Trace: +[11009.908162] [] dump_stack+0x4b/0x64 +[11009.908165] [] print_trailer+0xf9/0x150 +[11009.908168] [] object_err+0x34/0x40 +[11009.908171] [] kasan_report_error+0x230/0x550 +[11009.908175] [] ? trace_hardirqs_off_caller+0x21/0x290 +[11009.908179] [] ? kasan_unpoison_shadow+0x36/0x50 +[11009.908182] [] __asan_report_load1_noabort+0x43/0x50 +[11009.908185] [] ? __asan_register_globals+0x50/0xa0 +[11009.908189] [] ? strcmp+0x96/0xb0 +[11009.908192] [] strcmp+0x96/0xb0 +[11009.908196] [] xc2028_set_config+0x15c/0x630 [tuner_xc2028] +[11009.908200] [] xc2028_attach+0x310/0x8a0 [tuner_xc2028] +[11009.908203] [] ? memset+0x28/0x30 +[11009.908206] [] ? xc2028_set_config+0x630/0x630 [tuner_xc2028] +[11009.908211] [] em28xx_attach_xc3028.constprop.7+0x1f9/0x30d [em28xx_dvb] +[11009.908215] [] ? em28xx_dvb_init.part.3+0x37c/0x5cf4 [em28xx_dvb] +[11009.908219] [] ? hauppauge_hvr930c_init+0x487/0x487 [em28xx_dvb] +[11009.908222] [] ? lgdt330x_attach+0x1cc/0x370 [lgdt330x] +[11009.908226] [] ? i2c_read_demod_bytes.isra.2+0x210/0x210 [lgdt330x] +[11009.908230] [] ? ref_module.part.15+0x10/0x10 +[11009.908233] [] ? module_assert_mutex_or_preempt+0x80/0x80 +[11009.908238] [] em28xx_dvb_init.part.3+0x8e4/0x5cf4 [em28xx_dvb] +[11009.908242] [] ? em28xx_attach_xc3028.constprop.7+0x30d/0x30d [em28xx_dvb] +[11009.908245] [] ? string+0x14d/0x1f0 +[11009.908249] [] ? symbol_string+0xff/0x1a0 +[11009.908253] [] ? uuid_string+0x6f0/0x6f0 +[11009.908257] [] ? __kernel_text_address+0x7e/0xa0 +[11009.908260] [] ? print_context_stack+0x7f/0xf0 +[11009.908264] [] ? __module_address+0xb6/0x360 +[11009.908268] [] ? is_ftrace_trampoline+0x99/0xe0 +[11009.908271] [] ? __kernel_text_address+0x7e/0xa0 +[11009.908275] [] ? debug_check_no_locks_freed+0x290/0x290 +[11009.908278] [] ? dump_trace+0x11b/0x300 +[11009.908282] [] ? em28xx_register_extension+0x23/0x190 [em28xx] +[11009.908285] [] ? trace_hardirqs_off_caller+0x21/0x290 +[11009.908289] [] ? trace_hardirqs_on_caller+0x16/0x590 +[11009.908292] [] ? trace_hardirqs_on+0xd/0x10 +[11009.908296] [] ? em28xx_register_extension+0x23/0x190 [em28xx] +[11009.908299] [] ? mutex_trylock+0x400/0x400 +[11009.908302] [] ? do_one_initcall+0x131/0x300 +[11009.908306] [] ? call_rcu_sched+0x17/0x20 +[11009.908309] [] ? put_object+0x48/0x70 +[11009.908314] [] em28xx_dvb_init+0x81/0x8a [em28xx_dvb] +[11009.908317] [] em28xx_register_extension+0xd9/0x190 [em28xx] +[11009.908320] [] ? 0xffffffffa0150000 +[11009.908324] [] em28xx_dvb_register+0x10/0x1000 [em28xx_dvb] +[11009.908327] [] do_one_initcall+0x141/0x300 +[11009.908330] [] ? try_to_run_init_process+0x40/0x40 +[11009.908333] [] ? trace_hardirqs_on_caller+0x16/0x590 +[11009.908337] [] ? kasan_unpoison_shadow+0x36/0x50 +[11009.908340] [] ? kasan_unpoison_shadow+0x36/0x50 +[11009.908343] [] ? kasan_unpoison_shadow+0x36/0x50 +[11009.908346] [] ? __asan_register_globals+0x87/0xa0 +[11009.908350] [] do_init_module+0x1d0/0x5ad +[11009.908353] [] load_module+0x6666/0x9ba0 +[11009.908356] [] ? symbol_put_addr+0x50/0x50 +[11009.908361] [] ? em28xx_dvb_init.part.3+0x5989/0x5cf4 [em28xx_dvb] +[11009.908366] [] ? module_frob_arch_sections+0x20/0x20 +[11009.908369] [] ? open_exec+0x50/0x50 +[11009.908374] [] ? ns_capable+0x5b/0xd0 +[11009.908377] [] SyS_finit_module+0x108/0x130 +[11009.908379] [] ? SyS_init_module+0x1f0/0x1f0 +[11009.908383] [] ? lockdep_sys_exit_thunk+0x12/0x14 +[11009.908394] [] entry_SYSCALL_64_fastpath+0x16/0x76 +[11009.908396] Memory state around the buggy address: +[11009.908398] ffff8803bd78aa00: 00 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[11009.908401] ffff8803bd78aa80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[11009.908403] >ffff8803bd78ab00: fc fc fc fc fc fc fc fc 00 00 fc fc fc fc fc fc +[11009.908405] ^ +[11009.908407] ffff8803bd78ab80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[11009.908409] ffff8803bd78ac00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[11009.908411] ================================================================== + +In order to avoid it, let's set the cached value of the firmware +name to NULL after freeing it. While here, return an error if +the memory allocation fails. + +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 8dfbcc4351a0b6d2f2d77f367552f48ffefafe18) +Bug: 30946097 +Change-Id: I95d962c55c8c9b39d747cb326de263972331e8cd +--- + drivers/media/tuners/tuner-xc2028.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c +index 9771cd83c06e2..38afc54ef3497 100644 +--- a/drivers/media/tuners/tuner-xc2028.c ++++ b/drivers/media/tuners/tuner-xc2028.c +@@ -1385,11 +1385,12 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) + * in order to avoid troubles during device release. + */ + kfree(priv->ctrl.fname); ++ priv->ctrl.fname = NULL; + memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); + if (p->fname) { + priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); + if (priv->ctrl.fname == NULL) +- rc = -ENOMEM; ++ return -ENOMEM; + } + + /* diff --git a/Patches/Linux_CVEs/CVE-2016-7913/1.patch b/Patches/Linux_CVEs/CVE-2016-7913/1.patch new file mode 100644 index 00000000..bd96fdc9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7913/1.patch @@ -0,0 +1,45 @@ +From b151b71cd689c9002b94c295bedd8c8c0b7ae98e Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 3 Feb 2016 13:34:00 -0200 +Subject: [PATCH] UPSTREAM: [media] xc2028: unlock on error in + xc2028_set_config() + +We have to unlock before returning -ENOMEM. + +Fixes: 8dfbcc4351a0 ('[media] xc2028: avoid use after free') + +Signed-off-by: Dan Carpenter +Signed-off-by: Mauro Carvalho Chehab +(cherry picked from commit 210bd104c6acd31c3c6b8b075b3f12d4a9f6b60d) +Bug: 30946097 + +Change-Id: I2d0bab35824d204a05de36e265c443938033eb81 +--- + drivers/media/tuners/tuner-xc2028.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c +index 38afc54ef3497..ab0bfc46f99f2 100644 +--- a/drivers/media/tuners/tuner-xc2028.c ++++ b/drivers/media/tuners/tuner-xc2028.c +@@ -1389,8 +1389,10 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) + memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); + if (p->fname) { + priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); +- if (priv->ctrl.fname == NULL) +- return -ENOMEM; ++ if (priv->ctrl.fname == NULL) { ++ rc = -ENOMEM; ++ goto unlock; ++ } + } + + /* +@@ -1422,6 +1424,7 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) + } else + priv->state = XC2028_WAITING_FIRMWARE; + } ++unlock: + mutex_unlock(&priv->lock); + + return rc; diff --git a/Patches/Linux_CVEs/CVE-2016-7913/2.patch b/Patches/Linux_CVEs/CVE-2016-7913/2.patch new file mode 100644 index 00000000..d337894f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7913/2.patch @@ -0,0 +1,131 @@ +From 3bdb157105639fdcdff744432760c3f25c545678 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 17 Nov 2016 10:49:31 +0100 +Subject: xc2028: Fix use-after-free bug properly + +commit 22a1e7783e173ab3d86018eb590107d68df46c11 upstream. + +The commit 8dfbcc4351a0 ("[media] xc2028: avoid use after free") tried +to address the reported use-after-free by clearing the reference. + +However, it's clearing the wrong pointer; it sets NULL to +priv->ctrl.fname, but it's anyway overwritten by the next line +memcpy(&priv->ctrl, p, sizeof(priv->ctrl)). + +OTOH, the actual code accessing the freed string is the strcmp() call +with priv->fname: + if (!firmware_name[0] && p->fname && + priv->fname && strcmp(p->fname, priv->fname)) + free_firmware(priv); + +where priv->fname points to the previous file name, and this was +already freed by kfree(). + +For fixing the bug properly, this patch does the following: + +- Keep the copy of firmware file name in only priv->fname, + priv->ctrl.fname isn't changed; +- The allocation is done only when the firmware gets loaded; +- The kfree() is called in free_firmware() commonly + +Fixes: commit 8dfbcc4351a0 ('[media] xc2028: avoid use after free') +Signed-off-by: Takashi Iwai +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Willy Tarreau +--- + drivers/media/tuners/tuner-xc2028.c | 36 ++++++++++++++++-------------------- + 1 file changed, 16 insertions(+), 20 deletions(-) + +diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c +index ab0bfc46..3a615e4 100644 +--- a/drivers/media/tuners/tuner-xc2028.c ++++ b/drivers/media/tuners/tuner-xc2028.c +@@ -289,6 +289,14 @@ static void free_firmware(struct xc2028_data *priv) + int i; + tuner_dbg("%s called\n", __func__); + ++ /* free allocated f/w string */ ++ if (priv->fname != firmware_name) ++ kfree(priv->fname); ++ priv->fname = NULL; ++ ++ priv->state = XC2028_NO_FIRMWARE; ++ memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); ++ + if (!priv->firm) + return; + +@@ -299,9 +307,6 @@ static void free_firmware(struct xc2028_data *priv) + + priv->firm = NULL; + priv->firm_size = 0; +- priv->state = XC2028_NO_FIRMWARE; +- +- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); + } + + static int load_all_firmwares(struct dvb_frontend *fe, +@@ -890,9 +895,9 @@ read_not_reliable: + return 0; + + fail: ++ free_firmware(priv); + priv->state = XC2028_SLEEP; + +- memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); + if (retry_count < 8) { + msleep(50); + retry_count++; +@@ -1314,11 +1319,8 @@ static int xc2028_dvb_release(struct dvb_frontend *fe) + mutex_lock(&xc2028_list_mutex); + + /* only perform final cleanup if this is the last instance */ +- if (hybrid_tuner_report_instance_count(priv) == 1) { ++ if (hybrid_tuner_report_instance_count(priv) == 1) + free_firmware(priv); +- kfree(priv->ctrl.fname); +- priv->ctrl.fname = NULL; +- } + + if (priv) + hybrid_tuner_release_state(priv); +@@ -1381,19 +1383,8 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) + + /* + * Copy the config data. +- * For the firmware name, keep a local copy of the string, +- * in order to avoid troubles during device release. + */ +- kfree(priv->ctrl.fname); +- priv->ctrl.fname = NULL; + memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); +- if (p->fname) { +- priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); +- if (priv->ctrl.fname == NULL) { +- rc = -ENOMEM; +- goto unlock; +- } +- } + + /* + * If firmware name changed, frees firmware. As free_firmware will +@@ -1408,10 +1399,15 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) + + if (priv->state == XC2028_NO_FIRMWARE) { + if (!firmware_name[0]) +- priv->fname = priv->ctrl.fname; ++ priv->fname = kstrdup(p->fname, GFP_KERNEL); + else + priv->fname = firmware_name; + ++ if (!priv->fname) { ++ rc = -ENOMEM; ++ goto unlock; ++ } ++ + rc = request_firmware_nowait(THIS_MODULE, 1, + priv->fname, + priv->i2c_props.adap->dev.parent, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-7914/0.patch b/Patches/Linux_CVEs/CVE-2016-7914/0.patch new file mode 100644 index 00000000..dfe5c639 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7914/0.patch @@ -0,0 +1,109 @@ +From 8d4a2ec1e0b41b0cf9a0c5cd4511da7f8e4f3de2 Mon Sep 17 00:00:00 2001 +From: Jerome Marchand +Date: Wed, 6 Apr 2016 14:06:48 +0100 +Subject: [PATCH] assoc_array: don't call compare_object() on a node + +Changes since V1: fixed the description and added KASan warning. + +In assoc_array_insert_into_terminal_node(), we call the +compare_object() method on all non-empty slots, even when they're +not leaves, passing a pointer to an unexpected structure to +compare_object(). Currently it causes an out-of-bound read access +in keyring_compare_object detected by KASan (see below). The issue +is easily reproduced with keyutils testsuite. +Only call compare_object() when the slot is a leave. + +KASan warning: +================================================================== +BUG: KASAN: slab-out-of-bounds in keyring_compare_object+0x213/0x240 at addr ffff880060a6f838 +Read of size 8 by task keyctl/1655 +============================================================================= +BUG kmalloc-192 (Not tainted): kasan: bad access detected +----------------------------------------------------------------------------- + +Disabling lock debugging due to kernel taint +INFO: Allocated in assoc_array_insert+0xfd0/0x3a60 age=69 cpu=1 pid=1647 + ___slab_alloc+0x563/0x5c0 + __slab_alloc+0x51/0x90 + kmem_cache_alloc_trace+0x263/0x300 + assoc_array_insert+0xfd0/0x3a60 + __key_link_begin+0xfc/0x270 + key_create_or_update+0x459/0xaf0 + SyS_add_key+0x1ba/0x350 + entry_SYSCALL_64_fastpath+0x12/0x76 +INFO: Slab 0xffffea0001829b80 objects=16 used=8 fp=0xffff880060a6f550 flags=0x3fff8000004080 +INFO: Object 0xffff880060a6f740 @offset=5952 fp=0xffff880060a6e5d1 + +Bytes b4 ffff880060a6f730: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f740: d1 e5 a6 60 00 88 ff ff 0e 00 00 00 00 00 00 00 ...`............ +Object ffff880060a6f750: 02 cf 8e 60 00 88 ff ff 02 c0 8e 60 00 88 ff ff ...`.......`.... +Object ffff880060a6f760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f790: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f7a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f7b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f7c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f7d0: 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f7e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffff880060a6f7f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +CPU: 0 PID: 1655 Comm: keyctl Tainted: G B 4.5.0-rc4-kasan+ #291 +Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 + 0000000000000000 000000001b2800b4 ffff880060a179e0 ffffffff81b60491 + ffff88006c802900 ffff880060a6f740 ffff880060a17a10 ffffffff815e2969 + ffff88006c802900 ffffea0001829b80 ffff880060a6f740 ffff880060a6e650 +Call Trace: + [] dump_stack+0x85/0xc4 + [] print_trailer+0xf9/0x150 + [] object_err+0x34/0x40 + [] kasan_report_error+0x230/0x550 + [] ? keyring_get_key_chunk+0x13e/0x210 + [] __asan_report_load_n_noabort+0x5d/0x70 + [] ? keyring_compare_object+0x213/0x240 + [] keyring_compare_object+0x213/0x240 + [] assoc_array_insert+0x86c/0x3a60 + [] ? assoc_array_cancel_edit+0x70/0x70 + [] ? __key_link_begin+0x20d/0x270 + [] __key_link_begin+0xfc/0x270 + [] key_create_or_update+0x459/0xaf0 + [] ? trace_hardirqs_on+0xd/0x10 + [] ? key_type_lookup+0xc0/0xc0 + [] ? lookup_user_key+0x13d/0xcd0 + [] ? memdup_user+0x53/0x80 + [] SyS_add_key+0x1ba/0x350 + [] ? key_get_type_from_user.constprop.6+0xa0/0xa0 + [] ? retint_user+0x18/0x23 + [] ? trace_hardirqs_on_caller+0x3fe/0x580 + [] ? trace_hardirqs_on_thunk+0x17/0x19 + [] entry_SYSCALL_64_fastpath+0x12/0x76 +Memory state around the buggy address: + ffff880060a6f700: fc fc fc fc fc fc fc fc 00 00 00 00 00 00 00 00 + ffff880060a6f780: 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc +>ffff880060a6f800: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ^ + ffff880060a6f880: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ffff880060a6f900: fc fc fc fc fc fc 00 00 00 00 00 00 00 00 00 00 +================================================================== + +Signed-off-by: Jerome Marchand +Signed-off-by: David Howells +cc: stable@vger.kernel.org +--- + lib/assoc_array.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/lib/assoc_array.c b/lib/assoc_array.c +index 03dd576e67730..59fd7c0b119cb 100644 +--- a/lib/assoc_array.c ++++ b/lib/assoc_array.c +@@ -524,7 +524,9 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit, + free_slot = i; + continue; + } +- if (ops->compare_object(assoc_array_ptr_to_leaf(ptr), index_key)) { ++ if (assoc_array_ptr_is_leaf(ptr) && ++ ops->compare_object(assoc_array_ptr_to_leaf(ptr), ++ index_key)) { + pr_devel("replace in slot %d\n", i); + edit->leaf_p = &node->slots[i]; + edit->dead_leaf = node->slots[i]; diff --git a/Patches/Linux_CVEs/CVE-2016-7915/0.patch b/Patches/Linux_CVEs/CVE-2016-7915/0.patch new file mode 100644 index 00000000..a37e499e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7915/0.patch @@ -0,0 +1,47 @@ +From 50220dead1650609206efe91f0cc116132d59b3f Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Tue, 19 Jan 2016 12:34:58 +0100 +Subject: HID: core: prevent out-of-bound readings + +Plugging a Logitech DJ receiver with KASAN activated raises a bunch of +out-of-bound readings. + +The fields are allocated up to MAX_USAGE, meaning that potentially, we do +not have enough fields to fit the incoming values. +Add checks and silence KASAN. + +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 16c2c66..3f6ac5f 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1293,6 +1293,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, + /* Ignore report if ErrorRollOver */ + if (!(field->flags & HID_MAIN_ITEM_VARIABLE) && + value[n] >= min && value[n] <= max && ++ value[n] - min < field->maxusage && + field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) + goto exit; + } +@@ -1305,11 +1306,13 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, + } + + if (field->value[n] >= min && field->value[n] <= max ++ && field->value[n] - min < field->maxusage + && field->usage[field->value[n] - min].hid + && search(value, field->value[n], count)) + hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt); + + if (value[n] >= min && value[n] <= max ++ && value[n] - min < field->maxusage + && field->usage[value[n] - min].hid + && search(field->value, value[n], count)) + hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-7916/0.patch b/Patches/Linux_CVEs/CVE-2016-7916/0.patch new file mode 100644 index 00000000..310cb3ec --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7916/0.patch @@ -0,0 +1,56 @@ +From 8148a73c9901a8794a50f950083c00ccf97d43b3 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Thu, 5 May 2016 16:22:26 -0700 +Subject: proc: prevent accessing /proc//environ until it's ready + +If /proc//environ gets read before the envp[] array is fully set up +in create_{aout,elf,elf_fdpic,flat}_tables(), we might end up trying to +read more bytes than are actually written, as env_start will already be +set but env_end will still be zero, making the range calculation +underflow, allowing to read beyond the end of what has been written. + +Fix this as it is done for /proc//cmdline by testing env_end for +zero. It is, apparently, intentionally set last in create_*_tables(). + +This bug was found by the PaX size_overflow plugin that detected the +arithmetic underflow of 'this_len = env_end - (env_start + src)' when +env_end is still zero. + +The expected consequence is that userland trying to access +/proc//environ of a not yet fully set up process may get +inconsistent data as we're in the middle of copying in the environment +variables. + +Fixes: https://forums.grsecurity.net/viewtopic.php?f=3&t=4363 +Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=116461 +Signed-off-by: Mathias Krause +Cc: Emese Revfy +Cc: Pax Team +Cc: Al Viro +Cc: Mateusz Guzik +Cc: Alexey Dobriyan +Cc: Cyrill Gorcunov +Cc: Jarod Wilson +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + fs/proc/base.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index b1755b2..92e37e2 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -955,7 +955,8 @@ static ssize_t environ_read(struct file *file, char __user *buf, + struct mm_struct *mm = file->private_data; + unsigned long env_start, env_end; + +- if (!mm) ++ /* Ensure the process spawned far enough to have an environment. */ ++ if (!mm || !mm->env_end) + return 0; + + page = (char *)__get_free_page(GFP_TEMPORARY); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-7917/0.patch b/Patches/Linux_CVEs/CVE-2016-7917/0.patch new file mode 100644 index 00000000..6cbbe4e2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-7917/0.patch @@ -0,0 +1,76 @@ +From c58d6c93680f28ac58984af61d0a7ebf4319c241 Mon Sep 17 00:00:00 2001 +From: Phil Turnbull +Date: Tue, 2 Feb 2016 13:36:45 -0500 +Subject: netfilter: nfnetlink: correctly validate length of batch messages + +If nlh->nlmsg_len is zero then an infinite loop is triggered because +'skb_pull(skb, msglen);' pulls zero bytes. + +The calculation in nlmsg_len() underflows if 'nlh->nlmsg_len < +NLMSG_HDRLEN' which bypasses the length validation and will later +trigger an out-of-bound read. + +If the length validation does fail then the malformed batch message is +copied back to userspace. However, we cannot do this because the +nlh->nlmsg_len can be invalid. This leads to an out-of-bounds read in +netlink_ack: + + [ 41.455421] ================================================================== + [ 41.456431] BUG: KASAN: slab-out-of-bounds in memcpy+0x1d/0x40 at addr ffff880119e79340 + [ 41.456431] Read of size 4294967280 by task a.out/987 + [ 41.456431] ============================================================================= + [ 41.456431] BUG kmalloc-512 (Not tainted): kasan: bad access detected + [ 41.456431] ----------------------------------------------------------------------------- + ... + [ 41.456431] Bytes b4 ffff880119e79310: 00 00 00 00 d5 03 00 00 b0 fb fe ff 00 00 00 00 ................ + [ 41.456431] Object ffff880119e79320: 20 00 00 00 10 00 05 00 00 00 00 00 00 00 00 00 ............... + [ 41.456431] Object ffff880119e79330: 14 00 0a 00 01 03 fc 40 45 56 11 22 33 10 00 05 .......@EV."3... + [ 41.456431] Object ffff880119e79340: f0 ff ff ff 88 99 aa bb 00 14 00 0a 00 06 fe fb ................ + ^^ start of batch nlmsg with + nlmsg_len=4294967280 + ... + [ 41.456431] Memory state around the buggy address: + [ 41.456431] ffff880119e79400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + [ 41.456431] ffff880119e79480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + [ 41.456431] >ffff880119e79500: 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc fc + [ 41.456431] ^ + [ 41.456431] ffff880119e79580: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + [ 41.456431] ffff880119e79600: fc fc fc fc fc fc fc fc fc fc fb fb fb fb fb fb + [ 41.456431] ================================================================== + +Fix this with better validation of nlh->nlmsg_len and by setting +NFNL_BATCH_FAILURE if any batch message fails length validation. + +CAP_NET_ADMIN is required to trigger the bugs. + +Fixes: 9ea2aa8b7dba ("netfilter: nfnetlink: validate nfnetlink header from batch") +Signed-off-by: Phil Turnbull +Signed-off-by: Pablo Neira Ayuso +--- + net/netfilter/nfnetlink.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c +index 62e92af..857ae89 100644 +--- a/net/netfilter/nfnetlink.c ++++ b/net/netfilter/nfnetlink.c +@@ -328,10 +328,12 @@ replay: + nlh = nlmsg_hdr(skb); + err = 0; + +- if (nlmsg_len(nlh) < sizeof(struct nfgenmsg) || +- skb->len < nlh->nlmsg_len) { +- err = -EINVAL; +- goto ack; ++ if (nlh->nlmsg_len < NLMSG_HDRLEN || ++ skb->len < nlh->nlmsg_len || ++ nlmsg_len(nlh) < sizeof(struct nfgenmsg)) { ++ nfnl_err_reset(&err_list); ++ status |= NFNL_BATCH_FAILURE; ++ goto done; + } + + /* Only requests are handled by the kernel */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8391/0.patch b/Patches/Linux_CVEs/CVE-2016-8391/0.patch new file mode 100644 index 00000000..01fe5416 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8391/0.patch @@ -0,0 +1,97 @@ +From 62580295210b6c0bd809cde7088b45ebb65ace79 Mon Sep 17 00:00:00 2001 +From: Walter Yang +Date: Wed, 28 Sep 2016 20:11:23 +0800 +Subject: ASoC: msm: lock read/write when add/free audio ion memory + +As read/write get access to ion memory region as well, it's +necessary to lock them when ion memory is about to be added/freed +to avoid racing cases. + +CRs-Fixed: 1071809 +Change-Id: I436ead23c93384961b38ca99b9312a40c50ad03a +Signed-off-by: Walter Yang +--- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index 8041111..7a4bae3 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -1,6 +1,6 @@ + /* Copyright (C) 2008 Google, Inc. + * Copyright (C) 2008 HTC Corporation +- * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -570,6 +570,8 @@ int audio_aio_release(struct inode *inode, struct file *file) + struct q6audio_aio *audio = file->private_data; + pr_debug("%s[%p]\n", __func__, audio); + mutex_lock(&audio->lock); ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + audio->wflush = 1; + if (audio->enabled) + audio_aio_flush(audio); +@@ -584,6 +586,8 @@ int audio_aio_release(struct inode *inode, struct file *file) + wake_up(&audio->event_wait); + audio_aio_reset_event_queue(audio); + q6asm_audio_client_free(audio->ac); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + mutex_unlock(&audio->lock); + mutex_destroy(&audio->lock); + mutex_destroy(&audio->read_lock); +@@ -1679,7 +1683,11 @@ static long audio_aio_ioctl(struct file *file, unsigned int cmd, + __func__); + rc = -EFAULT; + } else { ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + rc = audio_aio_ion_add(audio, &info); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + } + mutex_unlock(&audio->lock); + break; +@@ -1694,7 +1702,11 @@ static long audio_aio_ioctl(struct file *file, unsigned int cmd, + __func__); + rc = -EFAULT; + } else { ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + rc = audio_aio_ion_remove(audio, &info); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + } + mutex_unlock(&audio->lock); + break; +@@ -1996,7 +2008,11 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + } else { + info.fd = info_32.fd; + info.vaddr = compat_ptr(info_32.vaddr); ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + rc = audio_aio_ion_add(audio, &info); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + } + mutex_unlock(&audio->lock); + break; +@@ -2013,7 +2029,11 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd, + } else { + info.fd = info_32.fd; + info.vaddr = compat_ptr(info_32.vaddr); ++ mutex_lock(&audio->read_lock); ++ mutex_lock(&audio->write_lock); + rc = audio_aio_ion_remove(audio, &info); ++ mutex_unlock(&audio->write_lock); ++ mutex_unlock(&audio->read_lock); + } + mutex_unlock(&audio->lock); + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8393/0.patch b/Patches/Linux_CVEs/CVE-2016-8393/0.patch new file mode 100644 index 00000000..e2c7abee --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8393/0.patch @@ -0,0 +1,444 @@ +From 9397e20764da2fdffdfe20e35cb78211753b83cc Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Wed, 14 Sep 2016 17:21:48 -0700 +Subject: [PATCH] input: synaptics: prevent sysfs races + +concurrent sysfs calls on the fw updater can cause +ugly race conditions. Return EBUSY on concurrent sysfs calls. + +For sysfs calls which generate deferred work, prevent +the deferred work from running concurrently with other +sysfs calls. + +Change-Id: Ie33add946fbcca8309998e4cb7cb01525c667c7e +Signed-off-by: Andrew Chant +Bug: 31252388 +--- + drivers/input/touchscreen/synaptics_fw_update.c | 144 ++++++++++++++++++------ + 1 file changed, 109 insertions(+), 35 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c +index 79b3a780550b8..ffa992b829a5a 100644 +--- a/drivers/input/touchscreen/synaptics_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_fw_update.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -296,6 +297,7 @@ struct synaptics_rmi4_fwu_handle { + static struct synaptics_rmi4_fwu_handle *fwu; + + DECLARE_COMPLETION(fwu_remove_complete); ++DEFINE_MUTEX(fwu_sysfs_mutex); + + static unsigned int extract_uint(const unsigned char *ptr) + { +@@ -1713,34 +1715,47 @@ static ssize_t fwu_sysfs_show_image(struct file *data_file, + char *buf, loff_t pos, size_t count) + { + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; ++ ssize_t retval; ++ ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + + if (count < fwu->config_size) { + dev_err(&rmi4_data->i2c_client->dev, + "%s: Not enough space (%zu bytes) in buffer\n", + __func__, count); +- return -EINVAL; ++ retval = -EINVAL; ++ goto show_image_exit; + } + + memcpy(buf, fwu->read_config_buf, fwu->config_size); +- +- return fwu->config_size; ++ retval = fwu->config_size; ++show_image_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) + { ++ ssize_t retval; ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (!fwu->ext_data_source) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot use this without setting imagesize!\n"); +- return -EAGAIN; ++ retval = -EAGAIN; ++ goto store_image_exit; + } + + if (count > fwu->image_size - fwu->data_pos) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "%s: Not enough space in buffer\n", + __func__); +- return -EINVAL; ++ retval = -EINVAL; ++ goto store_image_exit; + } + + memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]), +@@ -1749,8 +1764,11 @@ static ssize_t fwu_sysfs_store_image(struct file *data_file, + + fwu->data_buffer = fwu->ext_data_source; + fwu->data_pos += count; ++ retval = count; + +- return count; ++store_image_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_image_name_store(struct device *dev, +@@ -1758,11 +1776,15 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev, + { + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + char *strptr; ++ ssize_t retval; ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + + if (count >= NAME_BUFFER_SIZE) { + dev_err(&rmi4_data->i2c_client->dev, + "Input over %d characters long\n", NAME_BUFFER_SIZE); +- return -EINVAL; ++ retval = -EINVAL; ++ goto image_name_store_exit; + } + + strptr = strnstr(buf, ".img", +@@ -1770,21 +1792,32 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev, + if (!strptr) { + dev_err(&rmi4_data->i2c_client->dev, + "Input is not valid .img file\n"); +- return -EINVAL; ++ retval = -EINVAL; ++ goto image_name_store_exit; + } + + strlcpy(rmi4_data->fw_image_name, buf, count); +- return count; ++ retval = count; ++ ++image_name_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_image_name_show(struct device *dev, + struct device_attribute *attr, char *buf) + { ++ ssize_t retval; ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) > 0) +- return snprintf(buf, PAGE_SIZE, "%s\n", ++ retval = snprintf(buf, PAGE_SIZE, "%s\n", + fwu->rmi4_data->fw_image_name); + else +- return snprintf(buf, PAGE_SIZE, "No firmware name given\n"); ++ retval = snprintf(buf, PAGE_SIZE, "No firmware name given\n"); ++ ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_force_reflash_store(struct device *dev, +@@ -1794,14 +1827,17 @@ static ssize_t fwu_sysfs_force_reflash_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto force_reflash_store_exit; + } + + if (input != 1) { + retval = -EINVAL; +- goto exit; ++ goto force_reflash_store_exit; + } + if (LOCKDOWN) + fwu->do_lockdown = true; +@@ -1812,16 +1848,18 @@ static ssize_t fwu_sysfs_force_reflash_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to do reflash\n", + __func__); +- goto exit; ++ goto force_reflash_store_free_exit; + } + + retval = count; + +-exit: ++force_reflash_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = rmi4_data->board->do_lockdown; ++force_reflash_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -1832,9 +1870,12 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto reflash_store_exit; + } + + if (input & LOCKDOWN) { +@@ -1844,7 +1885,7 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + + if ((input != NORMAL) && (input != FORCE)) { + retval = -EINVAL; +- goto exit; ++ goto reflash_store_exit; + } + + if (input == FORCE) +@@ -1855,16 +1896,18 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to do reflash\n", + __func__); +- goto exit; ++ goto reflash_store_free_exit; + } + + retval = count; + +-exit: ++reflash_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = rmi4_data->board->do_lockdown; ++reflash_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -1875,26 +1918,31 @@ static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto lockdown_store_exit; + } + + if (input != 1) { + retval = -EINVAL; +- goto exit; ++ goto lockdown_store_exit; + } + + if (!fwu->ext_data_source) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot use this without loading image in manual way!\n"); +- return -EAGAIN; ++ retval = -EAGAIN; ++ goto lockdown_store_exit; + } + + if (fwu->rmi4_data->suspended == true) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot lockdown while device is in suspend\n"); +- return -EBUSY; ++ retval = -EBUSY; ++ goto lockdown_store_exit; + } + + retval = fwu_start_write_lockdown(); +@@ -1902,16 +1950,18 @@ static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to write lockdown block\n", + __func__); +- goto exit; ++ goto lockdown_store_free_exit; + } + + retval = count; + +-exit: ++lockdown_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = rmi4_data->board->do_lockdown; ++lockdown_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -1920,6 +1970,8 @@ static ssize_t fwu_sysfs_check_fw_store(struct device *dev, + { + unsigned int input = 0; + ++ /* Takes fwu_sysfs_mutex in the deferred work function. */ ++ + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + +@@ -1942,26 +1994,31 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev, + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; ++ + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; +- goto exit; ++ goto write_config_store_exit; + } + + if (input != 1) { + retval = -EINVAL; +- goto exit; ++ goto write_config_store_exit; + } + + if (!fwu->ext_data_source) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot use this without loading image in manual way!\n"); +- return -EAGAIN; ++ retval = -EAGAIN; ++ goto write_config_store_exit; + } + + if (fwu->rmi4_data->suspended == true) { + dev_err(&fwu->rmi4_data->i2c_client->dev, + "Cannot write config while device is in suspend\n"); +- return -EBUSY; ++ retval = -EBUSY; ++ goto write_config_store_exit; + } + + retval = fwu_start_write_config(); +@@ -1969,14 +2026,16 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to write config\n", + __func__); +- goto exit; ++ goto write_config_store_free_exit; + } + + retval = count; + +-exit: ++write_config_store_free_exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; ++write_config_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); + return retval; + } + +@@ -1999,7 +2058,11 @@ static ssize_t fwu_sysfs_read_config_store(struct device *dev, + return -EBUSY; + } + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + retval = fwu_do_read_config(); ++ mutex_unlock(&fwu_sysfs_mutex); ++ + if (retval < 0) { + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to read config\n", +@@ -2028,7 +2091,10 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev, + return -EINVAL; + } + ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + fwu->config_area = config_area; ++ mutex_unlock(&fwu_sysfs_mutex); + + return count; + } +@@ -2039,10 +2105,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, + int retval; + unsigned long size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; ++ if (!mutex_trylock(&fwu_sysfs_mutex)) ++ return -EBUSY; + + retval = kstrtoul(buf, 10, &size); + if (retval) +- return retval; ++ goto image_size_store_exit; + + fwu->image_size = size; + fwu->data_pos = 0; +@@ -2053,10 +2121,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev, + dev_err(&rmi4_data->i2c_client->dev, + "%s: Failed to alloc mem for image data\n", + __func__); +- return -ENOMEM; ++ retval = -ENOMEM; + } + +- return count; ++image_size_store_exit: ++ mutex_unlock(&fwu_sysfs_mutex); ++ return retval; + } + + static ssize_t fwu_sysfs_block_size_show(struct device *dev, +@@ -2241,6 +2311,8 @@ static void synaptics_rmi4_fwu_work(struct work_struct *work) + container_of(to_delayed_work(work), + struct synaptics_rmi4_fwu_handle, fwu_work); + ++ mutex_lock(&fwu_sysfs_mutex); ++ + if (fwu->fn_ptr->enable) + fwu->fn_ptr->enable(fwu->rmi4_data, false); + +@@ -2248,6 +2320,8 @@ static void synaptics_rmi4_fwu_work(struct work_struct *work) + + if (fwu->fn_ptr->enable) + fwu->fn_ptr->enable(fwu->rmi4_data, true); ++ ++ mutex_unlock(&fwu_sysfs_mutex); + } + + static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) +@@ -2338,7 +2412,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work); + #endif + +- retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, ++ retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, + &dev_attr_data); + if (retval < 0) { + dev_err(&rmi4_data->i2c_client->dev, diff --git a/Patches/Linux_CVEs/CVE-2016-8393/1.patch b/Patches/Linux_CVEs/CVE-2016-8393/1.patch new file mode 100644 index 00000000..1c473612 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8393/1.patch @@ -0,0 +1,61 @@ +From fd11eb5c433743c87bebe699604adfd7e7e805cf Mon Sep 17 00:00:00 2001 +From: Min Chong +Date: Thu, 13 Oct 2016 09:47:01 -0700 +Subject: [PATCH] input: synaptics_dsx: add bounds checks for firmware id + +A series of characters between '0' and '9' with a length more than +MAX_FIRMWARE_ID_LEN causes a heap buffer overflow. This is +mitigated by performing a bounds check. + +Bug: 31911920 +Signed-off-by: Mark Salyzyn +Signed-off-by: Min Chong +Change-Id: Iaefe92df2610153f2d3e2caa58322ae82cb5b7c2 +--- + .../touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 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 908693bd26a43..ff82a4f3a55e8 100755 +--- a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c +@@ -16,6 +16,7 @@ + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ ++#include + #include + #include + #include +@@ -2154,15 +2155,15 @@ static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd) + static int fwu_get_image_firmware_id(unsigned int *fw_id) + { + int retval; +- unsigned char index = 0; +- char *strptr; + char *firmware_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->img.contains_firmware_id) { + *fw_id = fwu->img.firmware_id; + } else { +- strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN); ++ size_t index, max_index; ++ unsigned char *strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN); ++ + if (!strptr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No valid PR number (PRxxxxxxx) " +@@ -2179,7 +2180,11 @@ static int fwu_get_image_firmware_id(unsigned int *fw_id) + __func__); + return -ENOMEM; + } +- while (strptr[index] >= '0' && strptr[index] <= '9') { ++ ++ max_index = min((ptrdiff_t)(MAX_FIRMWARE_ID_LEN - 1), ++ &fwu->image_name[MAX_IMAGE_NAME_LEN] - strptr); ++ index = 0; ++ while (index < max_index && isdigit(strptr[index])) { + firmware_id[index] = strptr[index]; + index++; + } diff --git a/Patches/Linux_CVEs/CVE-2016-8393/2.patch b/Patches/Linux_CVEs/CVE-2016-8393/2.patch new file mode 100644 index 00000000..a3dbbc01 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8393/2.patch @@ -0,0 +1,62 @@ +From 8a950b2d64cec7b8022b7572c2d3d9221b2dbab2 Mon Sep 17 00:00:00 2001 +From: Min Chong +Date: Thu, 13 Oct 2016 09:53:23 -0700 +Subject: [PATCH] input: synaptics_dsx: add bounds checks for firmware id + +A series of characters between '0' and '9' with a length more than +MAX_FIRMWARE_ID_LEN causes a heap buffer overflow. This is +mitigated by performing a bounds check. + +Bug: 31911920 +Signed-off-by: Mark Salyzyn +Signed-off-by: Min Chong +Change-Id: Iaefe92df2610153f2d3e2caa58322ae82cb5b7c2 +--- + .../synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c +index af6f92553aa7e..05f13b427739b 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c +@@ -30,7 +30,7 @@ + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ +- ++#include + #include + #include + #include +@@ -2508,15 +2508,15 @@ static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd) + static int fwu_get_image_firmware_id(unsigned int *fw_id) + { + int retval; +- unsigned char index = 0; +- char *strptr; + char *firmware_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->img.contains_firmware_id) { + *fw_id = fwu->img.firmware_id; + } else { +- strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN); ++ size_t index, max_index; ++ unsigned char *strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN); ++ + if (!strptr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No valid PR number (PRxxxxxxx) found in image file name (%s)\n", +@@ -2532,7 +2532,11 @@ static int fwu_get_image_firmware_id(unsigned int *fw_id) + __func__); + return -ENOMEM; + } +- while (strptr[index] >= '0' && strptr[index] <= '9') { ++ ++ max_index = min((ptrdiff_t)(MAX_FIRMWARE_ID_LEN - 1), ++ &fwu->image_name[MAX_IMAGE_NAME_LEN] - strptr); ++ index = 0; ++ while (index < max_index && isdigit(strptr[index])) { + firmware_id[index] = strptr[index]; + index++; + } diff --git a/Patches/Linux_CVEs/CVE-2016-8394/0.patch b/Patches/Linux_CVEs/CVE-2016-8394/0.patch new file mode 100644 index 00000000..95244d79 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8394/0.patch @@ -0,0 +1,32 @@ +From 4b9ae9048d63ef9fe9f8cc9d0e33cc38148b268d Mon Sep 17 00:00:00 2001 +From: Ariel Yin +Date: Wed, 12 Oct 2016 14:02:14 -0700 +Subject: [PATCH] input: synaptics_dsx: add checks of user input data for image + name + +Add checks of the user input count to avoid possible heap overflow + +Signed-off-by: Min Chong +Change-Id: I1d50a103a0abcbff5eb6bf204607170e9278dec3 +Bug: 31913197 +--- + drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c +index 282e06d9aabaa..1f7409efb1565 100644 +--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c +@@ -1767,6 +1767,12 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) + { + ssize_t retval; ++ if (!buf || count > MAX_IMAGE_NAME_LEN) { ++ dev_err(fwu->rmi4_data->pdev->dev.parent, ++ "%s: Failed to copy image file name\n", ++ __func__); ++ return -EINVAL; ++ } + + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; diff --git a/Patches/Linux_CVEs/CVE-2016-8399/0.patch b/Patches/Linux_CVEs/CVE-2016-8399/0.patch new file mode 100644 index 00000000..23d78a66 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8399/0.patch @@ -0,0 +1,71 @@ +From 0eab121ef8750a5c8637d51534d5e9143fb0633f Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Mon, 5 Dec 2016 10:34:38 -0800 +Subject: net: ping: check minimum size on ICMP header length + +Prior to commit c0371da6047a ("put iov_iter into msghdr") in v3.19, there +was no check that the iovec contained enough bytes for an ICMP header, +and the read loop would walk across neighboring stack contents. Since the +iov_iter conversion, bad arguments are noticed, but the returned error is +EFAULT. Returning EINVAL is a clearer error and also solves the problem +prior to v3.19. + +This was found using trinity with KASAN on v3.18: + +BUG: KASAN: stack-out-of-bounds in memcpy_fromiovec+0x60/0x114 at addr ffffffc071077da0 +Read of size 8 by task trinity-c2/9623 +page:ffffffbe034b9a08 count:0 mapcount:0 mapping: (null) index:0x0 +flags: 0x0() +page dumped because: kasan: bad access detected +CPU: 0 PID: 9623 Comm: trinity-c2 Tainted: G BU 3.18.0-dirty #15 +Hardware name: Google Tegra210 Smaug Rev 1,3+ (DT) +Call trace: +[] dump_backtrace+0x0/0x1ac arch/arm64/kernel/traps.c:90 +[] show_stack+0x10/0x1c arch/arm64/kernel/traps.c:171 +[< inline >] __dump_stack lib/dump_stack.c:15 +[] dump_stack+0x7c/0xd0 lib/dump_stack.c:50 +[< inline >] print_address_description mm/kasan/report.c:147 +[< inline >] kasan_report_error mm/kasan/report.c:236 +[] kasan_report+0x380/0x4b8 mm/kasan/report.c:259 +[< inline >] check_memory_region mm/kasan/kasan.c:264 +[] __asan_load8+0x20/0x70 mm/kasan/kasan.c:507 +[] memcpy_fromiovec+0x5c/0x114 lib/iovec.c:15 +[< inline >] memcpy_from_msg include/linux/skbuff.h:2667 +[] ping_common_sendmsg+0x50/0x108 net/ipv4/ping.c:674 +[] ping_v4_sendmsg+0xd8/0x698 net/ipv4/ping.c:714 +[] inet_sendmsg+0xe0/0x12c net/ipv4/af_inet.c:749 +[< inline >] __sock_sendmsg_nosec net/socket.c:624 +[< inline >] __sock_sendmsg net/socket.c:632 +[] sock_sendmsg+0x124/0x164 net/socket.c:643 +[< inline >] SYSC_sendto net/socket.c:1797 +[] SyS_sendto+0x178/0x1d8 net/socket.c:1761 + +CVE-2016-8399 + +Reported-by: Qidan He +Fixes: c319b4d76b9e ("net: ipv4: add IPPROTO_ICMP socket kind") +Cc: stable@vger.kernel.org +Signed-off-by: Kees Cook +Signed-off-by: David S. Miller +--- + net/ipv4/ping.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 205e200..96b8e2b 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -657,6 +657,10 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + if (len > 0xFFFF) + return -EMSGSIZE; + ++ /* Must have at least a full ICMP header. */ ++ if (len < icmph_len) ++ return -EINVAL; ++ + /* + * Check the flags. + */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8399/1.patch b/Patches/Linux_CVEs/CVE-2016-8399/1.patch new file mode 100644 index 00000000..cc01cda4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8399/1.patch @@ -0,0 +1,64 @@ +From a1b9bc540f4af79bd23e01ec08429e0efa4d2f7b Mon Sep 17 00:00:00 2001 +From: Qidan He +Date: Thu, 13 Oct 2016 16:27:46 -0700 +Subject: [PATCH] net: ping: Fix stack buffer overflow in ping_common_sendmsg() + +In ping_common_sendmsg(), when len < icmph_len, memcpy_fromiovec() +will access invalid memory because msg->msg_iov only has 1 element +and memcpy_fromiovec() attempts to increment it. KASAN report: + +BUG: KASAN: stack-out-of-bounds in memcpy_fromiovec+0x60/0x114 at addr ffffffc071077da0 +Read of size 8 by task trinity-c2/9623 +page:ffffffbe034b9a08 count:0 mapcount:0 mapping: (null) index:0x0 +flags: 0x0() +page dumped because: kasan: bad access detected +CPU: 0 PID: 9623 Comm: trinity-c2 Tainted: G BU 3.18.0-dirty #15 +Hardware name: Google Tegra210 Smaug Rev 1,3+ (DT) +Call trace: +[] dump_backtrace+0x0/0x1ac arch/arm64/kernel/traps.c:90 +[] show_stack+0x10/0x1c arch/arm64/kernel/traps.c:171 +[< inline >] __dump_stack lib/dump_stack.c:15 +[] dump_stack+0x7c/0xd0 lib/dump_stack.c:50 +[< inline >] print_address_description mm/kasan/report.c:147 +[< inline >] kasan_report_error mm/kasan/report.c:236 +[] kasan_report+0x380/0x4b8 mm/kasan/report.c:259 +[< inline >] check_memory_region mm/kasan/kasan.c:264 +[] __asan_load8+0x20/0x70 mm/kasan/kasan.c:507 +[] memcpy_fromiovec+0x5c/0x114 lib/iovec.c:15 +[< inline >] memcpy_from_msg include/linux/skbuff.h:2667 +[] ping_common_sendmsg+0x50/0x108 net/ipv4/ping.c:674 +[] ping_v4_sendmsg+0xd8/0x698 net/ipv4/ping.c:714 +[] inet_sendmsg+0xe0/0x12c net/ipv4/af_inet.c:749 +[< inline >] __sock_sendmsg_nosec net/socket.c:624 +[< inline >] __sock_sendmsg net/socket.c:632 +[] sock_sendmsg+0x124/0x164 net/socket.c:643 +[< inline >] SYSC_sendto net/socket.c:1797 +[] SyS_sendto+0x178/0x1d8 net/socket.c:1761 +Memory state around the buggy address: + ffffffc071077c80: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 f1 f1 + ffffffc071077d00: f1 f1 04 f4 f4 f4 f2 f2 f2 f2 04 f4 f4 f4 f2 f2 +>ffffffc071077d80: f2 f2 00 00 f4 f4 f2 f2 f2 f2 00 00 00 00 00 00 + ^ + ffffffc071077e00: 00 f4 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00 00 + ffffffc071077e80: 00 00 00 00 00 00 f3 f3 f3 f3 00 00 00 00 00 00 + +Bug: 31349935 +Change-Id: Ib7385fc26dfe7e07e9bab42a10ff65a37cbaab54 +Signed-off-by: Siqi Lin +--- + net/ipv4/ping.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index f8c8f60ad7e25..aaa70dd666674 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -651,7 +651,7 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len) { + u8 type, code; + +- if (len > 0xFFFF) ++ if (len > 0xFFFF || len < icmph_len) + return -EMSGSIZE; + + /* diff --git a/Patches/Linux_CVEs/CVE-2016-8401/0.patch b/Patches/Linux_CVEs/CVE-2016-8401/0.patch new file mode 100644 index 00000000..d04d8b5d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8401/0.patch @@ -0,0 +1,42 @@ +From 44a8e527e156245eff04ff36f426cb1ba8d23e34 Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Fri, 7 Oct 2016 11:51:15 -0700 +Subject: [PATCH] ion: blacklist %p kptr_restrict + +Bug: 31494725 +Change-Id: I10a0c2aae883dfaa6c235c38689a704064557008 +--- + drivers/staging/android/ion/ion.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c +index a215fd4a5c411..0a5522d308c74 100755 +--- a/drivers/staging/android/ion/ion.c ++++ b/drivers/staging/android/ion/ion.c +@@ -803,7 +803,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) + struct ion_handle *handle = rb_entry(n, struct ion_handle, + node); + +- seq_printf(s, "%16.16s: %16zx : %16d : %12p", ++ seq_printf(s, "%16.16s: %16zx : %16d : %12pK", + handle->buffer->heap->name, + handle->buffer->size, + atomic_read(&handle->ref.refcount), +@@ -1159,7 +1159,7 @@ static void ion_vm_open(struct vm_area_struct *vma) + mutex_lock(&buffer->lock); + list_add(&vma_list->list, &buffer->vmas); + mutex_unlock(&buffer->lock); +- pr_debug("%s: adding %p\n", __func__, vma); ++ pr_debug("%s: adding %pK\n", __func__, vma); + } + + static void ion_vm_close(struct vm_area_struct *vma) +@@ -1174,7 +1174,7 @@ static void ion_vm_close(struct vm_area_struct *vma) + continue; + list_del(&vma_list->list); + kfree(vma_list); +- pr_debug("%s: deleting %p\n", __func__, vma); ++ pr_debug("%s: deleting %pK\n", __func__, vma); + break; + } + mutex_unlock(&buffer->lock); diff --git a/Patches/Linux_CVEs/CVE-2016-8402/0.patch b/Patches/Linux_CVEs/CVE-2016-8402/0.patch new file mode 100644 index 00000000..d91bcad3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8402/0.patch @@ -0,0 +1,176 @@ +From de51c6f363b8ba7c513e8a5bbae3459571966bfd Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Fri, 7 Oct 2016 11:13:55 -0700 +Subject: [PATCH] binder: blacklist %p kptr_restrict + +Bug: 31495231 +Change-Id: Iebc150f6bc939b56e021424ee44fb30ce8d732fd +--- + drivers/staging/android/binder.c | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c +index 8c9945d071476..7340ef74433a5 100644 +--- a/drivers/staging/android/binder.c ++++ b/drivers/staging/android/binder.c +@@ -534,7 +534,7 @@ static void binder_insert_free_buffer(struct binder_proc *proc, + new_buffer_size = binder_buffer_size(proc, new_buffer); + + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: add free buffer, size %zd, at %p\n", ++ "%d: add free buffer, size %zd, at %pK\n", + proc->pid, new_buffer_size, new_buffer); + + while (*p) { +@@ -613,7 +613,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, + struct mm_struct *mm; + + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: %s pages %p-%p\n", proc->pid, ++ "%d: %s pages %pK-%pK\n", proc->pid, + allocate ? "allocate" : "free", start, end); + + if (end <= start) +@@ -655,7 +655,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, + BUG_ON(*page); + *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); + if (*page == NULL) { +- pr_err("%d: binder_alloc_buf failed for page at %p\n", ++ pr_err("%d: binder_alloc_buf failed for page at %pK\n", + proc->pid, page_addr); + goto err_alloc_page_failed; + } +@@ -664,7 +664,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, + page_array_ptr = page; + ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr); + if (ret) { +- pr_err("%d: binder_alloc_buf failed to map page at %p in kernel\n", ++ pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n", + proc->pid, page_addr); + goto err_map_kernel_failed; + } +@@ -774,7 +774,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, + } + + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: binder_alloc_buf size %zd got buffer %p size %zd\n", ++ "%d: binder_alloc_buf size %zd got buffer %pK size %zd\n", + proc->pid, size, buffer, buffer_size); + + has_page_addr = +@@ -803,7 +803,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, + binder_insert_free_buffer(proc, new_buffer); + } + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: binder_alloc_buf size %zd got %p\n", ++ "%d: binder_alloc_buf size %zd got %pK\n", + proc->pid, size, buffer); + buffer->data_size = data_size; + buffer->offsets_size = offsets_size; +@@ -843,7 +843,7 @@ static void binder_delete_free_buffer(struct binder_proc *proc, + if (buffer_end_page(prev) == buffer_end_page(buffer)) + free_page_end = 0; + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: merge free, buffer %p share page with %p\n", ++ "%d: merge free, buffer %pK share page with %pK\n", + proc->pid, buffer, prev); + } + +@@ -856,14 +856,14 @@ static void binder_delete_free_buffer(struct binder_proc *proc, + buffer_start_page(buffer)) + free_page_start = 0; + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: merge free, buffer %p share page with %p\n", ++ "%d: merge free, buffer %pK share page with %pK\n", + proc->pid, buffer, prev); + } + } + list_del(&buffer->entry); + if (free_page_start || free_page_end) { + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: merge free, buffer %p do not share page%s%s with %p or %p\n", ++ "%d: merge free, buffer %pK do not share page%s%s with %pK or %pK\n", + proc->pid, buffer, free_page_start ? "" : " end", + free_page_end ? "" : " start", prev, next); + binder_update_page_range(proc, 0, free_page_start ? +@@ -884,7 +884,7 @@ static void binder_free_buf(struct binder_proc *proc, + ALIGN(buffer->offsets_size, sizeof(void *)); + + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%d: binder_free_buf %p size %zd buffer_size %zd\n", ++ "%d: binder_free_buf %pK size %zd buffer_size %zd\n", + proc->pid, buffer, size, buffer_size); + + BUG_ON(buffer->free); +@@ -1311,7 +1311,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, + int debug_id = buffer->debug_id; + + binder_debug(BINDER_DEBUG_TRANSACTION, +- "%d buffer release %d, size %zd-%zd, failed at %p\n", ++ "%d buffer release %d, size %zd-%zd, failed at %pK\n", + proc->pid, buffer->debug_id, + buffer->data_size, buffer->offsets_size, failed_at); + +@@ -2159,7 +2159,7 @@ static int binder_thread_write(struct binder_proc *proc, + } + } + binder_debug(BINDER_DEBUG_DEAD_BINDER, +- "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", ++ "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n", + proc->pid, thread->pid, (u64)cookie, death); + if (death == NULL) { + binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n", +@@ -2907,7 +2907,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) + #ifdef CONFIG_CPU_CACHE_VIPT + if (cache_is_vipt_aliasing()) { + while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) { +- pr_info("binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); ++ pr_info("binder_mmap: %d %lx-%lx maps %pK bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); + vma->vm_start += PAGE_SIZE; + } + } +@@ -2943,7 +2943,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) + proc->vma = vma; + proc->vma_vm_mm = vma->vm_mm; + +- /*pr_info("binder_mmap: %d %lx-%lx maps %p\n", ++ /*pr_info("binder_mmap: %d %lx-%lx maps %pK\n", + proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ + return 0; + +@@ -3165,7 +3165,7 @@ static void binder_deferred_release(struct binder_proc *proc) + + page_addr = proc->buffer + i * PAGE_SIZE; + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "%s: %d: page %d at %p not freed\n", ++ "%s: %d: page %d at %pK not freed\n", + __func__, proc->pid, i, page_addr); + unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); + __free_page(proc->pages[i]); +@@ -3249,7 +3249,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, + struct binder_transaction *t) + { + seq_printf(m, +- "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d", ++ "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d", + prefix, t->debug_id, t, + t->from ? t->from->proc->pid : 0, + t->from ? t->from->pid : 0, +@@ -3263,7 +3263,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, + if (t->buffer->target_node) + seq_printf(m, " node %d", + t->buffer->target_node->debug_id); +- seq_printf(m, " size %zd:%zd data %p\n", ++ seq_printf(m, " size %zd:%zd data %pK\n", + t->buffer->data_size, t->buffer->offsets_size, + t->buffer->data); + } +@@ -3271,7 +3271,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, + static void print_binder_buffer(struct seq_file *m, const char *prefix, + struct binder_buffer *buffer) + { +- seq_printf(m, "%s %d: %p size %zd:%zd %s\n", ++ seq_printf(m, "%s %d: %pK size %zd:%zd %s\n", + prefix, buffer->debug_id, buffer->data, + buffer->data_size, buffer->offsets_size, + buffer->transaction ? "active" : "delivered"); diff --git a/Patches/Linux_CVEs/CVE-2016-8402/1.patch b/Patches/Linux_CVEs/CVE-2016-8402/1.patch new file mode 100644 index 00000000..c8e6de21 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8402/1.patch @@ -0,0 +1,394 @@ +From 8e145d45fdff30cb6471b7cc9717c30b21a0ec6b Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Thu, 16 Feb 2017 18:59:44 +0530 +Subject: binder: blacklist %p kptr_restrict + +Bug: 31495231 +Change-Id: Iebc150f6bc939b56e021424ee44fb30ce8d732fd +Git-repo: https://android.googlesource.com/kernel/msm +Git-commit: 0804d7840364fc1a93652632bd43a93c055c658e +Signed-off-by: Rahul Sharma +--- + drivers/staging/android/binder.c | 92 ++++++++++++++++++++-------------------- + 1 file changed, 46 insertions(+), 46 deletions(-) + +(limited to 'drivers') + +diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c +index 38d47e7..5ae7c13 100644 +--- a/drivers/staging/android/binder.c ++++ b/drivers/staging/android/binder.c +@@ -556,7 +556,7 @@ static void binder_insert_free_buffer(struct binder_proc *proc, + + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, + "binder: %d: add free buffer, size %zd, " +- "at %p\n", proc->pid, new_buffer_size, new_buffer); ++ "at %pK\n", proc->pid, new_buffer_size, new_buffer); + + while (*p) { + parent = *p; +@@ -634,7 +634,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, + struct mm_struct *mm; + + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "binder: %d: %s pages %p-%p\n", proc->pid, ++ "binder: %d: %s pages %pK-%pK\n", proc->pid, + allocate ? "allocate" : "free", start, end); + + if (end <= start) +@@ -675,7 +675,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, + *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); + if (*page == NULL) { + printk(KERN_ERR "binder: %d: binder_alloc_buf failed " +- "for page at %p\n", proc->pid, page_addr); ++ "for page at %pK\n", proc->pid, page_addr); + goto err_alloc_page_failed; + } + tmp_area.addr = page_addr; +@@ -684,7 +684,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, + ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr); + if (ret) { + printk(KERN_ERR "binder: %d: binder_alloc_buf failed " +- "to map page at %p in kernel\n", ++ "to map page at %pK in kernel\n", + proc->pid, page_addr); + goto err_map_kernel_failed; + } +@@ -790,7 +790,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, + + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, + "binder: %d: binder_alloc_buf size %zd got buff" +- "er %p size %zd\n", proc->pid, size, buffer, buffer_size); ++ "er %pK size %zd\n", proc->pid, size, buffer, buffer_size); + + has_page_addr = + (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK); +@@ -819,7 +819,7 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc, + } + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, + "binder: %d: binder_alloc_buf size %zd got " +- "%p\n", proc->pid, size, buffer); ++ "%pK\n", proc->pid, size, buffer); + buffer->data_size = data_size; + buffer->offsets_size = offsets_size; + buffer->async_transaction = is_async; +@@ -859,8 +859,8 @@ static void binder_delete_free_buffer(struct binder_proc *proc, + if (buffer_end_page(prev) == buffer_end_page(buffer)) + free_page_end = 0; + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "binder: %d: merge free, buffer %p " +- "share page with %p\n", proc->pid, buffer, prev); ++ "binder: %d: merge free, buffer %pK " ++ "share page with %pK\n", proc->pid, buffer, prev); + } + + if (!list_is_last(&buffer->entry, &proc->buffers)) { +@@ -873,15 +873,15 @@ static void binder_delete_free_buffer(struct binder_proc *proc, + free_page_start = 0; + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, + "binder: %d: merge free, buffer" +- " %p share page with %p\n", proc->pid, ++ " %pK share page with %pK\n", proc->pid, + buffer, prev); + } + } + list_del(&buffer->entry); + if (free_page_start || free_page_end) { + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "binder: %d: merge free, buffer %p do " +- "not share page%s%s with with %p or %p\n", ++ "binder: %d: merge free, buffer %pK do " ++ "not share page%s%s with with %pK or %pK\n", + proc->pid, buffer, free_page_start ? "" : " end", + free_page_end ? "" : " start", prev, next); + binder_update_page_range(proc, 0, free_page_start ? +@@ -902,7 +902,7 @@ static void binder_free_buf(struct binder_proc *proc, + ALIGN(buffer->offsets_size, sizeof(void *)); + + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, +- "binder: %d: binder_free_buf %p size %zd buffer" ++ "binder: %d: binder_free_buf %pK size %zd buffer" + "_size %zd\n", proc->pid, buffer, size, buffer_size); + + BUG_ON(buffer->free); +@@ -999,7 +999,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, + INIT_LIST_HEAD(&node->work.entry); + INIT_LIST_HEAD(&node->async_todo); + binder_debug(BINDER_DEBUG_INTERNAL_REFS, +- "binder: %d:%d node %d u%p c%p created\n", ++ "binder: %d:%d node %d u%pK c%pK created\n", + proc->pid, current->pid, node->debug_id, + node->ptr, node->cookie); + return node; +@@ -1335,7 +1335,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, + int debug_id = buffer->debug_id; + + binder_debug(BINDER_DEBUG_TRANSACTION, +- "binder: %d buffer release %d, size %zd-%zd, failed at %p\n", ++ "binder: %d buffer release %d, size %zd-%zd, failed at %pK\n", + proc->pid, buffer->debug_id, + buffer->data_size, buffer->offsets_size, failed_at); + +@@ -1364,11 +1364,11 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, + struct binder_node *node = binder_get_node(proc, fp->binder); + if (node == NULL) { + printk(KERN_ERR "binder: transaction release %d" +- " bad node %p\n", debug_id, fp->binder); ++ " bad node %pK\n", debug_id, fp->binder); + break; + } + binder_debug(BINDER_DEBUG_TRANSACTION, +- " node %d u%p\n", ++ " node %d u%pK\n", + node->debug_id, node->ptr); + binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0); + } break; +@@ -1552,7 +1552,7 @@ static void binder_transaction(struct binder_proc *proc, + if (reply) + binder_debug(BINDER_DEBUG_TRANSACTION, + "binder: %d:%d BC_REPLY %d -> %d:%d, " +- "data %p-%p size %zd-%zd\n", ++ "data %pK-%pK size %zd-%zd\n", + proc->pid, thread->pid, t->debug_id, + target_proc->pid, target_thread->pid, + tr->data.ptr.buffer, tr->data.ptr.offsets, +@@ -1560,7 +1560,7 @@ static void binder_transaction(struct binder_proc *proc, + else + binder_debug(BINDER_DEBUG_TRANSACTION, + "binder: %d:%d BC_TRANSACTION %d -> " +- "%d - node %d, data %p-%p size %zd-%zd\n", ++ "%d - node %d, data %pK-%pK size %zd-%zd\n", + proc->pid, thread->pid, t->debug_id, + target_proc->pid, target_node->debug_id, + tr->data.ptr.buffer, tr->data.ptr.offsets, +@@ -1647,8 +1647,8 @@ static void binder_transaction(struct binder_proc *proc, + node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); + } + if (fp->cookie != node->cookie) { +- binder_user_error("binder: %d:%d sending u%p " +- "node %d, cookie mismatch %p != %p\n", ++ binder_user_error("binder: %d:%d sending u%pK " ++ "node %d, cookie mismatch %pK != %pK\n", + proc->pid, thread->pid, + fp->binder, node->debug_id, + fp->cookie, node->cookie); +@@ -1675,7 +1675,7 @@ static void binder_transaction(struct binder_proc *proc, + + trace_binder_transaction_node_to_ref(t, node, ref); + binder_debug(BINDER_DEBUG_TRANSACTION, +- " node %d u%p -> ref %d desc %d\n", ++ " node %d u%pK -> ref %d desc %d\n", + node->debug_id, node->ptr, ref->debug_id, + ref->desc); + } break; +@@ -1705,7 +1705,7 @@ static void binder_transaction(struct binder_proc *proc, + binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL); + trace_binder_transaction_ref_to_node(t, ref); + binder_debug(BINDER_DEBUG_TRANSACTION, +- " ref %d desc %d -> node %d u%p\n", ++ " ref %d desc %d -> node %d u%pK\n", + ref->debug_id, ref->desc, ref->node->debug_id, + ref->node->ptr); + } else { +@@ -1941,7 +1941,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, + node = binder_get_node(proc, node_ptr); + if (node == NULL) { + binder_user_error("binder: %d:%d " +- "%s u%p no match\n", ++ "%s u%pK no match\n", + proc->pid, thread->pid, + cmd == BC_INCREFS_DONE ? + "BC_INCREFS_DONE" : +@@ -1950,8 +1950,8 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, + break; + } + if (cookie != node->cookie) { +- binder_user_error("binder: %d:%d %s u%p node %d" +- " cookie mismatch %p != %p\n", ++ binder_user_error("binder: %d:%d %s u%pK node %d" ++ " cookie mismatch %pK != %pK\n", + proc->pid, thread->pid, + cmd == BC_INCREFS_DONE ? + "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", +@@ -2006,19 +2006,19 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, + buffer = binder_buffer_lookup(proc, data_ptr); + if (buffer == NULL) { + binder_user_error("binder: %d:%d " +- "BC_FREE_BUFFER u%p no match\n", ++ "BC_FREE_BUFFER u%pK no match\n", + proc->pid, thread->pid, data_ptr); + break; + } + if (!buffer->allow_user_free) { + binder_user_error("binder: %d:%d " +- "BC_FREE_BUFFER u%p matched " ++ "BC_FREE_BUFFER u%pK matched " + "unreturned buffer\n", + proc->pid, thread->pid, data_ptr); + break; + } + binder_debug(BINDER_DEBUG_FREE_BUFFER, +- "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n", ++ "binder: %d:%d BC_FREE_BUFFER u%pK found buffer %d for %s transaction\n", + proc->pid, thread->pid, data_ptr, buffer->debug_id, + buffer->transaction ? "active" : "finished"); + +@@ -2118,7 +2118,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, + } + + binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, +- "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n", ++ "binder: %d:%d %s %pK ref %d desc %d s %d w %d for node %d\n", + proc->pid, thread->pid, + cmd == BC_REQUEST_DEATH_NOTIFICATION ? + "BC_REQUEST_DEATH_NOTIFICATION" : +@@ -2172,7 +2172,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, + "d BC_CLEAR_DEATH_NOTIFI" + "CATION death notificat" + "ion cookie mismatch " +- "%p != %p\n", ++ "%pK != %pK\n", + proc->pid, thread->pid, + death->cookie, cookie); + break; +@@ -2208,11 +2208,11 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, + } + } + binder_debug(BINDER_DEBUG_DEAD_BINDER, +- "binder: %d:%d BC_DEAD_BINDER_DONE %p found %p\n", ++ "binder: %d:%d BC_DEAD_BINDER_DONE %pK found %pK\n", + proc->pid, thread->pid, cookie, death); + if (death == NULL) { + binder_user_error("binder: %d:%d BC_DEAD" +- "_BINDER_DONE %p not found\n", ++ "_BINDER_DONE %pK not found\n", + proc->pid, thread->pid, cookie); + break; + } +@@ -2423,13 +2423,13 @@ retry: + + binder_stat_br(proc, thread, cmd); + binder_debug(BINDER_DEBUG_USER_REFS, +- "binder: %d:%d %s %d u%p c%p\n", ++ "binder: %d:%d %s %d u%pK c%pK\n", + proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie); + } else { + list_del_init(&w->entry); + if (!weak && !strong) { + binder_debug(BINDER_DEBUG_INTERNAL_REFS, +- "binder: %d:%d node %d u%p c%p deleted\n", ++ "binder: %d:%d node %d u%pK c%pK deleted\n", + proc->pid, thread->pid, node->debug_id, + node->ptr, node->cookie); + rb_erase(&node->rb_node, &proc->nodes); +@@ -2437,7 +2437,7 @@ retry: + binder_stats_deleted(BINDER_STAT_NODE); + } else { + binder_debug(BINDER_DEBUG_INTERNAL_REFS, +- "binder: %d:%d node %d u%p c%p state unchanged\n", ++ "binder: %d:%d node %d u%pK c%pK state unchanged\n", + proc->pid, thread->pid, node->debug_id, node->ptr, + node->cookie); + } +@@ -2462,7 +2462,7 @@ retry: + ptr += sizeof(void *); + binder_stat_br(proc, thread, cmd); + binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, +- "binder: %d:%d %s %p\n", ++ "binder: %d:%d %s %pK\n", + proc->pid, thread->pid, + cmd == BR_DEAD_BINDER ? + "BR_DEAD_BINDER" : +@@ -2532,7 +2532,7 @@ retry: + binder_stat_br(proc, thread, cmd); + binder_debug(BINDER_DEBUG_TRANSACTION, + "binder: %d:%d %s %d %d:%d, cmd %d" +- "size %zd-%zd ptr %p-%p\n", ++ "size %zd-%zd ptr %pK-%pK\n", + proc->pid, thread->pid, + (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : + "BR_REPLY", +@@ -2609,7 +2609,7 @@ static void binder_release_work(struct list_head *list) + + death = container_of(w, struct binder_ref_death, work); + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, +- "binder: undelivered death notification, %p\n", ++ "binder: undelivered death notification, %pK\n", + death->cookie); + kfree(death); + binder_stats_deleted(BINDER_STAT_DEATH); +@@ -2942,7 +2942,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) + #ifdef CONFIG_CPU_CACHE_VIPT + if (cache_is_vipt_aliasing()) { + while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) { +- printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); ++ printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %pK bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer); + vma->vm_start += PAGE_SIZE; + } + } +@@ -2974,7 +2974,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) + proc->vma = vma; + proc->vma_vm_mm = vma->vm_mm; + +- /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", ++ /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %pK\n", + proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/ + return 0; + +@@ -3168,7 +3168,7 @@ static void binder_deferred_release(struct binder_proc *proc) + void *page_addr = proc->buffer + i * PAGE_SIZE; + binder_debug(BINDER_DEBUG_BUFFER_ALLOC, + "binder_release: %d: " +- "page %d at %p not freed\n", ++ "page %d at %pK not freed\n", + proc->pid, i, + page_addr); + unmap_kernel_range((unsigned long)page_addr, +@@ -3251,7 +3251,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, + struct binder_transaction *t) + { + seq_printf(m, +- "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d", ++ "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d", + prefix, t->debug_id, t, + t->from ? t->from->proc->pid : 0, + t->from ? t->from->pid : 0, +@@ -3265,7 +3265,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, + if (t->buffer->target_node) + seq_printf(m, " node %d", + t->buffer->target_node->debug_id); +- seq_printf(m, " size %zd:%zd data %p\n", ++ seq_printf(m, " size %zd:%zd data %pK\n", + t->buffer->data_size, t->buffer->offsets_size, + t->buffer->data); + } +@@ -3273,7 +3273,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix, + static void print_binder_buffer(struct seq_file *m, const char *prefix, + struct binder_buffer *buffer) + { +- seq_printf(m, "%s %d: %p size %zd:%zd %s\n", ++ seq_printf(m, "%s %d: %pK size %zd:%zd %s\n", + prefix, buffer->debug_id, buffer->data, + buffer->data_size, buffer->offsets_size, + buffer->transaction ? "active" : "delivered"); +@@ -3296,7 +3296,7 @@ static void print_binder_work(struct seq_file *m, const char *prefix, + break; + case BINDER_WORK_NODE: + node = container_of(w, struct binder_node, work); +- seq_printf(m, "%snode work %d: u%p c%p\n", ++ seq_printf(m, "%snode work %d: u%pK c%pK\n", + prefix, node->debug_id, node->ptr, node->cookie); + break; + case BINDER_WORK_DEAD_BINDER: +@@ -3358,7 +3358,7 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) + hlist_for_each_entry(ref, pos, &node->refs, node_entry) + count++; + +- seq_printf(m, " node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d", ++ seq_printf(m, " node %d: u%pK c%pK hs %d hw %d ls %d lw %d is %d iw %d", + node->debug_id, node->ptr, node->cookie, + node->has_strong_ref, node->has_weak_ref, + node->local_strong_refs, node->local_weak_refs, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8404/0.patch b/Patches/Linux_CVEs/CVE-2016-8404/0.patch new file mode 100644 index 00000000..e5256268 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8404/0.patch @@ -0,0 +1,32 @@ +From 232ec805c7cc4150f05aa06a98335378ab272ec7 Mon Sep 17 00:00:00 2001 +From: chengengjia +Date: Wed, 14 Sep 2016 14:10:56 +0800 +Subject: usb: diag: prevent showing the address of kernel variable 'port' + +The format specifier %p can leak kernel address while not valuing the kptr_strict system settings. +The fix is designed to use %pK instead of %p, which also evaluates whether kptr_restrict is set. + +Signed-off-by: chengengjia +Test: compile +Bug: 31496950 +Change-Id: Ib93c0defdd68f4afe46b5a818ce4d1a2b850cf46 +--- + drivers/usb/gadget/u_ctrl_hsic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/u_ctrl_hsic.c b/drivers/usb/gadget/u_ctrl_hsic.c +index ff3fbf3..1c5f160 100644 +--- a/drivers/usb/gadget/u_ctrl_hsic.c ++++ b/drivers/usb/gadget/u_ctrl_hsic.c +@@ -557,7 +557,7 @@ static ssize_t gctrl_read_stats(struct file *file, char __user *ubuf, + + temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp, + "\nName: %s\n" +- "#PORT:%d port: %p\n" ++ "#PORT:%d port: %pK\n" + "to_usbhost: %lu\n" + "to_modem: %lu\n" + "cpkt_drp_cnt: %lu\n" +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8405/0.patch b/Patches/Linux_CVEs/CVE-2016-8405/0.patch new file mode 100644 index 00000000..a1219b3b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8405/0.patch @@ -0,0 +1,82 @@ +From 2dc705a9930b4806250fbf5a76e55266e59389f2 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Tue, 24 Jan 2017 15:18:24 -0800 +Subject: fbdev: color map copying bounds checking + +Copying color maps to userspace doesn't check the value of to->start, +which will cause kernel heap buffer OOB read due to signedness wraps. + +CVE-2016-8405 + +Link: http://lkml.kernel.org/r/20170105224249.GA50925@beast +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Kees Cook +Reported-by: Peter Pi (@heisecode) of Trend Micro +Cc: Min Chong +Cc: Dan Carpenter +Cc: Tomi Valkeinen +Cc: Bartlomiej Zolnierkiewicz +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + drivers/video/fbdev/core/fbcmap.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c +index f89245b..68a1135 100644 +--- a/drivers/video/fbdev/core/fbcmap.c ++++ b/drivers/video/fbdev/core/fbcmap.c +@@ -163,17 +163,18 @@ void fb_dealloc_cmap(struct fb_cmap *cmap) + + int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to) + { +- int tooff = 0, fromoff = 0; +- int size; ++ unsigned int tooff = 0, fromoff = 0; ++ size_t size; + + if (to->start > from->start) + fromoff = to->start - from->start; + else + tooff = from->start - to->start; +- size = to->len - tooff; +- if (size > (int) (from->len - fromoff)) +- size = from->len - fromoff; +- if (size <= 0) ++ if (fromoff >= from->len || tooff >= to->len) ++ return -EINVAL; ++ ++ size = min_t(size_t, to->len - tooff, from->len - fromoff); ++ if (size == 0) + return -EINVAL; + size *= sizeof(u16); + +@@ -187,17 +188,18 @@ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to) + + int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to) + { +- int tooff = 0, fromoff = 0; +- int size; ++ unsigned int tooff = 0, fromoff = 0; ++ size_t size; + + if (to->start > from->start) + fromoff = to->start - from->start; + else + tooff = from->start - to->start; +- size = to->len - tooff; +- if (size > (int) (from->len - fromoff)) +- size = from->len - fromoff; +- if (size <= 0) ++ if (fromoff >= from->len || tooff >= to->len) ++ return -EINVAL; ++ ++ size = min_t(size_t, to->len - tooff, from->len - fromoff); ++ if (size == 0) + return -EINVAL; + size *= sizeof(u16); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8406/0.patch b/Patches/Linux_CVEs/CVE-2016-8406/0.patch new file mode 100644 index 00000000..1ef84511 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8406/0.patch @@ -0,0 +1,102 @@ +From d7a15270ad80aff21d09aaea9c0e98e03e541b50 Mon Sep 17 00:00:00 2001 +From: Min Chong +Date: Thu, 13 Oct 2016 17:15:35 -0700 +Subject: [PATCH] netfilter: Change %p to %pK in debug messages + +The format specifier %p can leak kernel addresses +while not valuing the kptr_restrict system settings. +Use %pK instead of %p, which also evaluates whether +kptr_restrict is set. + +Bug: 31796940 +Change-Id: Ia2946d6b493126d68281f97778faf578247f088e +Signed-off-by: Min Chong +--- + net/netfilter/nf_conntrack_core.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c +index 1c118edd4b794..d9b86c2e96e24 100644 +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -188,7 +188,7 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple); + static void + clean_from_lists(struct nf_conn *ct) + { +- pr_debug("clean_from_lists(%p)\n", ct); ++ pr_debug("clean_from_lists(%pK)\n", ct); + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); + hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode); + +@@ -203,7 +203,7 @@ destroy_conntrack(struct nf_conntrack *nfct) + struct net *net = nf_ct_net(ct); + struct nf_conntrack_l4proto *l4proto; + +- pr_debug("destroy_conntrack(%p)\n", ct); ++ pr_debug("destroy_conntrack(%pK)\n", ct); + NF_CT_ASSERT(atomic_read(&nfct->use) == 0); + NF_CT_ASSERT(!timer_pending(&ct->timeout)); + +@@ -234,7 +234,7 @@ destroy_conntrack(struct nf_conntrack *nfct) + if (ct->master) + nf_ct_put(ct->master); + +- pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct); ++ pr_debug("destroy_conntrack: returning ct=%pK to slab\n", ct); + nf_conntrack_free(ct); + } + +@@ -496,7 +496,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) + /* No external references means no one else could have + confirmed us. */ + NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); +- pr_debug("Confirming conntrack %p\n", ct); ++ pr_debug("Confirming conntrack %pK\n", ct); + + spin_lock_bh(&nf_conntrack_lock); + +@@ -826,7 +826,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, + spin_lock_bh(&nf_conntrack_lock); + exp = nf_ct_find_expectation(net, zone, tuple); + if (exp) { +- pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", ++ pr_debug("conntrack: expectation arrives ct=%pK exp=%pK\n", + ct, exp); + /* Welcome, Mr. Bond. We've been expecting you... */ + __set_bit(IPS_EXPECTED_BIT, &ct->status); +@@ -916,14 +916,14 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, + } else { + /* Once we've had two way comms, always ESTABLISHED. */ + if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { +- pr_debug("nf_conntrack_in: normal packet for %p\n", ct); ++ pr_debug("nf_conntrack_in: normal packet for %pK\n", ct); + *ctinfo = IP_CT_ESTABLISHED; + } else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) { +- pr_debug("nf_conntrack_in: related packet for %p\n", ++ pr_debug("nf_conntrack_in: related packet for %pK\n", + ct); + *ctinfo = IP_CT_RELATED; + } else { +- pr_debug("nf_conntrack_in: new packet for %p\n", ct); ++ pr_debug("nf_conntrack_in: new packet for %pK\n", ct); + *ctinfo = IP_CT_NEW; + } + *set_reply = 0; +@@ -1065,7 +1065,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, + /* Should be unconfirmed, so not in hash table yet */ + NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); + +- pr_debug("Altering reply tuple of %p to ", ct); ++ pr_debug("Altering reply tuple of %pK to ", ct); + nf_ct_dump_tuple(newreply); + + ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; +@@ -1640,7 +1640,7 @@ int nf_conntrack_init_net(struct net *net) + goto err_stat; + } + +- net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%p", net); ++ net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%pK", net); + if (!net->ct.slabname) { + ret = -ENOMEM; + goto err_slabname; diff --git a/Patches/Linux_CVEs/CVE-2016-8407/0.patch b/Patches/Linux_CVEs/CVE-2016-8407/0.patch new file mode 100644 index 00000000..7d41297b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8407/0.patch @@ -0,0 +1,157 @@ +From c01b4ad61a7e4291ea3db18baaf6c3532eff7e38 Mon Sep 17 00:00:00 2001 +From: Min Chong +Date: Fri, 14 Oct 2016 13:38:11 -0700 +Subject: [PATCH] usb: gadget: f_mbim: Change %p to %pK in debug messages + +The format specifier %p can leak kernel addresses +while not valuing the kptr_restrict system settings. +Use %pK instead of %p, which also evaluates whether +kptr_restrict is set. + +Bug: 31802656 +Change-Id: I74e83192e0379586469edba3c7579a1cd75cf3c0 +Signed-off-by: Min Chong +--- + drivers/usb/gadget/f_mbim.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c +index d1d10e07eb8db..797756dc46548 100644 +--- a/drivers/usb/gadget/f_mbim.c ++++ b/drivers/usb/gadget/f_mbim.c +@@ -589,24 +589,24 @@ static void fmbim_ctrl_response_available(struct f_mbim *dev) + unsigned long flags; + int ret; + +- pr_debug("dev:%p portno#%d\n", dev, dev->port_num); ++ pr_debug("dev:%pK portno#%d\n", dev, dev->port_num); + + spin_lock_irqsave(&dev->lock, flags); + + if (!atomic_read(&dev->online)) { +- pr_err("dev:%p is not online\n", dev); ++ pr_err("dev:%pK is not online\n", dev); + spin_unlock_irqrestore(&dev->lock, flags); + return; + } + + if (!req) { +- pr_err("dev:%p req is NULL\n", dev); ++ pr_err("dev:%pK req is NULL\n", dev); + spin_unlock_irqrestore(&dev->lock, flags); + return; + } + + if (!req->buf) { +- pr_err("dev:%p req->buf is NULL\n", dev); ++ pr_err("dev:%pK req->buf is NULL\n", dev); + spin_unlock_irqrestore(&dev->lock, flags); + return; + } +@@ -645,21 +645,21 @@ fmbim_send_cpkt_response(struct f_mbim *gr, struct ctrl_pkt *cpkt) + unsigned long flags; + + if (!gr || !cpkt) { +- pr_err("Invalid cpkt, dev:%p cpkt:%p\n", ++ pr_err("Invalid cpkt, dev:%pK cpkt:%pK\n", + gr, cpkt); + return -ENODEV; + } + +- pr_debug("dev:%p port_num#%d\n", dev, dev->port_num); ++ pr_debug("dev:%pK port_num#%d\n", dev, dev->port_num); + + if (!atomic_read(&dev->online)) { +- pr_err("dev:%p is not connected\n", dev); ++ pr_err("dev:%pK is not connected\n", dev); + mbim_free_ctrl_pkt(cpkt); + return 0; + } + + if (dev->not_port.notify_state != MBIM_NOTIFY_RESPONSE_AVAILABLE) { +- pr_err("dev:%p state=%d, recover!!\n", dev, ++ pr_err("dev:%pK state=%d, recover!!\n", dev, + dev->not_port.notify_state); + mbim_free_ctrl_pkt(cpkt); + return 0; +@@ -700,7 +700,7 @@ static int mbim_bam_connect(struct f_mbim *dev) + enum peer_bam bam_name = (dev->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ? + IPA_P_BAM : A2_P_BAM; + +- pr_info("dev:%p portno:%d\n", dev, dev->port_num); ++ pr_info("dev:%pK portno:%d\n", dev, dev->port_num); + + src_connection_idx = usb_bam_get_connection_idx(gadget->name, bam_name, + USB_TO_PEER_PERIPHERAL, USB_BAM_DEVICE, dev->port_num); +@@ -727,7 +727,7 @@ static int mbim_bam_connect(struct f_mbim *dev) + + static int mbim_bam_disconnect(struct f_mbim *dev) + { +- pr_info("%s - dev:%p port:%d\n", __func__, dev, dev->port_num); ++ pr_info("%s - dev:%pK port:%d\n", __func__, dev, dev->port_num); + bam_data_disconnect(&dev->bam_port, dev->port_num); + + return 0; +@@ -862,7 +862,7 @@ static void mbim_notify_complete(struct usb_ep *ep, struct usb_request *req) + struct f_mbim *mbim = req->context; + struct usb_cdc_notification *event = req->buf; + +- pr_debug("dev:%p\n", mbim); ++ pr_debug("dev:%pK\n", mbim); + + spin_lock(&mbim->lock); + switch (req->status) { +@@ -892,7 +892,7 @@ static void mbim_notify_complete(struct usb_ep *ep, struct usb_request *req) + mbim_do_notify(mbim); + spin_unlock(&mbim->lock); + +- pr_debug("dev:%p Exit\n", mbim); ++ pr_debug("dev:%pK Exit\n", mbim); + } + + static void mbim_ep0out_complete(struct usb_ep *ep, struct usb_request *req) +@@ -903,7 +903,7 @@ static void mbim_ep0out_complete(struct usb_ep *ep, struct usb_request *req) + struct f_mbim *mbim = func_to_mbim(f); + struct mbim_ntb_input_size *ntb = NULL; + +- pr_debug("dev:%p\n", mbim); ++ pr_debug("dev:%pK\n", mbim); + + req->context = NULL; + if (req->status || req->actual != req->length) { +@@ -941,7 +941,7 @@ static void mbim_ep0out_complete(struct usb_ep *ep, struct usb_request *req) + invalid: + usb_ep_set_halt(ep); + +- pr_err("dev:%p Failed\n", mbim); ++ pr_err("dev:%pK Failed\n", mbim); + + return; + } +@@ -963,7 +963,7 @@ fmbim_cmd_complete(struct usb_ep *ep, struct usb_request *req) + return; + } + +- pr_debug("dev:%p port#%d\n", dev, dev->port_num); ++ pr_debug("dev:%pK port#%d\n", dev, dev->port_num); + + cpkt = mbim_alloc_ctrl_pkt(len, GFP_ATOMIC); + if (!cpkt) { +@@ -1313,7 +1313,7 @@ static int mbim_set_alt(struct usb_function *f, unsigned intf, unsigned alt) + return ret; + } + +- pr_info("Set mbim port in_desc = 0x%p", ++ pr_info("Set mbim port in_desc = 0x%pK", + mbim->bam_port.in->desc); + + ret = config_ep_by_speed(cdev->gadget, f, +@@ -1325,7 +1325,7 @@ static int mbim_set_alt(struct usb_function *f, unsigned intf, unsigned alt) + return ret; + } + +- pr_info("Set mbim port out_desc = 0x%p", ++ pr_info("Set mbim port out_desc = 0x%pK", + mbim->bam_port.out->desc); + + if (mbim->xport == USB_GADGET_XPORT_BAM2BAM_IPA diff --git a/Patches/Linux_CVEs/CVE-2016-8410/0.patch b/Patches/Linux_CVEs/CVE-2016-8410/0.patch new file mode 100644 index 00000000..399fe062 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8410/0.patch @@ -0,0 +1,1747 @@ +From e2bbf665187a1f0a1248e4a088823cb182153ba9 Mon Sep 17 00:00:00 2001 +From: Ben Romberger +Date: Wed, 18 May 2016 17:15:50 -0700 +Subject: ASoC: msm: qdsp6v2: Change audio drivers to use %pK + +Change all qdsp6v2 audio driver to use %pK instead +of %p. %pK hides addresses when the users doesn't +have kernel permissions. If address information +is needed echo 0 > /proc/sys/kernel/kptr_restrict. + +Change-Id: I7baa9f127266726fecf9238167a1e0128a258847 +Signed-off-by: Ben Romberger +Signed-off-by: Surendar karka +--- + drivers/soc/qcom/qdsp6v2/apr.c | 12 ++-- + drivers/soc/qcom/qdsp6v2/msm_audio_ion.c | 37 ++++++------ + sound/soc/msm/qdsp6v2/audio_cal_utils.c | 4 +- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c | 16 +++--- + sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 4 +- + sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c | 4 +- + sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c | 4 +- + sound/soc/msm/qdsp6v2/msm-dts-eagle.c | 32 +++++------ + sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c | 4 +- + sound/soc/msm/qdsp6v2/msm-lsm-client.c | 24 ++++---- + sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c | 6 +- + sound/soc/msm/qdsp6v2/msm-pcm-host-voice-v2.c | 6 +- + sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c | 6 +- + sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c | 6 +- + sound/soc/msm/qdsp6v2/q6adm.c | 24 ++++---- + sound/soc/msm/qdsp6v2/q6afe.c | 28 ++++----- + sound/soc/msm/qdsp6v2/q6asm.c | 82 +++++++++++++-------------- + sound/soc/msm/qdsp6v2/q6core.c | 8 +-- + sound/soc/msm/qdsp6v2/q6lsm.c | 22 +++---- + sound/soc/msm/qdsp6v2/q6voice.c | 28 ++++----- + sound/soc/msm/qdsp6v2/rtac.c | 26 ++++----- + 21 files changed, 192 insertions(+), 191 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/apr.c b/drivers/soc/qcom/qdsp6v2/apr.c +index e88703d..06e7a05 100644 +--- a/drivers/soc/qcom/qdsp6v2/apr.c ++++ b/drivers/soc/qcom/qdsp6v2/apr.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2016, The 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 +@@ -513,7 +513,7 @@ void apr_cb_func(void *buf, int len, void *priv) + pr_debug("\n*****************\n"); + + if (!buf || len <= APR_HDR_SIZE) { +- pr_err("APR: Improper apr pkt received:%p %d\n", buf, len); ++ pr_err("APR: Improper apr pkt received:%pK %d\n", buf, len); + return; + } + hdr = buf; +@@ -599,7 +599,7 @@ void apr_cb_func(void *buf, int len, void *priv) + return; + } + pr_debug("svc_idx = %d\n", i); +- pr_debug("%x %x %x %p %p\n", c_svc->id, c_svc->dest_id, ++ pr_debug("%x %x %x %pK %pK\n", c_svc->id, c_svc->dest_id, + c_svc->client_id, c_svc->fn, c_svc->priv); + data.payload_size = hdr->pkt_size - hdr_size; + data.opcode = hdr->opcode; +@@ -663,7 +663,7 @@ static void apr_reset_deregister(struct work_struct *work) + container_of(work, struct apr_reset_work, work); + + handle = apr_reset->handle; +- pr_debug("%s:handle[%p]\n", __func__, handle); ++ pr_debug("%s:handle[%pK]\n", __func__, handle); + apr_deregister(handle); + kfree(apr_reset); + } +@@ -696,7 +696,7 @@ int apr_deregister(void *handle) + client[dest_id][client_id].svc_cnt--; + if (!client[dest_id][client_id].svc_cnt) { + svc->need_reset = 0x0; +- pr_debug("%s: service is reset %p\n", __func__, svc); ++ pr_debug("%s: service is reset %pK\n", __func__, svc); + } + } + +@@ -724,7 +724,7 @@ void apr_reset(void *handle) + + if (!handle) + return; +- pr_debug("%s: handle[%p]\n", __func__, handle); ++ pr_debug("%s: handle[%pK]\n", __func__, handle); + + if (apr_reset_workqueue == NULL) { + pr_err("%s: apr_reset_workqueue is NULL\n", __func__); +diff --git a/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c b/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c +index 52c97e4..470be30 100644 +--- a/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c ++++ b/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2016, The 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 +@@ -103,11 +103,11 @@ int msm_audio_ion_alloc(const char *name, struct ion_client **client, + pr_err("%s: ION memory mapping for AUDIO failed\n", __func__); + goto err_ion_handle; + } +- pr_debug("%s: mapped address = %p, size=%zd\n", __func__, ++ pr_debug("%s: mapped address = %pK, size=%zd\n", __func__, + *vaddr, bufsz); + + if (bufsz != 0) { +- pr_debug("%s: memset to 0 %p %zd\n", __func__, *vaddr, bufsz); ++ pr_debug("%s: memset to 0 %pK %zd\n", __func__, *vaddr, bufsz); + memset((void *)*vaddr, 0, bufsz); + } + +@@ -153,7 +153,7 @@ int msm_audio_ion_import(const char *name, struct ion_client **client, + bufsz should be 0 and fd shouldn't be 0 as of now + */ + *handle = ion_import_dma_buf(*client, fd); +- pr_debug("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__, ++ pr_debug("%s: DMA Buf name=%s, fd=%d handle=%pK\n", __func__, + name, fd, *handle); + if (IS_ERR_OR_NULL((void *) (*handle))) { + pr_err("%s: ion import dma buffer failed\n", +@@ -184,7 +184,7 @@ int msm_audio_ion_import(const char *name, struct ion_client **client, + rc = -ENOMEM; + goto err_ion_handle; + } +- pr_debug("%s: mapped address = %p, size=%zd\n", __func__, ++ pr_debug("%s: mapped address = %pK, size=%zd\n", __func__, + *vaddr, bufsz); + + return 0; +@@ -207,7 +207,7 @@ int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle) + } + if (msm_audio_ion_data.smmu_enabled) { + /* Need to populate book kept infomation */ +- pr_debug("client=%p, domain=%p, domain_id=%d, group=%p", ++ pr_debug("client=%pK, domain=%pK, domain_id=%d, group=%pK", + client, msm_audio_ion_data.domain, + msm_audio_ion_data.domain_id, msm_audio_ion_data.group); + +@@ -273,7 +273,7 @@ int msm_audio_ion_mmap(struct audio_buffer *ab, + offset = 0; + } + len = min(len, remainder); +- pr_debug("vma=%p, addr=%x len=%ld vm_start=%x vm_end=%x vm_page_prot=%ld\n", ++ pr_debug("vma=%pK, addr=%x len=%ld vm_start=%x vm_end=%x vm_page_prot=%ld\n", + vma, (unsigned int)addr, len, + (unsigned int)vma->vm_start, + (unsigned int)vma->vm_end, +@@ -296,8 +296,8 @@ int msm_audio_ion_mmap(struct audio_buffer *ab, + , __func__ , ret); + return ret; + } +- pr_debug("phys=%pa len=%zd\n", &phys_addr, phys_len); +- pr_debug("vma=%p, vm_start=%x vm_end=%x vm_pgoff=%ld vm_page_prot=%ld\n", ++ pr_debug("phys=%pK len=%zd\n", &phys_addr, phys_len); ++ pr_debug("vma=%pK, vm_start=%x vm_end=%x vm_pgoff=%ld vm_page_prot=%ld\n", + vma, (unsigned int)vma->vm_start, + (unsigned int)vma->vm_end, vma->vm_pgoff, + (unsigned long int)vma->vm_page_prot); +@@ -333,7 +333,7 @@ struct ion_client *msm_audio_ion_client_create(const char *name) + + void msm_audio_ion_client_destroy(struct ion_client *client) + { +- pr_debug("%s: client = %p smmu_enabled = %d\n", __func__, ++ pr_debug("%s: client = %pK smmu_enabled = %d\n", __func__, + client, msm_audio_ion_data.smmu_enabled); + + ion_client_destroy(client); +@@ -355,7 +355,7 @@ int msm_audio_ion_import_legacy(const char *name, struct ion_client *client, + bufsz should be 0 and fd shouldn't be 0 as of now + */ + *handle = ion_import_dma_buf(client, fd); +- pr_debug("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__, ++ pr_debug("%s: DMA Buf name=%s, fd=%d handle=%pK\n", __func__, + name, fd, *handle); + if (IS_ERR_OR_NULL((void *)(*handle))) { + pr_err("%s: ion import dma buffer failed\n", +@@ -421,7 +421,7 @@ int msm_audio_ion_cache_operations(struct audio_buffer *abuff, int cache_op) + int msm_cache_ops = 0; + + if (!abuff) { +- pr_err("Invalid params: %p, %p\n", __func__, abuff); ++ pr_err("%s: Invalid params: %pK\n", __func__, abuff); + return -EINVAL; + } + rc = ion_handle_get_flags(abuff->client, abuff->handle, +@@ -467,7 +467,7 @@ static int msm_audio_ion_get_phys(struct ion_client *client, + pr_err("%s: ION map iommu failed %d\n", __func__, rc); + return rc; + } +- pr_debug("client=%p, domain=%p, domain_id=%d, group=%p", ++ pr_debug("client=%pK, domain=%pK, domain_id=%d, group=%pK", + client, msm_audio_ion_data.domain, + msm_audio_ion_data.domain_id, msm_audio_ion_data.group); + /* Append the SMMU SID information to the address */ +@@ -476,7 +476,8 @@ static int msm_audio_ion_get_phys(struct ion_client *client, + /* SMMU is disabled*/ + rc = ion_phys(client, handle, addr, len); + } +- pr_debug("phys=%pa, len=%zd, rc=%d\n", &(*addr), *len, rc); ++ pr_debug("phys=%pK, len=%zd, rc=%d\n", &(*addr), *len, rc); ++ + return rc; + } + +@@ -540,18 +541,18 @@ static int msm_audio_ion_probe(struct platform_device *pdev) + msm_audio_ion_data.domain = + iommu_group_get_iommudata(msm_audio_ion_data.group); + if (IS_ERR_OR_NULL(msm_audio_ion_data.domain)) { +- pr_err("Failed to get domain data for group %p", ++ pr_err("Failed to get domain data for group %pK", + msm_audio_ion_data.group); + goto fail_group; + } + msm_audio_ion_data.domain_id = + msm_find_domain_no(msm_audio_ion_data.domain); + if (msm_audio_ion_data.domain_id < 0) { +- pr_err("Failed to get domain index for domain %p", ++ pr_err("Failed to get domain index for domain %pK", + msm_audio_ion_data.domain); + goto fail_group; + } +- pr_debug("domain=%p, domain_id=%d, group=%p", ++ pr_debug("domain=%pK, domain_id=%d, group=%pK", + msm_audio_ion_data.domain, + msm_audio_ion_data.domain_id, msm_audio_ion_data.group); + +@@ -575,7 +576,7 @@ fail_group: + + static int msm_audio_ion_remove(struct platform_device *pdev) + { +- pr_debug("%s: msm audio ion is unloaded, domain=%p, group=%p\n", ++ pr_debug("%s: msm audio ion is unloaded, domain=%pK, group=%pK\n", + __func__, msm_audio_ion_data.domain, msm_audio_ion_data.group); + iommu_detach_group(msm_audio_ion_data.domain, msm_audio_ion_data.group); + +diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c +index 67275df..562e9a1 100644 +--- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c ++++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The 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 +@@ -599,7 +599,7 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, + goto err; + } + cal_block->buffer_number = basic_cal->cal_hdr.buffer_number; +- pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pa!\n", ++ pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pK!\n", + __func__, cal_type->info.reg.cal_type, + cal_block->buffer_number, + cal_block->map_data.ion_map_handle, +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +index 82de46c..5071be9 100644 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014, 2016 The 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 +@@ -192,7 +192,7 @@ static void compr_event_handler(uint32_t opcode, + pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", + __func__, prtd->pcm_count, prtd->out_head); + temp = buf[0].phys + (prtd->out_head * prtd->pcm_count); +- pr_debug("%s:writing buffer[%d] from 0x%pa\n", ++ pr_debug("%s:writing buffer[%d] from 0x%pK\n", + __func__, prtd->out_head, &temp); + + if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +@@ -243,7 +243,7 @@ static void compr_event_handler(uint32_t opcode, + break; + case ASM_DATA_EVENT_READ_DONE_V2: { + pr_debug("ASM_DATA_EVENT_READ_DONE\n"); +- pr_debug("buf = %p, data = 0x%X, *data = %p,\n" ++ pr_debug("buf = %pK, data = 0x%X, *data = %pK,\n" + "prtd->pcm_irq_pos = %d\n", + prtd->audio_client->port[OUT].buf, + *(uint32_t *)prtd->audio_client->port[OUT].buf->data, +@@ -253,7 +253,7 @@ static void compr_event_handler(uint32_t opcode, + memcpy(prtd->audio_client->port[OUT].buf->data + + prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE), + COMPRE_CAPTURE_HEADER_SIZE); +- pr_debug("buf = %p, updated data = 0x%X, *data = %p\n", ++ pr_debug("buf = %pK, updated data = 0x%X, *data = %pK\n", + prtd->audio_client->port[OUT].buf, + *(uint32_t *)(prtd->audio_client->port[OUT].buf->data + + prtd->pcm_irq_pos), +@@ -269,7 +269,7 @@ static void compr_event_handler(uint32_t opcode, + } + buf = prtd->audio_client->port[OUT].buf; + +- pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%pa\n", ++ pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%pK\n", + prtd->pcm_irq_pos, &buf[0].phys); + read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE; + read_param.paddr = buf[0].phys + +@@ -295,7 +295,7 @@ static void compr_event_handler(uint32_t opcode, + pr_debug("%s: writing %d bytes of buffer[%d] to dsp\n", + __func__, prtd->pcm_count, prtd->out_head); + buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s: writing buffer[%d] from 0x%pa head %d count %d\n", ++ pr_debug("%s: writing buffer[%d] from 0x%pK head %d count %d\n", + __func__, prtd->out_head, &buf[0].phys, + prtd->pcm_count, prtd->out_head); + if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +@@ -602,7 +602,7 @@ static int msm_compr_capture_prepare(struct snd_pcm_substream *substream) + - COMPRE_CAPTURE_HEADER_SIZE; + read_param.paddr = buf[i].phys + + COMPRE_CAPTURE_HEADER_SIZE; +- pr_debug("Push buffer [%d] to DSP, paddr: %pa, vaddr: %p\n", ++ pr_debug("Push buffer [%d] to DSP, paddr: %pK, vaddr: %pK\n", + i, &read_param.paddr, + buf[i].data); + q6asm_async_read(prtd->audio_client, &read_param); +@@ -963,7 +963,7 @@ static int msm_compr_hw_params(struct snd_pcm_substream *substream, + dma_buf->addr = buf[0].phys; + dma_buf->bytes = runtime->hw.buffer_bytes_max; + +- pr_debug("%s: buf[%p]dma_buf->area[%p]dma_buf->addr[%pa]\n" ++ pr_debug("%s: buf[%pK]dma_buf->area[%pK]dma_buf->addr[%pK]\n" + "dma_buf->bytes[%zd]\n", __func__, + (void *)buf, (void *)dma_buf->area, + &dma_buf->addr, dma_buf->bytes); +diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +index bb0cb9f..7aac112 100644 +--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -2056,7 +2056,7 @@ static int msm_compr_get_caps(struct snd_compr_stream *cstream, + memcpy(arg, &prtd->compr_cap, sizeof(struct snd_compr_caps)); + } else { + ret = -EINVAL; +- pr_err("%s: arg (0x%p), prtd (0x%p)\n", __func__, arg, prtd); ++ pr_err("%s: arg (0x%pK), prtd (0x%pK)\n", __func__, arg, prtd); + } + + return ret; +diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +index ee5a340..8ef8f49 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -1861,7 +1861,7 @@ static int msm_auxpcm_dev_probe(struct platform_device *pdev) + goto fail_pdata_nomem; + } + +- dev_dbg(&pdev->dev, "%s: dev %p, dai_data %p, auxpcm_pdata %p\n", ++ dev_dbg(&pdev->dev, "%s: dev %pK, dai_data %pK, auxpcm_pdata %pK\n", + __func__, &pdev->dev, dai_data, auxpcm_pdata); + + rc = of_property_read_u32_array(pdev->dev.of_node, +diff --git a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +index ace747d..fea7bb4 100644 +--- a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +@@ -1103,7 +1103,7 @@ static int msm_ds2_dap_send_end_point(int dev_map_idx, int endp_idx) + ds2_ap_params_obj = &ds2_dap_params[cache_device]; + pr_debug("%s: cache dev %d, dev_map_idx %d\n", __func__, + cache_device, dev_map_idx); +- pr_debug("%s: endp - %p %p\n", __func__, ++ pr_debug("%s: endp - %pK %pK\n", __func__, + &ds2_dap_params[cache_device], ds2_ap_params_obj); + + params_value = kzalloc(params_length, GFP_KERNEL); +@@ -1189,7 +1189,7 @@ static int msm_ds2_dap_send_cached_params(int dev_map_idx, + } + + ds2_ap_params_obj = &ds2_dap_params[cache_device]; +- pr_debug("%s: cached param - %p %p, cache_device %d\n", __func__, ++ pr_debug("%s: cached param - %pK %pK, cache_device %d\n", __func__, + &ds2_dap_params[cache_device], ds2_ap_params_obj, + cache_device); + params_value = kzalloc(params_length, GFP_KERNEL); +diff --git a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c b/sound/soc/msm/qdsp6v2/msm-dts-eagle.c +index 3a6a9c2..465947f 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c ++++ b/sound/soc/msm/qdsp6v2/msm-dts-eagle.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The 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 +@@ -470,7 +470,7 @@ static int _sendcache_pre(struct audio_client *ac) + err = -EINVAL; + if ((_depc_size == 0) || !_depc || (size == 0) || + cmd == 0 || ((offset + size) > _depc_size) || (err != 0)) { +- eagle_precache_err("%s: primary device %i cache index %i general error - cache size = %u, cache ptr = %p, offset = %u, size = %u, cmd = %i", ++ eagle_precache_err("%s: primary device %i cache index %i general error - cache size = %u, cache ptr = %pK, offset = %u, size = %u, cmd = %i", + __func__, _device_primary, cidx, _depc_size, _depc, + offset, size, cmd); + return -EINVAL; +@@ -554,7 +554,7 @@ NT_MODE_GOTO: + err = -EINVAL; + if ((_depc_size == 0) || !_depc || (err != 0) || (size == 0) || + (cmd == 0) || (offset + size) > _depc_size) { +- eagle_postcache_err("%s: primary device %i cache index %i port_id 0x%X general error - cache size = %u, cache ptr = %p, offset = %u, size = %u, cmd = %i", ++ eagle_postcache_err("%s: primary device %i cache index %i port_id 0x%X general error - cache size = %u, cache ptr = %pK, offset = %u, size = %u, cmd = %i", + __func__, _device_primary, cidx, port_id, + _depc_size, _depc, offset, size, cmd); + return -EINVAL; +@@ -1042,7 +1042,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + eagle_ioctl_info("%s: called with control 0x%X (allocate param cache)", + __func__, cmd); + if (copy_from_user((void *)&size, (void *)arg, sizeof(size))) { +- eagle_ioctl_err("%s: error copying size (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error copying size (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, &size, sizeof(size)); + return -EFAULT; + } else if (size > DEPC_MAX_SIZE) { +@@ -1082,7 +1082,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + eagle_ioctl_info("%s: control 0x%X (get param)", + __func__, cmd); + if (copy_from_user((void *)&depd, (void *)arg, sizeof(depd))) { +- eagle_ioctl_err("%s: error copying dts_eagle_param_desc (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error copying dts_eagle_param_desc (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, &depd, sizeof(depd)); + return -EFAULT; + } +@@ -1153,7 +1153,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + eagle_ioctl_info("%s: control 0x%X (set param)", + __func__, cmd); + if (copy_from_user((void *)&depd, (void *)arg, sizeof(depd))) { +- eagle_ioctl_err("%s: error copying dts_eagle_param_desc (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error copying dts_eagle_param_desc (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, &depd, sizeof(depd)); + return -EFAULT; + } +@@ -1186,7 +1186,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + if (copy_from_user((void *)&_depc[offset], + (void *)(((char *)arg)+sizeof(depd)), + depd.size)) { +- eagle_ioctl_err("%s: error copying param to cache (src:%p, tgt:%p, size:%u)", ++ eagle_ioctl_err("%s: error copying param to cache (src:%pK, tgt:%pK, size:%u)", + __func__, ((char *)arg)+sizeof(depd), + &_depc[offset], depd.size); + return -EFAULT; +@@ -1205,7 +1205,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + eagle_ioctl_info("%s: with control 0x%X (set param cache block)", + __func__, cmd); + if (copy_from_user((void *)b_, (void *)arg, sizeof(b_))) { +- eagle_ioctl_err("%s: error copying cache block data (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error copying cache block data (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, b_, sizeof(b_)); + return -EFAULT; + } +@@ -1236,7 +1236,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + eagle_ioctl_dbg("%s: with control 0x%X (set active device)", + __func__, cmd); + if (copy_from_user((void *)data, (void *)arg, sizeof(data))) { +- eagle_ioctl_err("%s: error copying active device data (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error copying active device data (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, data, sizeof(data)); + return -EFAULT; + } +@@ -1258,7 +1258,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + __func__, cmd); + if (copy_from_user((void *)&target, (void *)arg, + sizeof(target))) { +- eagle_ioctl_err("%s: error reading license index. (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error reading license index. (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, &target, sizeof(target)); + return -EFAULT; + } +@@ -1305,7 +1305,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + cmd); + if (copy_from_user((void *)target, (void *)arg, + sizeof(target))) { +- eagle_ioctl_err("%s: error reading license index (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error reading license index (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, target, sizeof(target)); + return -EFAULT; + } +@@ -1348,7 +1348,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + (void *)&(((u32 *)_sec_blob[target[0]])[1]), + (void *)(((char *)arg)+sizeof(target)), + target[1])) { +- eagle_ioctl_err("%s: error copying license to index %u, size %u (src:%p, tgt:%p, size:%u)", ++ eagle_ioctl_err("%s: error copying license to index %u, size %u (src:%pK, tgt:%pK, size:%u)", + __func__, target[0], target[1], + ((char *)arg)+sizeof(target), + &(((u32 *)_sec_blob[target[0]])[1]), +@@ -1365,7 +1365,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + cmd); + if (copy_from_user((void *)&target, (void *)arg, + sizeof(target))) { +- eagle_ioctl_err("%s: error reading license index (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error reading license index (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, &target, sizeof(target)); + return -EFAULT; + } +@@ -1395,7 +1395,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + __func__, cmd); + if (copy_from_user((void *)&spec, (void *)arg, + sizeof(spec))) { +- eagle_ioctl_err("%s: error reading volume command specifier (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error reading volume command specifier (src:%pK, tgt:%pK, size:%zu)", + __func__, (void *)arg, &spec, sizeof(spec)); + return -EFAULT; + } +@@ -1417,7 +1417,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + if (copy_from_user((void *)&_vol_cmds_d[idx], + (void *)(((char *)arg) + sizeof(int)), + sizeof(struct vol_cmds_d))) { +- eagle_ioctl_err("%s: error reading volume command descriptor (src:%p, tgt:%p, size:%zu)", ++ eagle_ioctl_err("%s: error reading volume command descriptor (src:%pK, tgt:%pK, size:%zu)", + __func__, ((char *)arg) + sizeof(int), + &_vol_cmds_d[idx], + sizeof(struct vol_cmds_d)); +@@ -1430,7 +1430,7 @@ int msm_dts_eagle_ioctl(unsigned int cmd, unsigned long arg) + if (copy_from_user((void *)_vol_cmds[idx], + (void *)(((char *)arg) + (sizeof(int) + + sizeof(struct vol_cmds_d))), size)) { +- eagle_ioctl_err("%s: error reading volume command string (src:%p, tgt:%p, size:%i)", ++ eagle_ioctl_err("%s: error reading volume command string (src:%pK, tgt:%pK, size:%i)", + __func__, ((char *)arg) + (sizeof(int) + + sizeof(struct vol_cmds_d)), + _vol_cmds[idx], size); +diff --git a/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c b/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c +index ddfbcec..7c35d19 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-dts-srs-tm-config.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014, 2016, The 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 +@@ -292,7 +292,7 @@ static int reg_ion_mem(void) + &po.kvaddr); + if (rc != 0) + pr_err("%s: failed to allocate memory.\n", __func__); +- pr_debug("%s: exited ion_client = %p, ion_handle = %p, phys_addr = %lu, length = %d, vaddr = %p, rc = 0x%x\n", ++ pr_debug("%s: exited ion_client = %pK, ion_handle = %pK, phys_addr = %lu, length = %d, vaddr = %pK, rc = 0x%x\n", + __func__, ion_client, ion_handle, (long)po.paddr, + (unsigned int)po.size, po.kvaddr, rc); + return rc; +diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +index 79b92f6..32a16bf 100644 +--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c ++++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2016, 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 +@@ -95,7 +95,7 @@ static int msm_lsm_queue_lab_buffer(struct lsm_priv *prtd, int i) + struct snd_soc_pcm_runtime *rtd; + + if (!prtd || !prtd->lsm_client) { +- pr_err("%s: Invalid params prtd %p lsm client %p\n", ++ pr_err("%s: Invalid params prtd %pK lsm client %pK\n", + __func__, prtd, ((!prtd) ? NULL : prtd->lsm_client)); + return -EINVAL; + } +@@ -109,7 +109,7 @@ static int msm_lsm_queue_lab_buffer(struct lsm_priv *prtd, int i) + if (!prtd->lsm_client->lab_buffer || + i >= prtd->lsm_client->hw_params.period_count) { + dev_err(rtd->dev, +- "%s: Lab buffer not setup %p incorrect index %d period count %d\n", ++ "%s: Lab buffer not setup %pK incorrect index %d period count %d\n", + __func__, prtd->lsm_client->lab_buffer, i, + prtd->lsm_client->hw_params.period_count); + return -EINVAL; +@@ -136,7 +136,7 @@ static int lsm_lab_buffer_sanity(struct lsm_priv *prtd, + struct snd_soc_pcm_runtime *rtd; + + if (!prtd || !read_done || !index) { +- pr_err("%s: Invalid params prtd %p read_done %p index %p\n", ++ pr_err("%s: Invalid params prtd %pK read_done %pK index %pK\n", + __func__, prtd, read_done, index); + return -EINVAL; + } +@@ -150,7 +150,7 @@ static int lsm_lab_buffer_sanity(struct lsm_priv *prtd, + + if (!prtd->lsm_client->lab_enable || !prtd->lsm_client->lab_buffer) { + dev_err(rtd->dev, +- "%s: Lab not enabled %d invalid lab buffer %p\n", ++ "%s: Lab not enabled %d invalid lab buffer %pK\n", + __func__, prtd->lsm_client->lab_enable, + prtd->lsm_client->lab_buffer); + return -EINVAL; +@@ -164,7 +164,7 @@ static int lsm_lab_buffer_sanity(struct lsm_priv *prtd, + (prtd->lsm_client->lab_buffer[i].mem_map_handle == + read_done->mem_map_handle)) { + dev_dbg(rtd->dev, +- "%s: Buffer found %pa memmap handle %d\n", ++ "%s: Buffer found %pK memmap handle %d\n", + __func__, &prtd->lsm_client->lab_buffer[i].phys, + prtd->lsm_client->lab_buffer[i].mem_map_handle); + if (read_done->total_size > +@@ -211,7 +211,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token, + if (prtd->lsm_client->session != token || + !read_done) { + dev_err(rtd->dev, +- "%s: EVENT_READ_DONE invalid callback, session %d callback %d payload %p", ++ "%s: EVENT_READ_DONE invalid callback, session %d callback %d payload %pK", + __func__, prtd->lsm_client->session, + token, read_done); + return; +@@ -310,7 +310,7 @@ static int msm_lsm_lab_buffer_alloc(struct lsm_priv *lsm, int alloc) + int ret = 0; + struct snd_dma_buffer *dma_buf = NULL; + if (!lsm) { +- pr_err("%s: Invalid param lsm %p\n", __func__, lsm); ++ pr_err("%s: Invalid param lsm %pK\n", __func__, lsm); + return -EINVAL; + } + if (alloc) { +@@ -778,7 +778,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + snd_model_v2.data, snd_model_v2.data_size)) { + dev_err(rtd->dev, + "%s: copy from user data failed\n" +- "data %p size %d\n", __func__, ++ "data %pK size %d\n", __func__, + snd_model_v2.data, snd_model_v2.data_size); + q6lsm_snd_model_buf_free(prtd->lsm_client); + rc = -EFAULT; +@@ -1798,7 +1798,7 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, + + if (!prtd || !params) { + dev_err(rtd->dev, +- "%s: invalid params prtd %p params %p", ++ "%s: invalid params prtd %pK params %pK", + __func__, prtd, params); + return -EINVAL; + } +@@ -1840,7 +1840,7 @@ static snd_pcm_uframes_t msm_lsm_pcm_pointer( + + if (!prtd) { + dev_err(rtd->dev, +- "%s: Invalid param %p\n", __func__, prtd); ++ "%s: Invalid param %pK\n", __func__, prtd); + return 0; + } + +@@ -1868,7 +1868,7 @@ static int msm_lsm_pcm_copy(struct snd_pcm_substream *substream, int ch, + + if (!prtd) { + dev_err(rtd->dev, +- "%s: Invalid param %p\n", __func__, prtd); ++ "%s: Invalid param %pK\n", __func__, prtd); + return -EINVAL; + } + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +index 84c21f4a1..f1c96ef 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -387,7 +387,7 @@ static int msm_afe_open(struct snd_pcm_substream *substream) + pr_err("Failed to allocate memory for msm_audio\n"); + return -ENOMEM; + } else +- pr_debug("prtd %p\n", prtd); ++ pr_debug("prtd %pK\n", prtd); + + mutex_init(&prtd->lock); + spin_lock_init(&prtd->dsp_lock); +@@ -606,7 +606,7 @@ static int msm_afe_hw_params(struct snd_pcm_substream *substream, + return -ENOMEM; + } + +- pr_debug("%s:buf = %p\n", __func__, buf); ++ pr_debug("%s:buf = %pK\n", __func__, buf); + dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; + dma_buf->dev.dev = substream->pcm->card->dev; + dma_buf->private_data = NULL; +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-host-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-host-voice-v2.c +index c190977..1dd18c6 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-host-voice-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-host-voice-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2014, 2016 The 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 +@@ -504,7 +504,7 @@ static int hpcm_allocate_shared_memory(struct hpcm_drv *prtd) + + sess->tp_mem_table.size = sizeof(struct vss_imemory_table_t); + +- pr_debug("%s: data %p phys %pa\n", __func__, ++ pr_debug("%s: data %pK phys %pK\n", __func__, + sess->tp_mem_table.data, &sess->tp_mem_table.phys); + + /* Split 4096 block into four 1024 byte blocks for each dai */ +@@ -682,7 +682,7 @@ void hpcm_notify_evt_processing(uint8_t *data, char *session, + } + + if (tp == NULL || tmd == NULL) { +- pr_err("%s: tp = %p or tmd = %p is null\n", __func__, ++ pr_err("%s: tp = %pK or tmd = %pK is null\n", __func__, + tp, tmd); + + return; +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c +index 64d3fe0..ad7e114 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014, 2016 The 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 +@@ -132,7 +132,7 @@ static void event_handler(uint32_t opcode, + pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", + __func__, prtd->pcm_count, prtd->out_head); + temp = buf[0].phys + (prtd->out_head * prtd->pcm_count); +- pr_debug("%s:writing buffer[%d] from 0x%pa\n", ++ pr_debug("%s:writing buffer[%d] from 0x%pK\n", + __func__, prtd->out_head, &temp); + if (prtd->meta_data_mode) { + memcpy(&output_meta_data, (char *)(buf->data + +@@ -623,7 +623,7 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream, + if (buf == NULL || buf[0].data == NULL) + return -ENOMEM; + +- pr_debug("%s:buf = %p\n", __func__, buf); ++ pr_debug("%s:buf = %pK\n", __func__, buf); + dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; + dma_buf->dev.dev = substream->pcm->card->dev; + dma_buf->private_data = NULL; +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +index 4eb3f2a..37461db 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -746,7 +746,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream, + pr_debug("%s: pcm stopped in_count 0\n", __func__); + return 0; + } +- pr_debug("Checking if valid buffer is available...%p\n", ++ pr_debug("Checking if valid buffer is available...%pK\n", + data); + data = q6asm_is_cpu_buf_avail(OUT, prtd->audio_client, &size, &idx); + bufptr = data; +@@ -903,7 +903,7 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream, + if (buf == NULL || buf[0].data == NULL) + return -ENOMEM; + +- pr_debug("%s:buf = %p\n", __func__, buf); ++ pr_debug("%s:buf = %pK\n", __func__, buf); + dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; + dma_buf->dev.dev = substream->pcm->card->dev; + dma_buf->private_data = NULL; +diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c +index 5d0fd0d..f029594 100644 +--- a/sound/soc/msm/qdsp6v2/q6adm.c ++++ b/sound/soc/msm/qdsp6v2/q6adm.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -378,7 +378,7 @@ int adm_dts_eagle_get(int port_id, int copp_idx, int param_id, + } + + if ((size == 0) || !data) { +- pr_err("DTS_EAGLE_ADM: %s - invalid size %u or pointer %p.\n", ++ pr_err("DTS_EAGLE_ADM: %s - invalid size %u or pointer %pK.\n", + __func__, size, data); + return -EINVAL; + } +@@ -1246,7 +1246,7 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) + payload = data->payload; + + if (data->opcode == RESET_EVENTS) { +- pr_debug("%s: Reset event is received: %d %d apr[%p]\n", ++ pr_debug("%s: Reset event is received: %d %d apr[%pK]\n", + __func__, + data->reset_event, data->reset_proc, this_adm.apr); + if (this_adm.apr) { +@@ -1739,7 +1739,7 @@ static void remap_cal_data(struct cal_block_data *cal_block, int cal_index) + pr_err("%s: ADM mmap did not work! size = %zd ret %d\n", + __func__, + cal_block->map_data.map_size, ret); +- pr_debug("%s: ADM mmap did not work! addr = 0x%pa, size = %zd ret %d\n", ++ pr_debug("%s: ADM mmap did not work! addr = 0x%pK, size = %zd ret %d\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size, ret); +@@ -1802,7 +1802,7 @@ static void send_adm_custom_topology(void) + + atomic_set(&this_adm.adm_stat, 0); + atomic_set(&this_adm.adm_cmd_err_code, 0); +- pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%pa, size = %d\n", ++ pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%pK, size = %d\n", + __func__, &cal_block->cal_data.paddr, + adm_top.payload_size); + result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_top); +@@ -1892,14 +1892,14 @@ static int send_adm_cal_block(int port_id, int copp_idx, + + atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0); + atomic_set(&this_adm.copp.cmd_err_code[port_idx][copp_idx], 0); +- pr_debug("%s: Sending SET_PARAMS payload = 0x%pa, size = %d\n", ++ pr_debug("%s: Sending SET_PARAMS payload = 0x%pK, size = %d\n", + __func__, &cal_block->cal_data.paddr, + adm_params.payload_size); + result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_params); + if (result < 0) { + pr_err("%s: Set params failed port 0x%x result %d\n", + __func__, port_id, result); +- pr_debug("%s: Set params failed port = 0x%x payload = 0x%pa result %d\n", ++ pr_debug("%s: Set params failed port = 0x%x payload = 0x%pK result %d\n", + __func__, port_id, &cal_block->cal_data.paddr, result); + result = -EINVAL; + goto done; +@@ -1911,7 +1911,7 @@ static int send_adm_cal_block(int port_id, int copp_idx, + if (!result) { + pr_err("%s: Set params timed out port = 0x%x\n", + __func__, port_id); +- pr_debug("%s: Set params timed out port = 0x%x, payload = 0x%pa\n", ++ pr_debug("%s: Set params timed out port = 0x%x, payload = 0x%pK\n", + __func__, port_id, &cal_block->cal_data.paddr); + result = -EINVAL; + goto done; +@@ -2352,7 +2352,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, + res = adm_memory_map_regions(&this_adm.outband_memmap.paddr, 0, + (uint32_t *)&this_adm.outband_memmap.size, 1); + if (res < 0) { +- pr_err("%s: SRS adm_memory_map_regions failed ! addr = 0x%p, size = %d\n", ++ pr_err("%s: SRS adm_memory_map_regions failed ! addr = 0x%pK, size = %d\n", + __func__, (void *)this_adm.outband_memmap.paddr, + (uint32_t)this_adm.outband_memmap.size); + } +@@ -2781,7 +2781,7 @@ int adm_map_rtac_block(struct rtac_cal_block_data *cal_block) + pr_err("%s: RTAC mmap did not work! size = %d result %d\n", + __func__, + cal_block->map_data.map_size, result); +- pr_debug("%s: RTAC mmap did not work! addr = 0x%pa, size = %d\n", ++ pr_debug("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size); +@@ -3963,7 +3963,7 @@ static int adm_source_tracking_alloc_map_memory(void) + (uint32_t *)&this_adm.sourceTrackingData.memmap.size, + 1); + if (ret < 0) { +- pr_err("%s: failed to map memory, paddr = 0x%p, size = %d\n", ++ pr_err("%s: failed to map memory, paddr = 0x%pK, size = %d\n", + __func__, + (void *)this_adm.sourceTrackingData.memmap.paddr, + (uint32_t)this_adm.sourceTrackingData.memmap.size); +@@ -3983,7 +3983,7 @@ static int adm_source_tracking_alloc_map_memory(void) + goto done; + } + ret = 0; +- pr_debug("%s: paddr = 0x%p, size = %d, mem_map_handle = 0x%x\n", ++ pr_debug("%s: paddr = 0x%pK, size = %d, mem_map_handle = 0x%x\n", + __func__, (void *)this_adm.sourceTrackingData.memmap.paddr, + (uint32_t)this_adm.sourceTrackingData.memmap.size, + atomic_read(&this_adm.mem_map_handles +diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c +index 860aab8..e5c7347 100644 +--- a/sound/soc/msm/qdsp6v2/q6afe.c ++++ b/sound/soc/msm/qdsp6v2/q6afe.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -167,7 +167,7 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) + return -EINVAL; + } + if (data->opcode == RESET_EVENTS) { +- pr_debug("%s: reset event = %d %d apr[%p]\n", ++ pr_debug("%s: reset event = %d %d apr[%pK]\n", + __func__, + data->reset_event, data->reset_proc, this_afe.apr); + +@@ -202,7 +202,7 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) + + if ((data->payload_size < sizeof(this_afe.calib_data)) + || !payload || (data->token >= AFE_MAX_PORTS)) { +- pr_err("%s: Error: size %d payload %p token %d\n", ++ pr_err("%s: Error: size %d payload %pK token %d\n", + __func__, data->payload_size, + payload, data->token); + return -EINVAL; +@@ -541,7 +541,7 @@ static int afe_send_cal_block(u16 port_id, struct cal_block_data *cal_block) + populate_upper_32_bits(cal_block->cal_data.paddr); + afe_cal.param.mem_map_handle = cal_block->map_data.q6map_handle; + +- pr_debug("%s: AFE cal sent for device port = 0x%x, cal size = %zd, cal addr = 0x%pa\n", ++ pr_debug("%s: AFE cal sent for device port = 0x%x, cal size = %zd, cal addr = 0x%pK\n", + __func__, port_id, + cal_block->cal_data.size, &cal_block->cal_data.paddr); + +@@ -586,7 +586,7 @@ static int afe_send_custom_topology_block(struct cal_block_data *cal_block) + populate_upper_32_bits(cal_block->cal_data.paddr); + afe_cal.mem_map_handle = cal_block->map_data.q6map_handle; + +- pr_debug("%s:cmd_id:0x%x calsize:%zd memmap_hdl:0x%x caladdr:0x%pa", ++ pr_debug("%s:cmd_id:0x%x calsize:%zd memmap_hdl:0x%x caladdr:0x%pK", + __func__, AFE_CMD_ADD_TOPOLOGIES, cal_block->cal_data.size, + afe_cal.mem_map_handle, &cal_block->cal_data.paddr); + +@@ -1090,7 +1090,7 @@ static void remap_cal_data(struct cal_block_data *cal_block, int cal_index) + pr_err("%s: mmap did not work! size = %zd ret %d\n", + __func__, + cal_block->map_data.map_size, ret); +- pr_debug("%s: mmap did not work! addr = 0x%pa, size = %zd\n", ++ pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size); +@@ -2843,7 +2843,7 @@ int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir, + size_t len; + + if (!(ac) || ((dir != IN) && (dir != OUT))) { +- pr_err("%s: ac %p dir %d\n", __func__, ac, dir); ++ pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + return -EINVAL; + } + +@@ -2895,7 +2895,7 @@ int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir, + buf[cnt].used = dir ^ 1; + buf[cnt].size = bufsz; + buf[cnt].actual_size = bufsz; +- pr_debug("%s: data[%p]phys[%pa][%p]\n", __func__, ++ pr_debug("%s: data[%pK]phys[%pK][%pK]\n", __func__, + buf[cnt].data, + &buf[cnt].phys, + &buf[cnt].phys); +@@ -2992,7 +2992,7 @@ int afe_cmd_memory_map(phys_addr_t dma_addr_p, u32 dma_buf_sz) + mregion_pl->shm_addr_msw = populate_upper_32_bits(dma_addr_p); + mregion_pl->mem_size_bytes = dma_buf_sz; + +- pr_debug("%s: dma_addr_p 0x%pa , size %d\n", __func__, ++ pr_debug("%s: dma_addr_p 0x%pK , size %d\n", __func__, + &dma_addr_p, dma_buf_sz); + atomic_set(&this_afe.state, 1); + atomic_set(&this_afe.status, 0); +@@ -3116,7 +3116,7 @@ int q6afe_audio_client_buf_free_contiguous(unsigned int dir, + cnt = port->max_buf_cnt - 1; + + if (port->buf[0].data) { +- pr_debug("%s: data[%p]phys[%pa][%p] , client[%p] handle[%p]\n", ++ pr_debug("%s: data[%pK]phys[%pK][%pK] , client[%pK] handle[%pK]\n", + __func__, + port->buf[0].data, + &port->buf[0].phys, +@@ -3371,7 +3371,7 @@ int afe_rt_proxy_port_write(phys_addr_t buf_addr_p, + ret = -ENODEV; + return ret; + } +- pr_debug("%s: buf_addr_p = 0x%pa bytes = %d\n", __func__, ++ pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__, + &buf_addr_p, bytes); + + afecmd_wr.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, +@@ -3407,7 +3407,7 @@ int afe_rt_proxy_port_read(phys_addr_t buf_addr_p, + ret = -ENODEV; + return ret; + } +- pr_debug("%s: buf_addr_p = 0x%pa bytes = %d\n", __func__, ++ pr_debug("%s: buf_addr_p = 0x%pK bytes = %d\n", __func__, + &buf_addr_p, bytes); + + afecmd_rd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, +@@ -4757,7 +4757,7 @@ static int afe_map_cal_data(int32_t cal_type, + pr_err("%s: mmap did not work! size = %zd ret %d\n", + __func__, + cal_block->map_data.map_size, ret); +- pr_debug("%s: mmap did not work! addr = 0x%pa, size = %zd\n", ++ pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size); +@@ -4904,7 +4904,7 @@ int afe_map_rtac_block(struct rtac_cal_block_data *cal_block) + result = afe_cmd_memory_map(cal_block->cal_data.paddr, + cal_block->map_data.map_size); + if (result < 0) { +- pr_err("%s: afe_cmd_memory_map failed for addr = 0x%pa, size = %d, err %d\n", ++ pr_err("%s: afe_cmd_memory_map failed for addr = 0x%pK, size = %d, err %d\n", + __func__, &cal_block->cal_data.paddr, + cal_block->map_data.map_size, result); + return result; +diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c +index 1c6e938..ab34ac1 100644 +--- a/sound/soc/msm/qdsp6v2/q6asm.c ++++ b/sound/soc/msm/qdsp6v2/q6asm.c +@@ -481,7 +481,7 @@ static int q6asm_map_cal_memory(struct cal_block_data *cal_block) + pr_err("%s: mmap did not work! size = %zd result %d\n", + __func__, + cal_block->map_data.map_size, result); +- pr_debug("%s: mmap did not work! addr = 0x%pa, size = %zd\n", ++ pr_debug("%s: mmap did not work! addr = 0x%pK, size = %zd\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size); +@@ -613,7 +613,7 @@ int send_asm_custom_topology(struct audio_client *ac) + asm_top.mem_map_handle = cal_block->map_data.q6map_handle; + asm_top.payload_size = cal_block->cal_data.size; + +- pr_debug("%s: Sending ASM_CMD_ADD_TOPOLOGIES payload = %pa, size = %d, map handle = 0x%x\n", ++ pr_debug("%s: Sending ASM_CMD_ADD_TOPOLOGIES payload = %pK, size = %d, map handle = 0x%x\n", + __func__, &cal_block->cal_data.paddr, + asm_top.payload_size, asm_top.mem_map_handle); + +@@ -621,7 +621,7 @@ int send_asm_custom_topology(struct audio_client *ac) + if (result < 0) { + pr_err("%s: Set topologies failed result %d\n", + __func__, result); +- pr_debug("%s: Set topologies failed payload = 0x%pa\n", ++ pr_debug("%s: Set topologies failed payload = 0x%pK\n", + __func__, &cal_block->cal_data.paddr); + goto unmap; + +@@ -631,7 +631,7 @@ int send_asm_custom_topology(struct audio_client *ac) + (atomic_read(&ac->mem_state) <= 0), 5*HZ); + if (!result) { + pr_err("%s: Set topologies failed timeout\n", __func__); +- pr_debug("%s: Set topologies failed after timedout payload = 0x%pa\n", ++ pr_debug("%s: Set topologies failed after timedout payload = 0x%pK\n", + __func__, &cal_block->cal_data.paddr); + result = -ETIMEDOUT; + goto unmap; +@@ -707,7 +707,7 @@ int q6asm_map_rtac_block(struct rtac_cal_block_data *cal_block) + pr_err("%s: mmap did not work! size = %d result %d\n", + __func__, + cal_block->map_data.map_size, result); +- pr_debug("%s: mmap did not work! addr = 0x%pa, size = %d\n", ++ pr_debug("%s: mmap did not work! addr = 0x%pK, size = %d\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size); +@@ -844,7 +844,7 @@ int q6asm_audio_client_buf_free_contiguous(unsigned int dir, + } + + if (port->buf[0].data) { +- pr_debug("%s: data[%p]phys[%pa][%p] , client[%p] handle[%p]\n", ++ pr_debug("%s: data[%pK]phys[%pK][%pK] , client[%pK] handle[%pK]\n", + __func__, + port->buf[0].data, + &port->buf[0].phys, +@@ -875,7 +875,7 @@ void q6asm_audio_client_free(struct audio_client *ac) + int loopcnt; + struct audio_port_data *port; + if (!ac) { +- pr_err("%s: ac %p\n", __func__, ac); ++ pr_err("%s: ac %pK\n", __func__, ac); + return; + } + if (!ac->session) { +@@ -1092,7 +1092,7 @@ int q6asm_audio_client_buf_alloc(unsigned int dir, + size_t len; + + if (!(ac) || ((dir != IN) && (dir != OUT))) { +- pr_err("%s: ac %p dir %d\n", __func__, ac, dir); ++ pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + return -EINVAL; + } + +@@ -1145,7 +1145,7 @@ int q6asm_audio_client_buf_alloc(unsigned int dir, + buf[cnt].used = 1; + buf[cnt].size = bufsz; + buf[cnt].actual_size = bufsz; +- pr_debug("%s: data[%p]phys[%pa][%p]\n", ++ pr_debug("%s: data[%pK]phys[%pK][%pK]\n", + __func__, + buf[cnt].data, + &buf[cnt].phys, +@@ -1182,7 +1182,7 @@ int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir, + int bytes_to_alloc; + + if (!(ac) || ((dir != IN) && (dir != OUT))) { +- pr_err("%s: ac %p dir %d\n", __func__, ac, dir); ++ pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + return -EINVAL; + } + +@@ -1251,7 +1251,7 @@ int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir, + buf[cnt].used = dir ^ 1; + buf[cnt].size = bufsz; + buf[cnt].actual_size = bufsz; +- pr_debug("%s: data[%p]phys[%pa][%p]\n", ++ pr_debug("%s: data[%pK]phys[%pK][%pK]\n", + __func__, + buf[cnt].data, + &buf[cnt].phys, +@@ -1294,7 +1294,7 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv) + payload = data->payload; + + if (data->opcode == RESET_EVENTS) { +- pr_debug("%s: Reset event is received: %d %d apr[%p]\n", ++ pr_debug("%s: Reset event is received: %d %d apr[%pK]\n", + __func__, + data->reset_event, + data->reset_proc, +@@ -1462,7 +1462,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) + return -EINVAL; + } + if (!q6asm_is_valid_audio_client(ac)) { +- pr_err("%s: audio client pointer is invalid, ac = %p\n", ++ pr_err("%s: audio client pointer is invalid, ac = %pK\n", + __func__, ac); + return -EINVAL; + } +@@ -1488,7 +1488,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) + atomic_set(&ac->reset, 1); + if (ac->apr == NULL) + ac->apr = ac->apr2; +- pr_debug("%s: Reset event is received: %d %d apr[%p]\n", ++ pr_debug("%s: Reset event is received: %d %d apr[%pK]\n", + __func__, + data->reset_event, data->reset_proc, ac->apr); + if (ac->cb) +@@ -1631,7 +1631,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) + payload[0] || + populate_upper_32_bits(port->buf[data->token].phys) != + payload[1]) { +- pr_debug("%s: Expected addr %pa\n", ++ pr_debug("%s: Expected addr %pK\n", + __func__, &port->buf[data->token].phys); + pr_err("%s: rxedl[0x%x] rxedu [0x%x]\n", + __func__, payload[0], payload[1]); +@@ -1717,7 +1717,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) + payload[READDONE_IDX_BUFADD_LSW] || + populate_upper_32_bits(port->buf[token].phys) != + payload[READDONE_IDX_BUFADD_MSW]) { +- dev_vdbg(ac->dev, "%s: Expected addr %pa\n", ++ dev_vdbg(ac->dev, "%s: Expected addr %pK\n", + __func__, &port->buf[token].phys); + pr_err("%s: rxedl[0x%x] rxedu[0x%x]\n", + __func__, +@@ -1802,7 +1802,7 @@ void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size, + struct audio_port_data *port; + + if (!ac || ((dir != IN) && (dir != OUT))) { +- pr_err("%s: ac %p dir %d\n", __func__, ac, dir); ++ pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + return NULL; + } + +@@ -1829,7 +1829,7 @@ void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size, + *size = port->buf[idx].actual_size; + *index = port->cpu_buf; + data = port->buf[idx].data; +- dev_vdbg(ac->dev, "%s: session[%d]index[%d] data[%p]size[%d]\n", ++ dev_vdbg(ac->dev, "%s: session[%d]index[%d] data[%pK]size[%d]\n", + __func__, + ac->session, + port->cpu_buf, +@@ -1854,7 +1854,7 @@ void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac, + struct audio_port_data *port; + + if (!ac || ((dir != IN) && (dir != OUT))) { +- pr_err("%s: ac %p dir %d\n", __func__, ac, dir); ++ pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + return NULL; + } + +@@ -1881,7 +1881,7 @@ void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac, + *size = port->buf[idx].actual_size; + *index = port->cpu_buf; + data = port->buf[idx].data; +- dev_vdbg(ac->dev, "%s: session[%d]index[%d] data[%p]size[%d]\n", ++ dev_vdbg(ac->dev, "%s: session[%d]index[%d] data[%pK]size[%d]\n", + __func__, ac->session, port->cpu_buf, + data, *size); + /* +@@ -1902,7 +1902,7 @@ int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac) + uint32_t idx; + + if (!ac || (dir != OUT)) { +- pr_err("%s: ac %p dir %d\n", __func__, ac, dir); ++ pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + return ret; + } + +@@ -2169,13 +2169,13 @@ int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format, + struct asm_stream_cmd_open_write_compressed open; + + if (ac == NULL) { +- pr_err("%s: ac[%p] NULL\n", __func__, ac); ++ pr_err("%s: ac[%pK] NULL\n", __func__, ac); + rc = -EINVAL; + goto fail_cmd; + } + + if (ac->apr == NULL) { +- pr_err("%s: APR handle[%p] NULL\n", __func__, ac->apr); ++ pr_err("%s: APR handle[%pK] NULL\n", __func__, ac->apr); + rc = -EINVAL; + goto fail_cmd; + } +@@ -4032,7 +4032,7 @@ int q6asm_memory_map(struct audio_client *ac, phys_addr_t buf_add, int dir, + + ac->port[dir].tmp_hdl = 0; + port = &ac->port[dir]; +- pr_debug("%s: buf_add 0x%pa, bufsz: %d\n", __func__, ++ pr_debug("%s: buf_add 0x%pK, bufsz: %d\n", __func__, + &buf_add, bufsz); + mregions->shm_addr_lsw = lower_32_bits(buf_add); + mregions->shm_addr_msw = populate_upper_32_bits(buf_add); +@@ -4218,7 +4218,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, + q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, TRUE, + ((ac->session << 8) | dir)); + atomic_set(&ac->mem_state, 1); +- pr_debug("%s: mmap_region=0x%p token=0x%x\n", __func__, ++ pr_debug("%s: mmap_region=0x%pK token=0x%x\n", __func__, + mmap_regions, ((ac->session << 8) | dir)); + + mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS; +@@ -4274,7 +4274,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, + buffer_node[i].mmap_hdl = ac->port[dir].tmp_hdl; + list_add_tail(&buffer_node[i].list, + &ac->port[dir].mem_map_handle); +- pr_debug("%s: i=%d, bufadd[i] = 0x%pa, maphdl[i] = 0x%x\n", ++ pr_debug("%s: i=%d, bufadd[i] = 0x%pK, maphdl[i] = 0x%x\n", + __func__, i, &buffer_node[i].buf_phys_addr, + buffer_node[i].mmap_hdl); + } +@@ -4501,7 +4501,7 @@ int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size, + struct asm_dts_eagle_param *ad; + + if (!ac || ac->apr == NULL || (size == 0) || !data) { +- pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %p.\n", ++ pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %pK.\n", + __func__, size, data); + return -EINVAL; + } +@@ -4512,7 +4512,7 @@ int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size, + __func__, sz); + return -ENOMEM; + } +- pr_debug("DTS_EAGLE_ASM - %s: ac %p param_id 0x%x size %u data %p m_id 0x%x\n", ++ pr_debug("DTS_EAGLE_ASM - %s: ac %pK param_id 0x%x size %u data %pK m_id 0x%x\n", + __func__, ac, param_id, size, data, m_id); + q6asm_add_hdr_async(ac, &ad->hdr, sz, 1); + ad->hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; +@@ -4531,8 +4531,8 @@ int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size, + if (po) { + struct list_head *ptr, *next; + struct asm_buffer_node *node; +- pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %p, physical %lu)\n", +- __func__, po->kvaddr, (long)po->paddr); ++ pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %pK, physical %pK)\n", ++ __func__, po->kvaddr, &po->paddr); + ad->param.data_payload_addr_lsw = lower_32_bits(po->paddr); + ad->param.data_payload_addr_msw = populate_upper_32_bits( + po->paddr); +@@ -4599,7 +4599,7 @@ int q6asm_dts_eagle_get(struct audio_client *ac, int param_id, uint32_t size, + (po ? 0 : size); + + if (!ac || ac->apr == NULL || (size == 0) || !data) { +- pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %p\n", ++ pr_err("DTS_EAGLE_ASM - %s: APR handle NULL, invalid size %u or pointer %pK\n", + __func__, size, data); + return -EINVAL; + } +@@ -4609,7 +4609,7 @@ int q6asm_dts_eagle_get(struct audio_client *ac, int param_id, uint32_t size, + __func__, sz); + return -ENOMEM; + } +- pr_debug("DTS_EAGLE_ASM - %s: ac %p param_id 0x%x size %u data %p m_id 0x%x\n", ++ pr_debug("DTS_EAGLE_ASM - %s: ac %pK param_id 0x%x size %u data %pK m_id 0x%x\n", + __func__, ac, param_id, size, data, m_id); + q6asm_add_hdr(ac, &ad->hdr, sz, TRUE); + ad->hdr.opcode = ASM_STREAM_CMD_GET_PP_PARAMS_V2; +@@ -4634,8 +4634,8 @@ int q6asm_dts_eagle_get(struct audio_client *ac, int param_id, uint32_t size, + if (po) { + struct list_head *ptr, *next; + struct asm_buffer_node *node; +- pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %p, physical %lu)\n", +- __func__, po->kvaddr, (long)po->paddr); ++ pr_debug("DTS_EAGLE_ASM - %s: using out of band memory (virtual %pK, physical %pK)\n", ++ __func__, po->kvaddr, &po->paddr); + ad->param.data_payload_addr_lsw = lower_32_bits(po->paddr); + ad->param.data_payload_addr_msw = populate_upper_32_bits( + po->paddr); +@@ -5066,7 +5066,7 @@ static int __q6asm_read(struct audio_client *ac, bool is_custom_len_reqd, + } + ab = &port->buf[dsp_buf]; + +- dev_vdbg(ac->dev, "%s: session[%d]dsp-buf[%d][%p]cpu_buf[%d][%pa]\n", ++ dev_vdbg(ac->dev, "%s: session[%d]dsp-buf[%d][%pK]cpu_buf[%d][%pK]\n", + __func__, + ac->session, + dsp_buf, +@@ -5092,7 +5092,7 @@ static int __q6asm_read(struct audio_client *ac, bool is_custom_len_reqd, + port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf, + port->max_buf_cnt); + mutex_unlock(&port->lock); +- dev_vdbg(ac->dev, "%s: buf add[%pa] token[%d] uid[%d]\n", ++ dev_vdbg(ac->dev, "%s: buf add[%pK] token[%d] uid[%d]\n", + __func__, &ab->phys, read.hdr.token, + read.seq_id); + rc = apr_send_pkt(ac->apr, (uint32_t *) &read); +@@ -5144,7 +5144,7 @@ int q6asm_read_nolock(struct audio_client *ac) + dsp_buf = port->dsp_buf; + ab = &port->buf[dsp_buf]; + +- dev_vdbg(ac->dev, "%s: session[%d]dsp-buf[%d][%p]cpu_buf[%d][%pa]\n", ++ dev_vdbg(ac->dev, "%s: session[%d]dsp-buf[%d][%pK]cpu_buf[%d][%pK]\n", + __func__, + ac->session, + dsp_buf, +@@ -5170,7 +5170,7 @@ int q6asm_read_nolock(struct audio_client *ac) + + port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf, + port->max_buf_cnt); +- dev_vdbg(ac->dev, "%s: buf add[%pa] token[%d] uid[%d]\n", ++ dev_vdbg(ac->dev, "%s: buf add[%pK] token[%d] uid[%d]\n", + __func__, &ab->phys, read.hdr.token, + read.seq_id); + rc = apr_send_pkt(ac->apr, (uint32_t *) &read); +@@ -5233,7 +5233,7 @@ int q6asm_async_write(struct audio_client *ac, + else + lbuf_phys_addr = param->paddr; + +- dev_vdbg(ac->dev, "%s: token[0x%x], buf_addr[%pa], buf_size[0x%x], ts_msw[0x%x], ts_lsw[0x%x], lbuf_phys_addr: 0x[%pa]\n", ++ dev_vdbg(ac->dev, "%s: token[0x%x], buf_addr[%pK], buf_size[0x%x], ts_msw[0x%x], ts_lsw[0x%x], lbuf_phys_addr: 0x[%pK]\n", + __func__, + write.hdr.token, ¶m->paddr, + write.buf_size, write.timestamp_msw, +@@ -5381,7 +5381,7 @@ int q6asm_write(struct audio_client *ac, uint32_t len, uint32_t msw_ts, + list); + write.mem_map_handle = buf_node->mmap_hdl; + +- dev_vdbg(ac->dev, "%s: ab->phys[%pa]bufadd[0x%x] token[0x%x]buf_id[0x%x]buf_size[0x%x]mmaphdl[0x%x]" ++ dev_vdbg(ac->dev, "%s: ab->phys[%pK]bufadd[0x%x] token[0x%x]buf_id[0x%x]buf_size[0x%x]mmaphdl[0x%x]" + , __func__, + &ab->phys, + write.buf_addr_lsw, +@@ -5455,7 +5455,7 @@ int q6asm_write_nolock(struct audio_client *ac, uint32_t len, uint32_t msw_ts, + port->dsp_buf = q6asm_get_next_buf(ac, port->dsp_buf, + port->max_buf_cnt); + +- dev_vdbg(ac->dev, "%s: ab->phys[%pa]bufadd[0x%x]token[0x%x] buf_id[0x%x]buf_size[0x%x]mmaphdl[0x%x]" ++ dev_vdbg(ac->dev, "%s: ab->phys[%pK]bufadd[0x%x]token[0x%x] buf_id[0x%x]buf_size[0x%x]mmaphdl[0x%x]" + , __func__, + &ab->phys, + write.buf_addr_lsw, +diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c +index 0c85d60..41ebf63 100644 +--- a/sound/soc/msm/qdsp6v2/q6core.c ++++ b/sound/soc/msm/qdsp6v2/q6core.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -184,7 +184,7 @@ void ocm_core_open(void) + if (q6core_lcl.core_handle_q == NULL) + q6core_lcl.core_handle_q = apr_register("ADSP", "CORE", + aprv2_core_fn_q, 0xFFFFFFFF, NULL); +- pr_debug("%s: Open_q %p\n", __func__, q6core_lcl.core_handle_q); ++ pr_debug("%s: Open_q %pK\n", __func__, q6core_lcl.core_handle_q); + if (q6core_lcl.core_handle_q == NULL) { + if (__ratelimit(&rl)) + pr_err("%s: Unable to register CORE\n", +@@ -347,7 +347,7 @@ int core_dts_eagle_set(int size, char *data) + + pr_debug("DTS_EAGLE_CORE - %s\n", __func__); + if (size <= 0 || !data) { +- pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %p.\n", ++ pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %pK.\n", + __func__, size, data); + return -EINVAL; + } +@@ -393,7 +393,7 @@ int core_dts_eagle_get(int id, int size, char *data) + + pr_debug("DTS_EAGLE_CORE - %s\n", __func__); + if (size <= 0 || !data) { +- pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %p.\n", ++ pr_err("DTS_EAGLE_CORE - %s: invalid size %i or pointer %pK.\n", + __func__, size, data); + return -EINVAL; + } +diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c +index 02ba8e4..fa2ab564 100644 +--- a/sound/soc/msm/qdsp6v2/q6lsm.c ++++ b/sound/soc/msm/qdsp6v2/q6lsm.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2016, 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 +@@ -134,7 +134,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv) + uint32_t *payload; + + if (!client || !data) { +- pr_err("%s: client %p data %p\n", ++ pr_err("%s: client %pK data %pK\n", + __func__, client, data); + WARN_ON(1); + return -EINVAL; +@@ -886,7 +886,7 @@ int q6lsm_register_sound_model(struct lsm_client *client, + rmb(); + cmd.mem_map_handle = client->sound_model.mem_map_handle; + +- pr_debug("%s: addr %pa, size %d, handle 0x%x\n", __func__, ++ pr_debug("%s: addr %pK, size %d, handle 0x%x\n", __func__, + &client->sound_model.phys, cmd.model_size, cmd.mem_map_handle); + rc = q6lsm_apr_send_pkt(client, client->apr, &cmd, true, NULL); + if (rc) +@@ -960,7 +960,7 @@ static int q6lsm_memory_map_regions(struct lsm_client *client, + int rc; + int cmd_size = 0; + +- pr_debug("%s: dma_addr_p 0x%pa, dma_buf_sz %d, mmap_p 0x%p, session %d\n", ++ pr_debug("%s: dma_addr_p 0x%pK, dma_buf_sz %d, mmap_p 0x%pK, session %d\n", + __func__, &dma_addr_p, dma_buf_sz, mmap_p, + client->session); + if (CHECK_SESSION(client->session)) { +@@ -1240,7 +1240,7 @@ int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len, + if (cal_block == NULL) + goto fail; + +- pr_debug("%s:Snd Model len = %zd cal size %zd phys addr %pa", __func__, ++ pr_debug("%s:Snd Model len = %zd cal size %zd phys addr %pK", __func__, + len, cal_block->cal_data.size, + &cal_block->cal_data.paddr); + if (!cal_block->cal_data.paddr) { +@@ -1295,8 +1295,8 @@ int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len, + memcpy((client->sound_model.data + pad_zero + + client->sound_model.size), + (uint32_t *)cal_block->cal_data.kvaddr, client->lsm_cal_size); +- pr_debug("%s: Copy cal start virt_addr %p phy_addr %pa\n" +- "Offset cal virtual Addr %p\n", __func__, ++ pr_debug("%s: Copy cal start virt_addr %pK phy_addr %pK\n" ++ "Offset cal virtual Addr %pK\n", __func__, + client->sound_model.data, &client->sound_model.phys, + (pad_zero + client->sound_model.data + + client->sound_model.size)); +@@ -1610,7 +1610,7 @@ int q6lsm_lab_control(struct lsm_client *client, u32 enable) + u32 param_size; + + if (!client) { +- pr_err("%s: invalid param client %p\n", __func__, client); ++ pr_err("%s: invalid param client %pK\n", __func__, client); + return -EINVAL; + } + /* enable/disable lab on dsp */ +@@ -1667,7 +1667,7 @@ int q6lsm_stop_lab(struct lsm_client *client) + { + int rc = 0; + if (!client) { +- pr_err("%s: invalid param client %p\n", __func__, client); ++ pr_err("%s: invalid param client %pK\n", __func__, client); + return -EINVAL; + } + rc = q6lsm_cmd(client, LSM_SESSION_CMD_EOB, true); +@@ -1680,7 +1680,7 @@ int q6lsm_read(struct lsm_client *client, struct lsm_cmd_read *read) + { + int rc = 0; + if (!client || !read) { +- pr_err("%s: Invalid params client %p read %p\n", __func__, ++ pr_err("%s: Invalid params client %pK read %pK\n", __func__, + client, read); + return -EINVAL; + } +@@ -1750,7 +1750,7 @@ int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc) + kfree(client->lab_buffer); + client->lab_buffer = NULL; + } else { +- pr_debug("%s: Memory map handle %x phys %pa size %d\n", ++ pr_debug("%s: Memory map handle %x phys %pK size %d\n", + __func__, + client->lab_buffer[0].mem_map_handle, + &client->lab_buffer[0].phys, +diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c +index 04909d3..face98c 100644 +--- a/sound/soc/msm/qdsp6v2/q6voice.c ++++ b/sound/soc/msm/qdsp6v2/q6voice.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -348,7 +348,7 @@ static struct voice_data *voice_get_session(u32 session_id) + break; + } + +- pr_debug("%s:session_id 0x%x session handle %p\n", ++ pr_debug("%s:session_id 0x%x session handle %pK\n", + __func__, session_id, v); + + return v; +@@ -3087,7 +3087,7 @@ static int voice_map_cal_memory(struct cal_block_data *cal_block, + cal_block->map_data.map_size, + VOC_CAL_MEM_MAP_TOKEN); + if (result < 0) { +- pr_err("%s: Mmap did not work! addr = 0x%pa, size = %zd\n", ++ pr_err("%s: Mmap did not work! addr = 0x%pK, size = %zd\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size); +@@ -3120,7 +3120,7 @@ static int remap_cal_data(struct cal_block_data *cal_block, + goto done; + } + } else { +- pr_debug("%s: Cal block 0x%pa, size %zd already mapped. Q6 map handle = %d\n", ++ pr_debug("%s: Cal block 0x%pK, size %zd already mapped. Q6 map handle = %d\n", + __func__, &cal_block->cal_data.paddr, + cal_block->map_data.map_size, + cal_block->map_data.q6map_handle); +@@ -3318,7 +3318,7 @@ int voc_map_rtac_block(struct rtac_cal_block_data *cal_block) + if (!is_rtac_memory_allocated()) { + result = voice_alloc_rtac_mem_map_table(); + if (result < 0) { +- pr_err("%s: RTAC alloc mem map table did not work! addr = 0x%pa, size = %d\n", ++ pr_err("%s: RTAC alloc mem map table did not work! addr = 0x%pK, size = %d\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size); +@@ -3333,7 +3333,7 @@ int voc_map_rtac_block(struct rtac_cal_block_data *cal_block) + cal_block->map_data.map_size, + VOC_RTAC_MEM_MAP_TOKEN); + if (result < 0) { +- pr_err("%s: RTAC mmap did not work! addr = 0x%pa, size = %d\n", ++ pr_err("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n", + __func__, + &cal_block->cal_data.paddr, + cal_block->map_data.map_size); +@@ -4444,7 +4444,7 @@ int voc_start_record(uint32_t port_id, uint32_t set, uint32_t session_id) + + break; + } +- pr_debug("%s: port_id: %d, set: %d, v: %p\n", ++ pr_debug("%s: port_id: %d, set: %d, v: %pK\n", + __func__, port_id, set, v); + + mutex_lock(&v->lock); +@@ -6510,12 +6510,12 @@ static int voice_alloc_oob_shared_mem(void) + cnt++; + } + +- pr_debug("%s buf[0].data:[%p], buf[0].phys:[%pa], &buf[0].phys:[%p],\n", ++ pr_debug("%s buf[0].data:[%pK], buf[0].phys:[%pK], &buf[0].phys:[%pK],\n", + __func__, + (void *)v->shmem_info.sh_buf.buf[0].data, + &v->shmem_info.sh_buf.buf[0].phys, + (void *)&v->shmem_info.sh_buf.buf[0].phys); +- pr_debug("%s: buf[1].data:[%p], buf[1].phys[%pa], &buf[1].phys[%p]\n", ++ pr_debug("%s: buf[1].data:[%pK], buf[1].phys[%pK], &buf[1].phys[%pK]\n", + __func__, + (void *)v->shmem_info.sh_buf.buf[1].data, + &v->shmem_info.sh_buf.buf[1].phys, +@@ -6557,7 +6557,7 @@ static int voice_alloc_oob_mem_table(void) + } + + v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t); +- pr_debug("%s data[%p]phys[%pa][%p]\n", __func__, ++ pr_debug("%s data[%pK]phys[%pK][%pK]\n", __func__, + (void *)v->shmem_info.memtbl.data, + &v->shmem_info.memtbl.phys, + (void *)&v->shmem_info.memtbl.phys); +@@ -6909,7 +6909,7 @@ static int voice_alloc_cal_mem_map_table(void) + } + + common.cal_mem_map_table.size = sizeof(struct vss_imemory_table_t); +- pr_debug("%s: data %p phys %pa\n", __func__, ++ pr_debug("%s: data %pK phys %pK\n", __func__, + common.cal_mem_map_table.data, + &common.cal_mem_map_table.phys); + +@@ -6936,7 +6936,7 @@ static int voice_alloc_rtac_mem_map_table(void) + } + + common.rtac_mem_map_table.size = sizeof(struct vss_imemory_table_t); +- pr_debug("%s: data %p phys %pa\n", __func__, ++ pr_debug("%s: data %pK phys %pK\n", __func__, + common.rtac_mem_map_table.data, + &common.rtac_mem_map_table.phys); + +@@ -7537,7 +7537,7 @@ static int voice_alloc_source_tracking_shared_memory(void) + memset((void *)(common.source_tracking_sh_mem.sh_mem_block.data), 0, + common.source_tracking_sh_mem.sh_mem_block.size); + +- pr_debug("%s: sh_mem_block: phys:[%pa], data:[0x%p], size:[%zd]\n", ++ pr_debug("%s: sh_mem_block: phys:[%pK], data:[0x%pK], size:[%zd]\n", + __func__, + &(common.source_tracking_sh_mem.sh_mem_block.phys), + (void *)(common.source_tracking_sh_mem.sh_mem_block.data), +@@ -7568,7 +7568,7 @@ static int voice_alloc_source_tracking_shared_memory(void) + memset((void *)(common.source_tracking_sh_mem.sh_mem_table.data), 0, + common.source_tracking_sh_mem.sh_mem_table.size); + +- pr_debug("%s sh_mem_table: phys:[%pa], data:[0x%p], size:[%zd],\n", ++ pr_debug("%s sh_mem_table: phys:[%pK], data:[0x%pK], size:[%zd],\n", + __func__, + &(common.source_tracking_sh_mem.sh_mem_table.phys), + (void *)(common.source_tracking_sh_mem.sh_mem_table.data), +diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c +index b1954a4..feed251 100644 +--- a/sound/soc/msm/qdsp6v2/rtac.c ++++ b/sound/soc/msm/qdsp6v2/rtac.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2016, The 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 +@@ -177,7 +177,7 @@ int rtac_allocate_cal_buffer(uint32_t cal_type) + } + + if (rtac_cal[cal_type].cal_data.paddr != 0) { +- pr_err("%s: memory already allocated! cal_type %d, paddr 0x%pa\n", ++ pr_err("%s: memory already allocated! cal_type %d, paddr 0x%pK\n", + __func__, cal_type, &rtac_cal[cal_type].cal_data.paddr); + result = -EPERM; + goto done; +@@ -196,7 +196,7 @@ int rtac_allocate_cal_buffer(uint32_t cal_type) + goto done; + } + +- pr_debug("%s: cal_type %d, paddr 0x%pa, kvaddr 0x%p, map_size 0x%x\n", ++ pr_debug("%s: cal_type %d, paddr 0x%pK, kvaddr 0x%pK, map_size 0x%x\n", + __func__, cal_type, + &rtac_cal[cal_type].cal_data.paddr, + rtac_cal[cal_type].cal_data.kvaddr, +@@ -226,7 +226,7 @@ int rtac_free_cal_buffer(uint32_t cal_type) + result = msm_audio_ion_free(rtac_cal[cal_type].map_data.ion_client, + rtac_cal[cal_type].map_data.ion_handle); + if (result < 0) { +- pr_err("%s: ION free for RTAC failed! cal_type %d, paddr 0x%pa\n", ++ pr_err("%s: ION free for RTAC failed! cal_type %d, paddr 0x%pK\n", + __func__, cal_type, &rtac_cal[cal_type].cal_data.paddr); + goto done; + } +@@ -671,7 +671,7 @@ static int get_voice_index(u32 mode, u32 handle) + /* ADM APR */ + void rtac_set_adm_handle(void *handle) + { +- pr_debug("%s: handle = %p\n", __func__, handle); ++ pr_debug("%s: handle = %pK\n", __func__, handle); + + mutex_lock(&rtac_adm_apr_mutex); + rtac_adm_apr_data.apr_handle = handle; +@@ -729,7 +729,7 @@ u32 send_adm_apr(void *buf, u32 opcode) + + if (copy_from_user(&user_buf_size, (void *)buf, + sizeof(user_buf_size))) { +- pr_err("%s: Copy from user failed! buf = 0x%p\n", ++ pr_err("%s: Copy from user failed! buf = 0x%pK\n", + __func__, buf); + goto done; + } +@@ -829,7 +829,7 @@ u32 send_adm_apr(void *buf, u32 opcode) + memcpy(rtac_adm_buffer, &adm_params, sizeof(adm_params)); + atomic_set(&rtac_adm_apr_data.cmd_state, 1); + +- pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pa\n", ++ pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pK\n", + __func__, opcode, + &rtac_cal[ADM_RTAC_CAL].cal_data.paddr); + +@@ -948,7 +948,7 @@ u32 send_rtac_asm_apr(void *buf, u32 opcode) + + if (copy_from_user(&user_buf_size, (void *)buf, + sizeof(user_buf_size))) { +- pr_err("%s: Copy from user failed! buf = 0x%p\n", ++ pr_err("%s: Copy from user failed! buf = 0x%pK\n", + __func__, buf); + goto done; + } +@@ -1048,7 +1048,7 @@ u32 send_rtac_asm_apr(void *buf, u32 opcode) + memcpy(rtac_asm_buffer, &asm_params, sizeof(asm_params)); + atomic_set(&rtac_asm_apr_data[session_id].cmd_state, 1); + +- pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pa\n", ++ pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pK\n", + __func__, opcode, + &rtac_cal[ASM_RTAC_CAL].cal_data.paddr); + +@@ -1188,7 +1188,7 @@ static u32 send_rtac_afe_apr(void *buf, uint32_t opcode) + + if (copy_from_user(&user_afe_buf, (void *)buf, + sizeof(struct rtac_afe_user_data))) { +- pr_err("%s: Copy from user failed! buf = 0x%p\n", ++ pr_err("%s: Copy from user failed! buf = 0x%pK\n", + __func__, buf); + goto done; + } +@@ -1304,7 +1304,7 @@ static u32 send_rtac_afe_apr(void *buf, uint32_t opcode) + + atomic_set(&rtac_afe_apr_data.cmd_state, 1); + +- pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pa\n", ++ pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pK\n", + __func__, opcode, + &rtac_cal[AFE_RTAC_CAL].cal_data.paddr); + +@@ -1428,7 +1428,7 @@ u32 send_voice_apr(u32 mode, void *buf, u32 opcode) + + if (copy_from_user(&user_buf_size, (void *)buf, + sizeof(user_buf_size))) { +- pr_err("%s: Copy from user failed! buf = 0x%p\n", ++ pr_err("%s: Copy from user failed! buf = 0x%pK\n", + __func__, buf); + goto done; + } +@@ -1529,7 +1529,7 @@ u32 send_voice_apr(u32 mode, void *buf, u32 opcode) + memcpy(rtac_voice_buffer, &voice_params, sizeof(voice_params)); + atomic_set(&rtac_voice_apr_data[mode].cmd_state, 1); + +- pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pa\n", ++ pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pK\n", + __func__, opcode, + &rtac_cal[VOICE_RTAC_CAL].cal_data.paddr); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8412/0.patch b/Patches/Linux_CVEs/CVE-2016-8412/0.patch new file mode 100644 index 00000000..2c1b2231 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8412/0.patch @@ -0,0 +1,36 @@ +From 42a98c44669d92dafcf4d6336bdccaeb2db12786 Mon Sep 17 00:00:00 2001 +From: Sureshnaidu Laveti +Date: Mon, 3 Oct 2016 04:01:32 -0700 +Subject: msm: sensor: Adding mutex for actuator power down operations + +Protecting operations performed during actuator powerdown +from race condition by adding mutex. +CRs-Fixed: 1071891 + +Change-Id: I7d6b2e8878788615c02678a4a28d31dca0ed6bca +Signed-off-by: Sureshnaidu Laveti +--- + drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c | 2 ++ + 1 file changed, 2 insertions(+) + +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 bf39738..a700f83 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 +@@ -1559,11 +1559,13 @@ static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd, + pr_err("a_ctrl->i2c_client.i2c_func_tbl NULL\n"); + return -EINVAL; + } ++ mutex_lock(a_ctrl->actuator_mutex); + rc = msm_actuator_power_down(a_ctrl); + if (rc < 0) { + pr_err("%s:%d Actuator Power down failed\n", + __func__, __LINE__); + } ++ mutex_unlock(a_ctrl->actuator_mutex); + return msm_actuator_close(sd, NULL); + default: + return -ENOIOCTLCMD; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8413/0.patch b/Patches/Linux_CVEs/CVE-2016-8413/0.patch new file mode 100644 index 00000000..9088b767 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8413/0.patch @@ -0,0 +1,33 @@ +From bc77232707df371ff6bab9350ae39676535c0e9d Mon Sep 17 00:00:00 2001 +From: Krishnankutty Kolathappilly +Date: Wed, 16 Nov 2016 18:22:58 -0800 +Subject: msm: cpp: Fix for buffer overflow in cpp. + +Fix for buffer overflow while handling ioctl. +Instead of checking for length boundary, fix checks +for exact length. + +CRs-Fixed: 518731 +Change-Id: I9002f84b219e8b06ae0672d87c2d999e728a75aa +Signed-off-by: Krishnankutty Kolathappilly +--- + drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 3 +-- + 1 file changed, 1 insertion(+), 2 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 022dd6b..0792380 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 +@@ -2070,8 +2070,7 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, + uint32_t identity; + struct msm_cpp_buff_queue_info_t *buff_queue_info; + CPP_DBG("VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO\n"); +- if ((ioctl_ptr->len == 0) || +- (ioctl_ptr->len > sizeof(uint32_t))) { ++ if (ioctl_ptr->len != sizeof(uint32_t)) { + mutex_unlock(&cpp_dev->mutex); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8414/0.patch b/Patches/Linux_CVEs/CVE-2016-8414/0.patch new file mode 100644 index 00000000..b3c39fb7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8414/0.patch @@ -0,0 +1,52 @@ +From 320970d3da9b091e96746424c44649a91852a846 Mon Sep 17 00:00:00 2001 +From: Swetha Chikkaboraiah +Date: Wed, 2 Nov 2016 16:49:41 +0530 +Subject: qcom: scm: remove printing input arguments + +scm_call2 is printing the input arguments if TZ ret value is < 0 +leading to information leak. Remove printing input arguments. + +Change-Id: I21dd6d83fa979aed2c79ebb2c9c8de63a247dded +CRs-Fixed: 1076407 +Signed-off-by: Swetha Chikkaboraiah +--- + drivers/soc/qcom/scm.c | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c +index 795f33d..d057328 100644 +--- a/drivers/soc/qcom/scm.c ++++ b/drivers/soc/qcom/scm.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2016, The 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 +@@ -644,10 +644,6 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) + + desc->ret[0] = desc->ret[1] = desc->ret[2] = 0; + +- pr_debug("scm_call: func id %#llx, args: %#x, %#llx, %#llx, %#llx, %#llx\n", +- x0, desc->arginfo, desc->args[0], desc->args[1], +- desc->args[2], desc->x5); +- + if (scm_version == SCM_ARMV8_64) + ret = __scm_call_armv8_64(x0, desc->arginfo, + desc->args[0], desc->args[1], +@@ -667,10 +663,8 @@ int scm_call2(u32 fn_id, struct scm_desc *desc) + } while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY)); + + if (ret < 0) +- pr_err("scm_call failed: func id %#llx, arginfo: %#x, args: %#llx, %#llx, %#llx, %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n", +- x0, desc->arginfo, desc->args[0], desc->args[1], +- desc->args[2], desc->x5, ret, desc->ret[0], +- desc->ret[1], desc->ret[2]); ++ pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n", ++ x0, ret, desc->ret[0], desc->ret[1], desc->ret[2]); + + if (arglen > N_REGISTER_ARGS) + kfree(desc->extra_arg_buf); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8415/0.patch b/Patches/Linux_CVEs/CVE-2016-8415/0.patch new file mode 100644 index 00000000..181f800f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8415/0.patch @@ -0,0 +1,48 @@ +From 188e12a816508b11771f362c852782ec9a6f9394 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Wed, 19 Oct 2016 07:25:33 -0700 +Subject: qcacld-2.0: Fix hdd_ocb_config_new() signature + +hdd_ocb_config_new() takes four "length" parameters, currently defined +to be of type 'int'. Since these are summed to calculate the size of a +dynamic memory allocation they must be non-negative so change them to +'uint32_t'. + +Change-Id: Ie66bbb7c69aba92d9d846cb90628110b3bea8f74 +CRs-Fixed: 1079596 +--- + CORE/HDD/src/wlan_hdd_ocb.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_ocb.c b/CORE/HDD/src/wlan_hdd_ocb.c +index b6494ca..95fde5e 100644 +--- a/CORE/HDD/src/wlan_hdd_ocb.c ++++ b/CORE/HDD/src/wlan_hdd_ocb.c +@@ -406,10 +406,11 @@ static int hdd_ocb_register_sta(hdd_adapter_t *adapter) + * + * Return: A pointer to the OCB configuration struct, NULL on failure. + */ +-static struct sir_ocb_config *hdd_ocb_config_new(int num_channels, +- int num_schedule, +- int ndl_chan_list_len, +- int ndl_active_state_list_len) ++static ++struct sir_ocb_config *hdd_ocb_config_new(uint32_t num_channels, ++ uint32_t num_schedule, ++ uint32_t ndl_chan_list_len, ++ uint32_t ndl_active_state_list_len) + { + struct sir_ocb_config *ret = 0; + uint32_t len; +@@ -903,7 +904,7 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, + void *def_tx_param = NULL; + uint32_t def_tx_param_size = 0; + int i; +- int channel_count, schedule_size; ++ uint32_t channel_count, schedule_size; + struct sir_ocb_config *config; + int rc = -EINVAL; + uint8_t *mac_addr; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8415/1.patch b/Patches/Linux_CVEs/CVE-2016-8415/1.patch new file mode 100644 index 00000000..2321f4a1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8415/1.patch @@ -0,0 +1,47 @@ +From c3ef29be79ea5d1c67cde62c7666cb6d4778383c Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Fri, 21 Oct 2016 14:17:14 -0700 +Subject: [PATCH] qcacld-2.0: Fix hdd_ocb_config_new() signature + +hdd_ocb_config_new() takes four "length" parameters, currently defined +to be of type 'int'. Since these are summed to calculate the size of a +dynamic memory allocation they must be non-negative so change them to +'uint32_t'. + +Change-Id: Ie66bbb7c69aba92d9d846cb90628110b3bea8f74 +CRs-Fixed: 1079596 +Bug: 31750554 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c +index 3e2d88987e013..eec9b9e094480 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_ocb.c +@@ -406,10 +406,11 @@ static int hdd_ocb_register_sta(hdd_adapter_t *adapter) + * + * Return: A pointer to the OCB configuration struct, NULL on failure. + */ +-static struct sir_ocb_config *hdd_ocb_config_new(int num_channels, +- int num_schedule, +- int ndl_chan_list_len, +- int ndl_active_state_list_len) ++static ++struct sir_ocb_config *hdd_ocb_config_new(uint32_t num_channels, ++ uint32_t num_schedule, ++ uint32_t ndl_chan_list_len, ++ uint32_t ndl_active_state_list_len) + { + struct sir_ocb_config *ret = 0; + uint32_t len; +@@ -904,7 +905,7 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, + void *def_tx_param = NULL; + uint32_t def_tx_param_size = 0; + int i; +- int channel_count, schedule_size; ++ uint32_t channel_count, schedule_size; + struct sir_ocb_config *config; + int rc = -EINVAL; + uint8_t *mac_addr; diff --git a/Patches/Linux_CVEs/CVE-2016-8416/0.patch b/Patches/Linux_CVEs/CVE-2016-8416/0.patch new file mode 100644 index 00000000..b08ceefb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8416/0.patch @@ -0,0 +1,73 @@ +From e3af5e89426f1c8d4e703d415eff5435b925649f Mon Sep 17 00:00:00 2001 +From: Benet Clark +Date: Thu, 10 Nov 2016 17:49:09 -0800 +Subject: msm: mdss: Clear compat structures before copying to user + +In the compat layer, the temporary structures used to convert +data from 32bit to 64bit structures need to be set to 0 before +being assigned values. + +CRs-Fixed: 1088206 +Change-Id: I04497bc11e01c3df4beadfd6d9b06ab4321f1723 +Signed-off-by: Benet Clark +--- + drivers/video/msm/mdss/mdss_compat_utils.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c +index 5ad51dd..a9ab5c1 100644 +--- a/drivers/video/msm/mdss/mdss_compat_utils.c ++++ b/drivers/video/msm/mdss/mdss_compat_utils.c +@@ -846,6 +846,7 @@ static int __from_user_pcc_coeff_v17( + return -EFAULT; + } + ++ memset(&pcc_cfg_payload, 0, sizeof(pcc_cfg_payload)); + pcc_cfg_payload.r.b = pcc_cfg_payload32.r.b; + pcc_cfg_payload.r.g = pcc_cfg_payload32.r.g; + pcc_cfg_payload.r.c = pcc_cfg_payload32.r.c; +@@ -1127,6 +1128,8 @@ static int __from_user_igc_lut_data_v17( + pr_err("failed to copy payload from user for igc\n"); + return -EFAULT; + } ++ ++ memset(&igc_cfg_payload, 0, sizeof(igc_cfg_payload)); + igc_cfg_payload.c0_c1_data = compat_ptr(igc_cfg_payload_32.c0_c1_data); + igc_cfg_payload.c2_data = compat_ptr(igc_cfg_payload_32.c2_data); + igc_cfg_payload.len = igc_cfg_payload_32.len; +@@ -1261,6 +1264,7 @@ static int __from_user_pgc_lut_data_v1_7( + pr_err("failed to copy from user the pgc32 payload\n"); + return -EFAULT; + } ++ memset(&pgc_cfg_payload, 0, sizeof(pgc_cfg_payload)); + pgc_cfg_payload.c0_data = compat_ptr(pgc_cfg_payload_32.c0_data); + pgc_cfg_payload.c1_data = compat_ptr(pgc_cfg_payload_32.c1_data); + pgc_cfg_payload.c2_data = compat_ptr(pgc_cfg_payload_32.c2_data); +@@ -1470,6 +1474,7 @@ static int __from_user_hist_lut_data_v1_7( + return -EFAULT; + } + ++ memset(&hist_lut_cfg_payload, 0, sizeof(hist_lut_cfg_payload)); + hist_lut_cfg_payload.len = hist_lut_cfg_payload32.len; + hist_lut_cfg_payload.data = compat_ptr(hist_lut_cfg_payload32.data); + +@@ -2024,6 +2029,7 @@ static int __from_user_pa_data_v1_7( + return -EFAULT; + } + ++ memset(&pa_cfg_payload, 0, sizeof(pa_cfg_payload)); + pa_cfg_payload.mode = pa_cfg_payload32.mode; + pa_cfg_payload.global_hue_adj = pa_cfg_payload32.global_hue_adj; + pa_cfg_payload.global_sat_adj = pa_cfg_payload32.global_sat_adj; +@@ -2280,6 +2286,8 @@ static int __from_user_gamut_cfg_data_v17( + pr_err("failed to copy the gamut payload from userspace\n"); + return -EFAULT; + } ++ ++ memset(&gamut_cfg_payload, 0, sizeof(gamut_cfg_payload)); + gamut_cfg_payload.mode = gamut_cfg_payload32.mode; + for (i = 0; i < MDP_GAMUT_TABLE_NUM_V1_7; i++) { + gamut_cfg_payload.tbl_size[i] = +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8417/0.patch b/Patches/Linux_CVEs/CVE-2016-8417/0.patch new file mode 100644 index 00000000..7a915874 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8417/0.patch @@ -0,0 +1,32 @@ +From 01dcc0a7cc23f23a89adf72393d5a27c6d576cd0 Mon Sep 17 00:00:00 2001 +From: Krishnankutty Kolathappilly +Date: Mon, 14 Nov 2016 18:46:12 -0800 +Subject: msm: camera: fix bound check of offset to avoid overread overwrite + +fix bound check of hw_cmd_p->offset in msm_jpeg_hw_exec_cmds +to avoid overread overwrite. + +CRs-Fixed: 1088824 + +Change-Id: Ifaa4b5387d4285ddce16d8e745aa0500c64c568b +Signed-off-by: Krishnankutty Kolathappilly +--- + drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c +index d67ab11..9bc37a0 100644 +--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c ++++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c +@@ -501,7 +501,7 @@ int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, uint32_t m_cmds, + uint32_t data; + + while (m_cmds--) { +- if (hw_cmd_p->offset > max_size) { ++ if (hw_cmd_p->offset >= max_size) { + JPEG_PR_ERR("%s:%d] %d exceed hw region %d\n", __func__, + __LINE__, hw_cmd_p->offset, max_size); + return -EFAULT; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8418/0.patch b/Patches/Linux_CVEs/CVE-2016-8418/0.patch new file mode 100644 index 00000000..5106e47e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8418/0.patch @@ -0,0 +1,42 @@ +From 8f8066581a8e575a7d57d27f36c4db63f91ca48f Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Mon, 24 Oct 2016 13:52:04 -0700 +Subject: msm: crypto: Fix integer over flow check in qce driver + +Integer overflow check is invalid when ULONG_MAX is used, +as ULONG_MAX has typeof 'unsigned long', while areq->assoclen, +q_req->crytlen, and qreq.ivsize are 'unsigned int'. Make change +to use UINT_MAX instead of ULONG_MAX. + +Change-Id: If2bb1900c07af1ea162da362c913d4880b0bc755 +Signed-off-by: Zhen Kong +--- + drivers/crypto/msm/qce.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c +index 7ddbb19..4cf95b9 100644 +--- a/drivers/crypto/msm/qce.c ++++ b/drivers/crypto/msm/qce.c +@@ -1,6 +1,6 @@ + /* Qualcomm Crypto Engine driver. + * +- * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2010-2016, The 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 +@@ -1962,8 +1962,8 @@ int qce_aead_req(void *handle, struct qce_req *q_req) + else + q_req->cryptlen = areq->cryptlen - authsize; + +- if ((q_req->cryptlen > ULONG_MAX - ivsize) || +- (q_req->cryptlen + ivsize > ULONG_MAX - areq->assoclen)) { ++ if ((q_req->cryptlen > UINT_MAX - ivsize) || ++ (q_req->cryptlen + ivsize > UINT_MAX - areq->assoclen)) { + pr_err("Integer overflow on total aead req length.\n"); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8419/0.patch b/Patches/Linux_CVEs/CVE-2016-8419/0.patch new file mode 100644 index 00000000..fd371144 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8419/0.patch @@ -0,0 +1,117 @@ +From 9ba50d536227666a5b6abd51f2b122675d950488 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Wed, 9 Nov 2016 09:01:10 -0800 +Subject: qcacld-2.0: Properly parse PNO vendor command + +Currently there is a single wlan_hdd_extscan_config_policy which +contains entries for both EXTSCAN and PNO attributes. However the +EXTSCAN and PNO attributes have separate and overlapping +assignments. Therefore one policy cannot be used by both types of +commands. In addition, when parsing nested PNO attributes the policy +is not used, and hence no checking is performed on the nested +data. This can result in a buffer overflow. + +To address these issues introduce a new policy for PNO vendor +commands, and use that policy both when parsing the initial command +and when parsing the nested attributes. Furthermore add a zero length +SSID check to prevent underflow. + +Change-Id: I92c8fc7ca1c44971502ea68b5486a2b3ae941cc5 +CRs-Fixed: 1087209 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 45 +++++++++++++++++++++++++++------------- + 1 file changed, 31 insertions(+), 14 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index c9e62c4..f488edc 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -842,11 +842,6 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = { .type = NLA_U32 }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = { .type = NLA_U32 }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = { .type = NLA_BINARY, +- .len = IEEE80211_MAX_SSID_LEN }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = { .type = NLA_U8 }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_SSID_LEN + 1 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = { .type = NLA_U32 }, +@@ -858,6 +853,23 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + }; + + static const struct nla_policy ++wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = { ++ .type = NLA_BINARY, ++ .len = IEEE80211_MAX_SSID_LEN + 1 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = { ++ .type = NLA_U8 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = { ++ .type = NLA_U8 ++ }, ++}; ++ ++static const struct nla_policy + wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = + { + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = { .type = NLA_U16 }, +@@ -4672,19 +4684,18 @@ static int hdd_extscan_epno_fill_network_list( + struct wifi_epno_params *req_msg, + struct nlattr **tb) + { +- struct nlattr *network[ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; ++ struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1]; + struct nlattr *networks; + int rem1, ssid_len; + uint8_t index, *ssid; + + index = 0; + nla_for_each_nested(networks, +- tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST], +- rem1) { +- if (nla_parse(network, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, +- nla_data(networks), nla_len(networks), NULL)) { ++ tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST], ++ rem1) { ++ if (nla_parse(network, QCA_WLAN_VENDOR_ATTR_PNO_MAX, ++ nla_data(networks), nla_len(networks), ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } +@@ -4697,6 +4708,12 @@ static int hdd_extscan_epno_fill_network_list( + ssid_len = nla_len( + network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]); + ++ /* nla_parse will detect overflow but not underflow */ ++ if (0 == ssid_len) { ++ hddLog(LOGE, FL("zero ssid length")); ++ return -EINVAL; ++ } ++ + /* Decrement by 1, don't count null character */ + ssid_len--; + +@@ -4771,8 +4788,8 @@ static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, +- data, data_len, +- wlan_hdd_extscan_config_policy)) { ++ data, data_len, ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8419/1.patch b/Patches/Linux_CVEs/CVE-2016-8419/1.patch new file mode 100644 index 00000000..2be193d6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8419/1.patch @@ -0,0 +1,102 @@ +From 5dcbbf80f4deb9b078cca860f6d1760d6f9398b8 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Wed, 9 Nov 2016 13:54:57 -0800 +Subject: [PATCH] qcacld-2.0: Properly parse PNO vendor command + +Currently there is a single wlan_hdd_extscan_config_policy which +contains entries for both EXTSCAN and PNO attributes. However the +EXTSCAN and PNO attributes have separate and overlapping +assignments. Therefore one policy cannot be used by both types of +commands. In addition, when parsing nested PNO attributes the policy +is not used, and hence no checking is performed on the nested +data. This can result in a buffer overflow. + +To address these issues introduce a new policy for PNO vendor +commands, and use that policy both when parsing the initial command +and when parsing the nested attributes. + +Change-Id: I92c8fc7ca1c44971502ea68b5486a2b3ae941cc5 +CRs-Fixed: 1087209 +Bug: 32454494 +Signed-off-by: Srinivas Girigowda +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 39 ++++++++++++++-------- + 1 file changed, 25 insertions(+), 14 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index ae8d13dd85b29..29f388fc7433f 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -842,11 +842,6 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = { .type = NLA_U32 }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = { .type = NLA_U32 }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = { .type = NLA_BINARY, +- .len = IEEE80211_MAX_SSID_LEN }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = { .type = NLA_U8 }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = { .type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_SSID_LEN + 1 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = { .type = NLA_U32 }, +@@ -858,6 +853,23 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + }; + + static const struct nla_policy ++wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = { ++ .type = NLA_BINARY, ++ .len = IEEE80211_MAX_SSID_LEN + 1 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = { ++ .type = NLA_U8 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = { ++ .type = NLA_U8 ++ }, ++}; ++ ++static const struct nla_policy + wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = + { + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = { .type = NLA_U16 }, +@@ -4675,19 +4687,18 @@ static int hdd_extscan_epno_fill_network_list( + struct wifi_epno_params *req_msg, + struct nlattr **tb) + { +- struct nlattr *network[ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; ++ struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1]; + struct nlattr *networks; + int rem1, ssid_len; + uint8_t index, *ssid; + + index = 0; + nla_for_each_nested(networks, +- tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST], +- rem1) { +- if (nla_parse(network, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, +- nla_data(networks), nla_len(networks), NULL)) { ++ tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST], ++ rem1) { ++ if (nla_parse(network, QCA_WLAN_VENDOR_ATTR_PNO_MAX, ++ nla_data(networks), nla_len(networks), ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } +@@ -4774,8 +4785,8 @@ static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, +- data, data_len, +- wlan_hdd_extscan_config_policy)) { ++ data, data_len, ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } diff --git a/Patches/Linux_CVEs/CVE-2016-8420/0.patch b/Patches/Linux_CVEs/CVE-2016-8420/0.patch new file mode 100644 index 00000000..1a0b35c6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8420/0.patch @@ -0,0 +1,56 @@ +From c6597e015a7ce5ee71d3725fc55e64fc50923f4e Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Wed, 9 Nov 2016 10:23:02 -0800 +Subject: qcacld-2.0: Avoid overflow of EPNO network list + +Currently when processing an EPNO vendor command the "num networks" +attribute is limit checked and if it exceeds a MAX value then it is +reset to that MAX value. This value is then used to calculate the size +of the buffer allocated to hold the internal representation of the +request. However later when the network attributes are parsed there is +no check to make sure the number of networks processed does not exceed +the (possibly modified) "num networks" used to allocate memory, and as +a result a buffer overflow can occur. Address this issue by aborting +the network parsing once "num networks" records have been parsed. + +Change-Id: I6e5f321d23471d082bb000ad0422ea9baa76577a +CRs-Fixed: 1087807 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 92cbb67..233482d 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -4825,11 +4825,19 @@ static int hdd_extscan_epno_fill_network_list( + struct nlattr *networks; + int rem1, ssid_len; + uint8_t index, *ssid; ++ uint32_t expected_networks; + ++ expected_networks = req_msg->num_networks; + index = 0; + nla_for_each_nested(networks, + tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST], + rem1) { ++ ++ if (index == expected_networks) { ++ hddLog(LOGW, FL("ignoring excess networks")); ++ break; ++ } ++ + if (nla_parse(network, QCA_WLAN_VENDOR_ATTR_PNO_MAX, + nla_data(networks), nla_len(networks), + wlan_hdd_pno_config_policy)) { +@@ -4883,6 +4891,7 @@ static int hdd_extscan_epno_fill_network_list( + + index++; + } ++ req_msg->num_networks = index; + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8420/1.patch b/Patches/Linux_CVEs/CVE-2016-8420/1.patch new file mode 100644 index 00000000..0ebb4e2f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8420/1.patch @@ -0,0 +1,55 @@ +From 983ad9423f67549b074cdb4fd5e51ed8248e2ccd Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Wed, 9 Nov 2016 13:55:17 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of EPNO network list + +Currently when processing an EPNO vendor command the "num networks" +attribute is limit checked and if it exceeds a MAX value then it is +reset to that MAX value. This value is then used to calculate the size +of the buffer allocated to hold the internal representation of the +request. However later when the network attributes are parsed there is +no check to make sure the number of networks processed does not exceed +the (possibly modified) "num networks" used to allocate memory, and as +a result a buffer overflow can occur. Address this issue by aborting +the network parsing once "num networks" records have been parsed. + +Change-Id: I6e5f321d23471d082bb000ad0422ea9baa76577a +CRs-Fixed: 1087807 +Bug: 32451171 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 29f388fc7433f..a22714874062e 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -4691,11 +4691,19 @@ static int hdd_extscan_epno_fill_network_list( + struct nlattr *networks; + int rem1, ssid_len; + uint8_t index, *ssid; ++ uint32_t expected_networks; + ++ expected_networks = req_msg->num_networks; + index = 0; + nla_for_each_nested(networks, + tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST], + rem1) { ++ ++ if (index == expected_networks) { ++ hddLog(LOGW, FL("ignoring excess networks")); ++ break; ++ } ++ + if (nla_parse(network, QCA_WLAN_VENDOR_ATTR_PNO_MAX, + nla_data(networks), nla_len(networks), + wlan_hdd_pno_config_policy)) { +@@ -4743,6 +4751,7 @@ static int hdd_extscan_epno_fill_network_list( + + index++; + } ++ req_msg->num_networks = index; + return 0; + } + diff --git a/Patches/Linux_CVEs/CVE-2016-8421/0.patch b/Patches/Linux_CVEs/CVE-2016-8421/0.patch new file mode 100644 index 00000000..150a6585 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8421/0.patch @@ -0,0 +1,76 @@ +From 61a5cdb9adc96645583f528ac923e6e59f3abbcb Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Wed, 9 Nov 2016 11:22:57 -0800 +Subject: qcacld-2.0: Avoid overflow of EXTSCAN bucket list + +Currently when processing an EXTSCAN vendor command the "num buckets" +attribute is limit checked and if it exceeds a MAX value then a +warning message is issued. But beyond that the "num buckets" attribute +is not used. Instead when the buckets are actually parsed the number +of buckets is calculated dynamically based upon the number of +attributes present in the request. Unfortunately when the bucket +attributes are parsed there is no check to make sure the number of +buckets processed does not exceed the MAX value, and as a result a +buffer overflow can occur. Address this issue by aborting the bucket +parsing once the expected number of records have been parsed. + +Change-Id: Ic260dd65dc99118afbb8042d102acb5b26d1e123 +CRs-Fixed: 1087797 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index f488edc..ce8043d 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -3531,6 +3531,7 @@ static int hdd_extscan_start_fill_bucket_channel_spec( + int rem1, rem2; + eHalStatus status; + uint8_t bktIndex, j, numChannels, total_channels = 0; ++ uint32_t expected_buckets; + uint32_t chanList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + + uint32_t min_dwell_time_active_bucket = +@@ -3542,7 +3543,6 @@ static int hdd_extscan_start_fill_bucket_channel_spec( + uint32_t max_dwell_time_passive_bucket = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; + +- bktIndex = 0; + pReqMsg->min_dwell_time_active = + pReqMsg->max_dwell_time_active = + pHddCtx->cfg_ini->extscan_active_max_chn_time; +@@ -3550,10 +3550,19 @@ static int hdd_extscan_start_fill_bucket_channel_spec( + pReqMsg->min_dwell_time_passive = + pReqMsg->max_dwell_time_passive = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; ++ ++ expected_buckets = pReqMsg->numBuckets; + pReqMsg->numBuckets = 0; ++ bktIndex = 0; + + nla_for_each_nested(buckets, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) { ++ ++ if (bktIndex >= expected_buckets) { ++ hddLog(LOGW, FL("ignoring excess buckets")); ++ break; ++ } ++ + if (nla_parse(bucket, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(buckets), nla_len(buckets), NULL)) { +@@ -4055,8 +4064,10 @@ static int __wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, + hddLog(LOGW, + FL("Exceeded MAX number of buckets: %d"), + WLAN_EXTSCAN_MAX_BUCKETS); ++ num_buckets = WLAN_EXTSCAN_MAX_BUCKETS; + } + hddLog(LOG1, FL("Input: Number of Buckets %d"), num_buckets); ++ pReqMsg->numBuckets = num_buckets; + + /* This is optional attribute, if not present set it to 0 */ + if (!tb[PARAM_CONFIG_FLAGS]) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8421/1.patch b/Patches/Linux_CVEs/CVE-2016-8421/1.patch new file mode 100644 index 00000000..16d9ff3e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8421/1.patch @@ -0,0 +1,75 @@ +From 0160130f4217c782a7857588f668ab54fae21f58 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Wed, 9 Nov 2016 13:55:37 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of EXTSCAN bucket list + +Currently when processing an EXTSCAN vendor command the "num buckets" +attribute is limit checked and if it exceeds a MAX value then a +warning message is issued. But beyond that the "num buckets" attribute +is not used. Instead when the buckets are actually parsed the number +of buckets is calculated dynamically based upon the number of +attributes present in the request. Unfortunately when the bucket +attributes are parsed there is no check to make sure the number of +buckets processed does not exceed the MAX value, and as a result a +buffer overflow can occur. Address this issue by aborting the bucket +parsing once the expected number of records have been parsed. + +Change-Id: Ic260dd65dc99118afbb8042d102acb5b26d1e123 +CRs-Fixed: 1087797 +Bug: 32451104 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index a22714874062e..e628b575350e4 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -3525,6 +3525,7 @@ static int hdd_extscan_start_fill_bucket_channel_spec( + int rem1, rem2; + eHalStatus status; + uint8_t bktIndex, j, numChannels, total_channels = 0; ++ uint32_t expected_buckets; + uint32_t chanList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}; + + uint32_t min_dwell_time_active_bucket = +@@ -3536,7 +3537,6 @@ static int hdd_extscan_start_fill_bucket_channel_spec( + uint32_t max_dwell_time_passive_bucket = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; + +- bktIndex = 0; + pReqMsg->min_dwell_time_active = + pReqMsg->max_dwell_time_active = + pHddCtx->cfg_ini->extscan_active_max_chn_time; +@@ -3544,10 +3544,19 @@ static int hdd_extscan_start_fill_bucket_channel_spec( + pReqMsg->min_dwell_time_passive = + pReqMsg->max_dwell_time_passive = + pHddCtx->cfg_ini->extscan_passive_max_chn_time; ++ ++ expected_buckets = pReqMsg->numBuckets; + pReqMsg->numBuckets = 0; ++ bktIndex = 0; + + nla_for_each_nested(buckets, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) { ++ ++ if (bktIndex >= expected_buckets) { ++ hddLog(LOGW, FL("ignoring excess buckets")); ++ break; ++ } ++ + if (nla_parse(bucket, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(buckets), nla_len(buckets), NULL)) { +@@ -4058,8 +4067,10 @@ static int __wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy, + hddLog(LOGW, + FL("Exceeded MAX number of buckets: %d"), + WLAN_EXTSCAN_MAX_BUCKETS); ++ num_buckets = WLAN_EXTSCAN_MAX_BUCKETS; + } + hddLog(LOG1, FL("Input: Number of Buckets %d"), num_buckets); ++ pReqMsg->numBuckets = num_buckets; + + /* This is optional attribute, if not present set it to 0 */ + if (!tb[PARAM_CONFIG_FLAGS]) diff --git a/Patches/Linux_CVEs/CVE-2016-8434/0.patch b/Patches/Linux_CVEs/CVE-2016-8434/0.patch new file mode 100644 index 00000000..afc04c26 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8434/0.patch @@ -0,0 +1,58 @@ +From 3e3866a5fced40ccf9ca442675cf915961efe4d9 Mon Sep 17 00:00:00 2001 +From: Jeremy Gebben +Date: Fri, 27 Feb 2015 11:32:29 -0700 +Subject: msm: kgsl: fix sync file error handling + +We need to call put_unused_fd() on failure, but only if +a file hasn't been stored into the fd yet. This function +wasn't called from kgsl_ioctl_syncsource_create_fence() +and was called incorrectly from kgsl_add_fence_event(). +Reorder our sync_fence_install() calls to happen after +all possible failures so that error cleanup will be +correct. + +Change-Id: I0e7bb459f2acc010446ac5e5b3b72c8b16cce079 +Signed-off-by: Jeremy Gebben +--- + drivers/gpu/msm/kgsl_sync.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c +index 4695b33..9e9e058 100644 +--- a/drivers/gpu/msm/kgsl_sync.c ++++ b/drivers/gpu/msm/kgsl_sync.c +@@ -203,7 +203,6 @@ int kgsl_add_fence_event(struct kgsl_device *device, + ret = priv.fence_fd; + goto out; + } +- sync_fence_install(fence, priv.fence_fd); + + /* + * If the timestamp hasn't expired yet create an event to trigger it. +@@ -222,9 +221,11 @@ int kgsl_add_fence_event(struct kgsl_device *device, + goto out; + } + +- if (copy_to_user(data, &priv, sizeof(priv))) ++ if (copy_to_user(data, &priv, sizeof(priv))) { + ret = -EFAULT; +- ++ goto out; ++ } ++ sync_fence_install(fence, priv.fence_fd); + out: + kgsl_context_put(context); + if (ret) { +@@ -599,6 +600,9 @@ out: + if (ret) { + if (fence) + sync_fence_put(fence); ++ if (fd >= 0) ++ put_unused_fd(fd); ++ + } + kgsl_syncsource_put(syncsource); + return ret; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8436/0.patch b/Patches/Linux_CVEs/CVE-2016-8436/0.patch new file mode 100644 index 00000000..9d934680 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8436/0.patch @@ -0,0 +1,31 @@ +From 228e8d17b9f5d22cf9896ab8eff88dc6737c2ced Mon Sep 17 00:00:00 2001 +From: Shalini Krishnamoorthi +Date: Thu, 12 May 2016 12:13:23 -0700 +Subject: msm: mdss: Fix NULL pointer dereference + +A wrong pointer was freed and dereferenced +leading to fatal exception. Fixed this by +correcting the pointer variable. + +Change-Id: Ic3d55d88c61ab215139de7fe0c53b8bb89bf85f8 +Signed-off-by: Shalini Krishnamoorthi +--- + drivers/video/msm/mdss/mdss_dsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c +index 4df7e98..403444f 100644 +--- a/drivers/video/msm/mdss/mdss_dsi.c ++++ b/drivers/video/msm/mdss/mdss_dsi.c +@@ -2802,7 +2802,7 @@ static int mdss_dsi_ctrl_clock_init(struct platform_device *ctrl_pdev, + error_clk_client_deregister: + mdss_dsi_clk_deregister(ctrl_pdata->dsi_clk_handle); + error_clk_deinit: +- mdss_dsi_clk_deinit(ctrl_pdata); ++ mdss_dsi_clk_deinit(ctrl_pdata->clk_mngr); + error_link_clk_deinit: + mdss_dsi_link_clk_deinit(&ctrl_pdev->dev, ctrl_pdata); + return rc; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8444/0.patch b/Patches/Linux_CVEs/CVE-2016-8444/0.patch new file mode 100644 index 00000000..8c38bb7e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8444/0.patch @@ -0,0 +1,31 @@ +From 78506ab75e0cbbfbf372867cc24282d7e739f4d6 Mon Sep 17 00:00:00 2001 +From: Ranjith Kagathi Ananda +Date: Fri, 4 Sep 2015 16:48:10 -0700 +Subject: [PATCH] msm: ispif: Remove handling of SD_SHUTDOWN + +Remove handling of SD_SHUTDOWN to avoid multiple release. + +Bug: 31243641 + +Change-Id: I09db8adb766d2e7889443f779a716aaa2f6c09d1 +Signed-off-by: Harsh Shah +Signed-off-by: Ranjith Kagathi Ananda +--- + drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +index 5115e3853fe1c..fb1f93cd4c0bc 100644 +--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c ++++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +@@ -1325,10 +1325,6 @@ static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd, + case VIDIOC_MSM_ISPIF_CFG: + return msm_ispif_cmd(sd, arg); + case MSM_SD_SHUTDOWN: { +- struct ispif_device *ispif = +- (struct ispif_device *)v4l2_get_subdevdata(sd); +- if (ispif && ispif->base) +- msm_ispif_release(ispif); + return 0; + } + default: diff --git a/Patches/Linux_CVEs/CVE-2016-8450/0.patch b/Patches/Linux_CVEs/CVE-2016-8450/0.patch new file mode 100644 index 00000000..ef1f72fd --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8450/0.patch @@ -0,0 +1,86 @@ +From e909d159ad1998ada853ed35be27c7b6ba241bdb Mon Sep 17 00:00:00 2001 +From: Walter Yang +Date: Wed, 27 Jul 2016 15:07:53 +0800 +Subject: ASoC: msm: set pointers to NULL after kfree + +In lsm-related driver files, some pointers are not set as NULL +after the memory is freed, which will leave many dangling pointers. +Set them to NULL explicitly to avoid potential risk. + +CRs-Fixed: 880388 +Change-Id: I44925240705608510266a51225cc02611637c571 +Signed-off-by: Walter Yang +--- + sound/soc/msm/msm-cpe-lsm.c | 7 +++++++ + sound/soc/msm/qdsp6v2/msm-dai-slim.c | 2 ++ + sound/soc/msm/qdsp6v2/q6lsm.c | 1 + + 3 files changed, 10 insertions(+) + +diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c +index 9f957e5..a529fcc 100644 +--- a/sound/soc/msm/msm-cpe-lsm.c ++++ b/sound/soc/msm/msm-cpe-lsm.c +@@ -1219,6 +1219,7 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + dev_err(rtd->dev, "%s: No memory for sound model\n", + __func__); + kfree(session->conf_levels); ++ session->conf_levels = NULL; + return -ENOMEM; + } + session->snd_model_size = snd_model.data_size; +@@ -1230,6 +1231,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + __func__); + kfree(session->conf_levels); + kfree(session->snd_model_data); ++ session->conf_levels = NULL; ++ session->snd_model_data = NULL; + return -EFAULT; + } + +@@ -1241,6 +1244,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + __func__, rc); + kfree(session->snd_model_data); + kfree(session->conf_levels); ++ session->snd_model_data = NULL; ++ session->conf_levels = NULL; + return rc; + } + +@@ -1254,6 +1259,8 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session); + kfree(session->snd_model_data); + kfree(session->conf_levels); ++ session->snd_model_data = NULL; ++ session->conf_levels = NULL; + return rc; + } + +diff --git a/sound/soc/msm/qdsp6v2/msm-dai-slim.c b/sound/soc/msm/qdsp6v2/msm-dai-slim.c +index b46d0a5..4bb8f59 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dai-slim.c ++++ b/sound/soc/msm/qdsp6v2/msm-dai-slim.c +@@ -482,7 +482,9 @@ static void msm_dai_slim_remove_dai_data( + dai_data_t = &drv_data->slim_dai_data[i]; + + kfree(dai_data_t->chan_h); ++ dai_data_t->chan_h = NULL; + kfree(dai_data_t->sh_ch); ++ dai_data_t->sh_ch = NULL; + } + } + +diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c +index ec73472..2bf0c49 100644 +--- a/sound/soc/msm/qdsp6v2/q6lsm.c ++++ b/sound/soc/msm/qdsp6v2/q6lsm.c +@@ -348,6 +348,7 @@ void q6lsm_client_free(struct lsm_client *client) + q6lsm_mmap_apr_dereg(); + mutex_destroy(&client->cmd_lock); + kfree(client); ++ client = NULL; + } + + /* +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8452/0.patch b/Patches/Linux_CVEs/CVE-2016-8452/0.patch new file mode 100644 index 00000000..d1d433b6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8452/0.patch @@ -0,0 +1,105 @@ +From 39fa8e972fa1b10dc68a066f4f9432753d8a2526 Mon Sep 17 00:00:00 2001 +From: kaliu +Date: Thu, 4 Aug 2016 14:08:13 +0800 +Subject: qcacld-2.0: Use heap memory for station_info instead of stack + +From kernel 3.19-rc4, size of struct station_info is around 600 bytes, +so stack frame size of such routine use this struct will easily +exceed 1024 bytes, the default value of stack frame size. + +So use heap memory for this struct instead. + +Change-Id: Ibe8a4f5189fcc9d5554f7a5d851c93be8fa8dbad +CRs-Fixed: 1050323 +--- + CORE/HDD/src/wlan_hdd_assoc.c | 19 +++++++++++++------ + CORE/HDD/src/wlan_hdd_hostapd.c | 18 ++++++++++++------ + 2 files changed, 25 insertions(+), 12 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c +index 492785d..c5947c2 100644 +--- a/CORE/HDD/src/wlan_hdd_assoc.c ++++ b/CORE/HDD/src/wlan_hdd_assoc.c +@@ -2811,7 +2811,7 @@ static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, t + case eCSR_ROAM_RESULT_IBSS_NEW_PEER: + { + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); +- struct station_info staInfo; ++ struct station_info *stainfo; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "IBSS New Peer indication from SME with peerMac " MAC_ADDRESS_STR " BSSID: " MAC_ADDRESS_STR " and stationID= %d", +@@ -2846,13 +2846,20 @@ static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, t + vosStatus, vosStatus ); + } + pHddStaCtx->ibss_sta_generation++; +- memset(&staInfo, 0, sizeof(staInfo)); +- staInfo.filled = 0; +- staInfo.generation = pHddStaCtx->ibss_sta_generation; ++ stainfo = vos_mem_malloc(sizeof(*stainfo)); ++ if (stainfo == NULL) { ++ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ++ "memory allocation for station_info failed"); ++ return eHAL_STATUS_FAILED_ALLOC; ++ } ++ memset(stainfo, 0, sizeof(*stainfo)); ++ stainfo->filled = 0; ++ stainfo->generation = pHddStaCtx->ibss_sta_generation; + + cfg80211_new_sta(pAdapter->dev, +- (const u8 *)pRoamInfo->peerMac, +- &staInfo, GFP_KERNEL); ++ (const u8 *)pRoamInfo->peerMac, ++ stainfo, GFP_KERNEL); ++ vos_mem_free(stainfo); + + if ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pHddStaCtx->ibss_enc_key.encType + ||eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pHddStaCtx->ibss_enc_key.encType +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index ba37ddc..1b7c1c7 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -1836,15 +1836,20 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa + HDD_SAP_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_SAP); + { +- struct station_info staInfo; + v_U16_t iesLen = pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.iesLen; + +- memset(&staInfo, 0, sizeof(staInfo)); + if (iesLen <= MAX_ASSOC_IND_IE_LEN ) + { +- staInfo.assoc_req_ies = ++ struct station_info *stainfo; ++ stainfo = vos_mem_malloc(sizeof(*stainfo)); ++ if (stainfo == NULL) { ++ hddLog(LOGE, FL("alloc station_info failed")); ++ return VOS_STATUS_E_NOMEM; ++ } ++ memset(stainfo, 0, sizeof(*stainfo)); ++ stainfo->assoc_req_ies = + (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.ies[0]; +- staInfo.assoc_req_ies_len = iesLen; ++ stainfo->assoc_req_ies_len = iesLen; + #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) + /* + * After Kernel 4.0, it's no longer need to set +@@ -1853,12 +1858,13 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa + * check the existance of request IE. + */ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,31)) || defined(WITH_BACKPORTS) +- staInfo.filled |= STATION_INFO_ASSOC_REQ_IES; ++ stainfo->filled |= STATION_INFO_ASSOC_REQ_IES; + #endif + #endif + cfg80211_new_sta(dev, + (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac.bytes[0], +- &staInfo, GFP_KERNEL); ++ stainfo, GFP_KERNEL); ++ vos_mem_free(stainfo); + } + else + { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8452/1.patch b/Patches/Linux_CVEs/CVE-2016-8452/1.patch new file mode 100644 index 00000000..8f01f321 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8452/1.patch @@ -0,0 +1,98 @@ +From b05c022755257abacfc6df9e4c649adcdc3099b5 Mon Sep 17 00:00:00 2001 +From: Ecco Park +Date: Tue, 1 Nov 2016 16:54:45 -0700 +Subject: [PATCH] qcacld-2.0: Use heap memory for station_info instead of stack + +From kernel 3.19-rc4, size of struct station_info is around 600 bytes, +so stack frame size of such routine use this struct will easily +exceed 1024 bytes, the default value of stack frame size. + +So use heap memory for this struct instead. + +CRs-Fixed: 1050323 + +Bug: 32506396 + +Change-Id: I64835329dc2e46ae33c12585f92c6a75401cfc5c +Signed-off-by: Ecco Park +--- + .../staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c | 17 ++++++++++++----- + .../staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c | 18 ++++++++++++------ + 2 files changed, 24 insertions(+), 11 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c +index 05bc9524088ca..9225042e4319e 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c +@@ -2694,7 +2694,7 @@ static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, t + case eCSR_ROAM_RESULT_IBSS_NEW_PEER: + { + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); +- struct station_info staInfo; ++ struct station_info *stainfo; + + pr_info ( "IBSS New Peer indication from SME " + "with peerMac " MAC_ADDRESS_STR " BSSID: " MAC_ADDRESS_STR " and stationID= %d", +@@ -2728,13 +2728,20 @@ static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, t + vosStatus, vosStatus ); + } + pHddStaCtx->ibss_sta_generation++; +- memset(&staInfo, 0, sizeof(staInfo)); +- staInfo.filled = 0; +- staInfo.generation = pHddStaCtx->ibss_sta_generation; ++ stainfo = vos_mem_malloc(sizeof(*stainfo)); ++ if (stainfo == NULL) { ++ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ++ "memory allocation for station_info failed"); ++ return eHAL_STATUS_FAILED_ALLOC; ++ } ++ memset(stainfo, 0, sizeof(*stainfo)); ++ stainfo->filled = 0; ++ stainfo->generation = pHddStaCtx->ibss_sta_generation; + + cfg80211_new_sta(pAdapter->dev, + (const u8 *)pRoamInfo->peerMac, +- &staInfo, GFP_KERNEL); ++ stainfo, GFP_KERNEL); ++ vos_mem_free(stainfo); + + if ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pHddStaCtx->ibss_enc_key.encType + ||eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pHddStaCtx->ibss_enc_key.encType +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c +index 024b3135ee74f..ee90efa1db586 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -1823,21 +1823,27 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa + HDD_SAP_WAKE_LOCK_DURATION, + WIFI_POWER_EVENT_WAKELOCK_SAP); + { +- struct station_info staInfo; + v_U16_t iesLen = pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.iesLen; + +- memset(&staInfo, 0, sizeof(staInfo)); + if (iesLen <= MAX_ASSOC_IND_IE_LEN ) + { +- staInfo.assoc_req_ies = ++ struct station_info *stainfo; ++ stainfo = vos_mem_malloc(sizeof(*stainfo)); ++ if (stainfo == NULL) { ++ hddLog(LOGE, FL("alloc station_info failed")); ++ return VOS_STATUS_E_NOMEM; ++ } ++ memset(stainfo, 0, sizeof(*stainfo)); ++ stainfo->assoc_req_ies = + (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.ies[0]; +- staInfo.assoc_req_ies_len = iesLen; ++ stainfo->assoc_req_ies_len = iesLen; + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,31)) || defined(WITH_BACKPORTS) +- staInfo.filled |= STATION_INFO_ASSOC_REQ_IES; ++ stainfo->filled |= STATION_INFO_ASSOC_REQ_IES; + #endif + cfg80211_new_sta(dev, + (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac.bytes[0], +- &staInfo, GFP_KERNEL); ++ stainfo, GFP_KERNEL); ++ vos_mem_free(stainfo); + } + else + { diff --git a/Patches/Linux_CVEs/CVE-2016-8452/2.patch b/Patches/Linux_CVEs/CVE-2016-8452/2.patch new file mode 100644 index 00000000..08d1f69c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8452/2.patch @@ -0,0 +1,102 @@ +From 1216822e1d051247ae1f6e194f16d2fc40f1eba2 Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Wed, 7 Dec 2016 16:21:07 +0530 +Subject: wlan: Use heap memory for station_info instead of stack + +qcacld-2.0 to prima propagation. + +From kernel 3.19-rc4, size of struct station_info is around 600 bytes, +so stack frame size of such routine use this struct will easily +exceed 1024 bytes, the default value of stack frame size. + +So use heap memory for this struct instead. + +Change-Id: Ibe8a4f5189fcc9d5554f7a5d851c93be8fa8dbad +CRs-Fixed: 1050323 +--- + CORE/HDD/src/wlan_hdd_assoc.c | 19 ++++++++++++++----- + CORE/HDD/src/wlan_hdd_hostapd.c | 19 +++++++++++++------ + 2 files changed, 27 insertions(+), 11 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c +index 933a2df..cd5686f 100644 +--- a/CORE/HDD/src/wlan_hdd_assoc.c ++++ b/CORE/HDD/src/wlan_hdd_assoc.c +@@ -2730,7 +2730,7 @@ static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, t + case eCSR_ROAM_RESULT_IBSS_NEW_PEER: + { + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); +- struct station_info staInfo; ++ struct station_info *staInfo; + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "IBSS New Peer indication from SME with peerMac " MAC_ADDRESS_STR " BSSID: " MAC_ADDRESS_STR " and stationID= %d", +@@ -2764,13 +2764,22 @@ static eHalStatus roamRoamConnectStatusUpdateHandler( hdd_adapter_t *pAdapter, t + break; + } + pHddStaCtx->ibss_sta_generation++; +- memset(&staInfo, 0, sizeof(staInfo)); +- staInfo.filled = 0; +- staInfo.generation = pHddStaCtx->ibss_sta_generation; ++ ++ staInfo = vos_mem_malloc(sizeof(*staInfo)); ++ if (staInfo == NULL) { ++ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ++ "memory allocation for station_info failed"); ++ return eHAL_STATUS_FAILED_ALLOC; ++ } ++ ++ memset(staInfo, 0, sizeof(*staInfo)); ++ staInfo->filled = 0; ++ staInfo->generation = pHddStaCtx->ibss_sta_generation; + + cfg80211_new_sta(pAdapter->dev, + (const u8 *)pRoamInfo->peerMac, +- &staInfo, GFP_KERNEL); ++ staInfo, GFP_KERNEL); ++ vos_mem_free(staInfo); + + if ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pHddStaCtx->ibss_enc_key.encType + ||eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pHddStaCtx->ibss_enc_key.encType +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index e67db4d..427a350 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -1065,21 +1065,28 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa + #endif + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) + { +- struct station_info staInfo; ++ struct station_info *staInfo; + v_U16_t iesLen = pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.iesLen; + +- memset(&staInfo, 0, sizeof(staInfo)); ++ staInfo = vos_mem_malloc(sizeof(*staInfo)); ++ if (staInfo == NULL) { ++ hddLog(LOGE, FL("alloc station_info failed")); ++ return VOS_STATUS_E_NOMEM; ++ } ++ ++ memset(staInfo, 0, sizeof(*staInfo)); + if (iesLen <= MAX_ASSOC_IND_IE_LEN ) + { +- staInfo.assoc_req_ies = ++ staInfo->assoc_req_ies = + (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.ies[0]; +- staInfo.assoc_req_ies_len = iesLen; ++ staInfo->assoc_req_ies_len = iesLen; + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,31)) +- staInfo.filled |= STATION_INFO_ASSOC_REQ_IES; ++ staInfo->filled |= STATION_INFO_ASSOC_REQ_IES; + #endif + cfg80211_new_sta(dev, + (const u8 *)&pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.staMac.bytes[0], +- &staInfo, GFP_KERNEL); ++ staInfo, GFP_KERNEL); ++ vos_mem_free(staInfo); + } + else + { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8453/0.patch b/Patches/Linux_CVEs/CVE-2016-8453/0.patch new file mode 100644 index 00000000..ac740441 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8453/0.patch @@ -0,0 +1,30 @@ +From f10f4e420dddc35dfef53965c55ffd5bdec41a45 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Mon, 12 Oct 2015 23:31:12 -0700 +Subject: [PATCH] net: wireless: bcmdhd: remove unnecessary PCIe memory access + when BUS down. + +In case PCIe BUS already down, we're not supposed to do access BAR0 +area in any reason. One instance seen on test that made kernel panic. +removed disable irq calling which is useless in bus down case. + +bug=24739315 + +Change-Id: I474e08c14c4dec0f4cc4cd207f29fef32e85ead7 +Signed-off-by: Insun Song +--- + drivers/net/wireless/bcmdhd/dhd_pcie.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie.c b/drivers/net/wireless/bcmdhd/dhd_pcie.c +index 21bbe54ee1889..1adffc366c679 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pcie.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pcie.c +@@ -2472,7 +2472,6 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) + bus->dhd->busstate = DHD_BUS_DOWN; + } else { + if (bus->intr) { +- dhdpcie_bus_intr_disable(bus); + dhdpcie_free_irq(bus); + } + diff --git a/Patches/Linux_CVEs/CVE-2016-8454/0.patch b/Patches/Linux_CVEs/CVE-2016-8454/0.patch new file mode 100644 index 00000000..4c7d61df --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8454/0.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, diff --git a/Patches/Linux_CVEs/CVE-2016-8455/0.patch b/Patches/Linux_CVEs/CVE-2016-8455/0.patch new file mode 100644 index 00000000..e02cc460 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8455/0.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)) { diff --git a/Patches/Linux_CVEs/CVE-2016-8456/0.patch b/Patches/Linux_CVEs/CVE-2016-8456/0.patch new file mode 100644 index 00000000..56fd18c6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8456/0.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: diff --git a/Patches/Linux_CVEs/CVE-2016-8457/0.patch b/Patches/Linux_CVEs/CVE-2016-8457/0.patch new file mode 100644 index 00000000..57a46338 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8457/0.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 } + }; diff --git a/Patches/Linux_CVEs/CVE-2016-8458/0.patch b/Patches/Linux_CVEs/CVE-2016-8458/0.patch new file mode 100644 index 00000000..5364123a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8458/0.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", diff --git a/Patches/Linux_CVEs/CVE-2016-8458/1.patch b/Patches/Linux_CVEs/CVE-2016-8458/1.patch new file mode 100644 index 00000000..40ae865a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8458/1.patch @@ -0,0 +1,454 @@ +From 11ab3add6cfb1ef752ac38adf1b4bf15617772e9 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Tue, 8 Nov 2016 15:19:32 -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: Forced a firmware update by removing +same-firmware check. Firmware update succeeded. + +Bug: 31525965 +Bug: 31968442 +Change-Id: I287f494d973868f6be28799bc2613ff2201b0717 +Signed-off-by: Andrew Chant +--- + .../synaptics_dsx_fw_update.c | 183 +++++++++++++++++---- + 1 file changed, 154 insertions(+), 29 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c +index 05f13b427739b..f7d5dbdd69b53 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c +@@ -771,6 +771,21 @@ static struct synaptics_rmi4_fwu_handle *fwu; + DECLARE_COMPLETION(fwu_remove_complete); + DEFINE_MUTEX(fwu_sysfs_mutex); + ++/* Check offset + size <= bound. true if in bounds, false otherwise. */ ++static bool 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 false; ++ } ++ if (offset > (bound - size)) { ++ pr_err("%s: %lu > %lu - %lu\n", __func__, offset, size, bound); ++ return false; ++ } ++ return true; ++} ++ + #ifdef HTC_FEATURE + static uint32_t syn_crc(uint16_t *data, uint32_t len) + { +@@ -966,8 +981,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; +@@ -979,6 +996,11 @@ static void fwu_parse_partition_table(const unsigned char *partition_table, + + 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; +@@ -987,7 +1009,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__, +@@ -1077,16 +1099,17 @@ static void fwu_parse_partition_table(const unsigned char *partition_table, + }; + } + +- return; ++ return 0; + } + +-static void fwu_parse_image_header_10_utility(const unsigned char *image) ++static int fwu_parse_image_header_10_utility(const unsigned char *image) + { + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; ++ unsigned int content_offset; + const unsigned char *content; + struct container_descriptor *descriptor; + +@@ -1099,15 +1122,22 @@ static void fwu_parse_image_header_10_utility(const unsigned char *image) + if (ii >= MAX_UTILITY_PARAMS) + continue; + addr = le_to_uint(fwu->img.utility.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 UTILITY_PARAMETER_CONTAINER: + fwu->img.utility_param[ii].data = content; + fwu->img.utility_param[ii].size = length; ++ if (length < sizeof(content[0])) ++ return -EINVAL; + fwu->img.utility_param_id[ii] = content[0]; + break; + default: +@@ -1115,28 +1145,36 @@ static void fwu_parse_image_header_10_utility(const unsigned char *image) + }; + } + +- return; ++ return 0; + } + +-static void fwu_parse_image_header_10_bootloader(const unsigned char *image) ++static int fwu_parse_image_header_10_bootloader(const unsigned char *image) + { + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; ++ unsigned int content_offset; + const unsigned char *content; + struct container_descriptor *descriptor; + ++ if (fwu->img.bootloader.size < 4) ++ return -EINVAL; + 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_IMAGE_CONTAINER: + fwu->img.bl_image.data = content; +@@ -1157,29 +1195,36 @@ static void fwu_parse_image_header_10_bootloader(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; + unsigned int addr; + unsigned int offset; ++ unsigned int content_offset; + unsigned int container_id; + unsigned int length; ++ unsigned int image_size; + const unsigned char *image; + const unsigned char *content; + struct container_descriptor *descriptor; + struct image_header_10 *header; + + image = fwu->image; ++ image_size = fwu->image_size; ++ if (image_size < sizeof(*header)) ++ return -EINVAL; + header = (struct image_header_10 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + /* address of top level container */ + offset = le_to_uint(header->top_level_container_start_addr); ++ if (!in_bounds(offset, sizeof(*descriptor), image_size)) ++ return -EINVAL; + descriptor = (struct container_descriptor *)(image + offset); + + /* address of top level container content */ +@@ -1187,13 +1232,20 @@ static void fwu_parse_image_header_10(void) + num_of_containers = le_to_uint(descriptor->content_length) / 4; + + for (ii = 0; ii < num_of_containers; ii++) { ++ if (!in_bounds(offset, 4, image_size)) ++ return -EINVAL; + addr = le_to_uint(image + offset); + offset += 4; ++ if (!in_bounds(addr, sizeof(*descriptor), 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, image_size)) ++ return -EINVAL; ++ content = image + content_offset; + switch (container_id) { + case UI_CONTAINER: + case CORE_CODE_CONTAINER: +@@ -1209,12 +1261,14 @@ 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_bootloader(image); ++ if (fwu_parse_image_header_10_bootloader(image)) ++ return -EINVAL; + break; + case UTILITY_CONTAINER: + fwu->img.utility.data = content; + fwu->img.utility.size = length; +- fwu_parse_image_header_10_utility(image); ++ if (fwu_parse_image_header_10_utility(image)) ++ return -EINVAL; + break; + case GUEST_CODE_CONTAINER: + fwu->img.contains_guest_code = true; +@@ -1239,6 +1293,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: +@@ -1246,10 +1302,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; +@@ -1257,6 +1313,8 @@ static void fwu_parse_image_header_05_06(void) + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + 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); +@@ -1269,18 +1327,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) || +@@ -1292,6 +1383,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, +@@ -1323,28 +1419,41 @@ static void fwu_parse_image_header_05_06(void) + } + fwu->img.product_id[PRODUCT_ID_SIZE] = 0; + ++ if (LOCKDOWN_SIZE > IMAGE_AREA_OFFSET) ++ return -EINVAL; ++ if (fwu->image_size < IMAGE_AREA_OFFSET) ++ return -EINVAL; + fwu->img.lockdown.size = LOCKDOWN_SIZE; + fwu->img.lockdown.data = image + IMAGE_AREA_OFFSET - LOCKDOWN_SIZE; + +- return; ++ return 0; + } + + static int fwu_parse_image_info(void) + { ++ int parse_retval; + struct image_header_10 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; ++ unsigned int image_size = 0; + + header = (struct image_header_10 *)fwu->image; +- ++ if (!header) ++ return -EINVAL; ++ image_size = fwu->image_size; ++ if (image_size < sizeof(struct image_header_05_06) && ++ image_size < 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(); ++ parse_retval = fwu_parse_image_header_10(); + break; + case IMAGE_HEADER_VERSION_05: + case IMAGE_HEADER_VERSION_06: +- fwu_parse_image_header_05_06(); ++ parse_retval = fwu_parse_image_header_05_06(); + break; + default: + dev_err(rmi4_data->pdev->dev.parent, +@@ -1353,6 +1462,10 @@ static int fwu_parse_image_info(void) + return -EINVAL; + } + ++ if (parse_retval != 0) { ++ return -EINVAL; ++ } ++ + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (!fwu->img.contains_flash_config) { + dev_err(rmi4_data->pdev->dev.parent, +@@ -1361,9 +1474,12 @@ 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)) { ++ return -EINVAL; ++ } + fwu_compare_partition_tables(); + } else { + fwu->new_partition_table = false; +@@ -1980,7 +2096,11 @@ 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)) { ++ kfree(ptable); ++ return -EINVAL; ++ } + + if (fwu->blkcount.dp_config) + fwu->flash_properties.has_disp_config = 1; +@@ -3209,6 +3329,9 @@ static int fwu_write_utility_parameter(void) + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + utility_param_size = fwu->blkcount.utility_param * fwu->block_size; ++ /* See remaining_size below for reason for '4' */ ++ if (utility_param_size < 4) ++ return -EINVAL; + retval = fwu_allocate_read_config_buf(utility_param_size); + if (retval < 0) + return retval; +@@ -4910,6 +5033,7 @@ int synaptics_config_updater(struct synaptics_dsx_board_data *bdata) + + rmi4_data->stay_awake = true; + ++ memset(config_id, 0, sizeof(config_id)); + if (fwu->bl_version == BL_V7) + config_id_size = V7_CONFIG_ID_SIZE; + else +@@ -4928,6 +5052,7 @@ int synaptics_config_updater(struct synaptics_dsx_board_data *bdata) + } + + memset(str_buf, 0, sizeof(str_buf)); ++ memset(tmp_buf, 0, sizeof(tmp_buf)); + for (ii = 0; ii < config_id_size; ii++) { + snprintf(tmp_buf, 3, "%02x ", config_id[ii]); + strlcat(str_buf, tmp_buf, sizeof(str_buf)); diff --git a/Patches/Linux_CVEs/CVE-2016-8463/0.patch b/Patches/Linux_CVEs/CVE-2016-8463/0.patch new file mode 100644 index 00000000..0df93c6b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8463/0.patch @@ -0,0 +1,35 @@ +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/Linux_CVEs/CVE-2016-8463/1.patch b/Patches/Linux_CVEs/CVE-2016-8463/1.patch new file mode 100644 index 00000000..49ee240d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8463/1.patch @@ -0,0 +1,32 @@ +From cd0fa86de6ca1d40c0a93d86d1c0f7846e8a9a10 Mon Sep 17 00:00:00 2001 +From: Laura Abbott +Date: Fri, 3 Jan 2014 10:47:00 -0800 +Subject: [PATCH] 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 e231a7ff11390..3411ed834bbac 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); diff --git a/Patches/Linux_CVEs/CVE-2016-8463/2.patch b/Patches/Linux_CVEs/CVE-2016-8463/2.patch new file mode 100644 index 00000000..07b1b7cf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8463/2.patch @@ -0,0 +1,35 @@ +From d1ac033d7862a7ec45fb1be8c06b8f51b36deb1a 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 c4ced86..e3181a3 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -929,6 +929,8 @@ static int fuse_readpages_fill(void *_data, struct page *page) + */ + 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/Linux_CVEs/CVE-2016-8464/0.patch b/Patches/Linux_CVEs/CVE-2016-8464/0.patch new file mode 100644 index 00000000..41a86e5a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8464/0.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; diff --git a/Patches/Linux_CVEs/CVE-2016-8465/0.patch b/Patches/Linux_CVEs/CVE-2016-8465/0.patch new file mode 100644 index 00000000..f39a5bf9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8465/0.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; ++ } + + } + diff --git a/Patches/Linux_CVEs/CVE-2016-8465/1.patch b/Patches/Linux_CVEs/CVE-2016-8465/1.patch new file mode 100644 index 00000000..23145edd --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8465/1.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, diff --git a/Patches/Linux_CVEs/CVE-2016-8465/2.patch b/Patches/Linux_CVEs/CVE-2016-8465/2.patch new file mode 100644 index 00000000..83a9f1f7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8465/2.patch @@ -0,0 +1,156 @@ +From 4add5112babf94dbc0f86e93395b6622d5080d16 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Thu, 3 Nov 2016 10:53:51 -0700 +Subject: 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 | 105 +++++++++++++++++++++-------- + 1 file changed, 77 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index aa8f352..037e885 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -615,14 +615,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; ++ 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; +@@ -630,37 +638,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 = 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; ++ } + + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8465/3.patch b/Patches/Linux_CVEs/CVE-2016-8465/3.patch new file mode 100644 index 00000000..6ac0375c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8465/3.patch @@ -0,0 +1,103 @@ +From 3619fd91b831f184d2e544e23cb54d20eed2531e Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Wed, 30 Nov 2016 12:00:17 -0800 +Subject: 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 420cb2f..3e80169 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -702,7 +702,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; + } + +@@ -711,10 +711,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) { +@@ -751,13 +774,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 58077b3..7d33c62 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.h ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.h +@@ -181,6 +181,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, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8466/0.patch b/Patches/Linux_CVEs/CVE-2016-8466/0.patch new file mode 100644 index 00000000..d024359b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8466/0.patch @@ -0,0 +1,57 @@ +From 67d429b1cb87879c33df58febc0b7bf6712bc7c0 Mon Sep 17 00:00:00 2001 +From: Ram Sripathi +Date: Fri, 4 Nov 2016 15:44:14 -0700 +Subject: [PATCH] net: wireless: bcmdhd: Heap over write in + dhdmsgbuf_query_ioctl + +handled heap overwrite with checks + +Change-Id: I9e9bc97a3f410d40d9bc6a44707a6c0f8917cd31 +Bug: 31822524 +Signed-off-by: Ram Sripathi +--- + drivers/net/wireless/bcmdhd/dhd_msgbuf.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c +index cb5018c52f10b..90f9733a7e36c 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c ++++ b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c +@@ -2612,22 +2612,24 @@ static int + dhdmsgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action) + { + dhd_prot_t *prot = dhd->prot; +- + int ret = 0; + +- DHD_TRACE(("%s: Enter\n", __FUNCTION__)); +- +- /* Respond "bcmerror" and "bcmerrorstr" with local cache */ +- if (cmd == WLC_GET_VAR && buf) +- { +- if (!strcmp((char *)buf, "bcmerrorstr")) +- { +- strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN); ++ DHD_TRACE(("%s: Enter\n", __func__)); ++ if (!buf || !len) { ++ DHD_ERROR(("%s(): Zero length bailing\n", __func__)); ++ ret = BCME_BADARG; ++ goto done; ++ } ++ if (cmd == WLC_GET_VAR) { ++ /* Respond "bcmerror" and "bcmerrorstr" with local cache */ ++ if ((len > strlen("bcmerrorstr")) && ++ !strcmp(buf, "bcmerrorstr")) { ++ strlcpy(buf, bcmerrorstr(dhd->dongle_error), len); + goto done; +- } +- else if (!strcmp((char *)buf, "bcmerror")) +- { +- *(int *)buf = dhd->dongle_error; ++ } else if ((len > strlen("bcmerror")) && ++ !strcmp(buf, "bcmerror")) { ++ memcpy(buf, &dhd->dongle_error, ++ sizeof(dhd->dongle_error)); + goto done; + } + } diff --git a/Patches/Linux_CVEs/CVE-2016-8466/1.patch b/Patches/Linux_CVEs/CVE-2016-8466/1.patch new file mode 100644 index 00000000..49762309 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8466/1.patch @@ -0,0 +1,59 @@ +From 4af032a458109027c88c478c800aac97a7105250 Mon Sep 17 00:00:00 2001 +From: Ram Sripathi +Date: Fri, 4 Nov 2016 15:44:14 -0700 +Subject: net: wireless: bcmdhd: Heap over write in dhdmsgbuf_query_ioctl + +handled heap overwrite with checks + +Signed-off-by: Ram Sripathi +Bug: 31822524 +Change-Id: I9e9bc97a3f410d40d9bc6a44707a6c0f8917cd31 +--- + drivers/net/wireless/bcmdhd/dhd_msgbuf.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c +index 8d7d4bf..e6e2848 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c ++++ b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c +@@ -2493,22 +2493,24 @@ static int + dhdmsgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action) + { + dhd_prot_t *prot = dhd->prot; +- + int ret = 0; + +- DHD_TRACE(("%s: Enter\n", __FUNCTION__)); +- +- /* Respond "bcmerror" and "bcmerrorstr" with local cache */ +- if (cmd == WLC_GET_VAR && buf) +- { +- if (!strcmp((char *)buf, "bcmerrorstr")) +- { +- strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN); ++ DHD_TRACE(("%s: Enter\n", __func__)); ++ if (!buf || !len) { ++ DHD_ERROR(("%s(): Zero length bailing\n", __func__)); ++ ret = BCME_BADARG; ++ goto done; ++ } ++ if (cmd == WLC_GET_VAR) { ++ /* Respond "bcmerror" and "bcmerrorstr" with local cache */ ++ if ((len > strlen("bcmerrorstr")) && ++ !strcmp(buf, "bcmerrorstr")) { ++ strlcpy(buf, bcmerrorstr(dhd->dongle_error), len); + goto done; +- } +- else if (!strcmp((char *)buf, "bcmerror")) +- { +- *(int *)buf = dhd->dongle_error; ++ } else if ((len > strlen("bcmerror")) && ++ !strcmp(buf, "bcmerror")) { ++ memcpy(buf, &dhd->dongle_error, ++ sizeof(dhd->dongle_error)); + goto done; + } + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8468/0.patch b/Patches/Linux_CVEs/CVE-2016-8468/0.patch new file mode 100644 index 00000000..97434d64 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8468/0.patch @@ -0,0 +1,36 @@ +From 0d37d64f02e18a301867ae7684c3801bd99c5df2 Mon Sep 17 00:00:00 2001 +From: Martijn Coenen +Date: Tue, 8 Nov 2016 20:12:16 +0100 +Subject: [PATCH] Android: binder: check set_context_mgr permission on time. + +Bug: 32394425 +Change-Id: I860c6aab97850bff05a56e96cd3f4b41691bfd96 +Signed-off-by: Martijn Coenen +--- + drivers/staging/android/binder.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c +index ad902dbac8fa5..56f9713de523c 100644 +--- a/drivers/staging/android/binder.c ++++ b/drivers/staging/android/binder.c +@@ -2784,6 +2784,9 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) + ret = -EBUSY; + goto out; + } ++ ret = security_binder_set_context_mgr(proc->tsk); ++ if (ret < 0) ++ goto out; + if (uid_valid(binder_context_mgr_uid)) { + if (!uid_eq(binder_context_mgr_uid, curr_euid)) { + pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", +@@ -2849,9 +2852,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + ret = binder_ioctl_set_ctx_mgr(filp); + if (ret) + goto err; +- ret = security_binder_set_context_mgr(proc->tsk); +- if (ret < 0) +- goto err; + break; + case BINDER_THREAD_EXIT: + binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n", diff --git a/Patches/Linux_CVEs/CVE-2016-8473/0.patch b/Patches/Linux_CVEs/CVE-2016-8473/0.patch new file mode 100644 index 00000000..8acfa4c8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8473/0.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, diff --git a/Patches/Linux_CVEs/CVE-2016-8474/0.patch b/Patches/Linux_CVEs/CVE-2016-8474/0.patch new file mode 100644 index 00000000..8acfa4c8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8474/0.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, diff --git a/Patches/Linux_CVEs/CVE-2016-8475/0.patch b/Patches/Linux_CVEs/CVE-2016-8475/0.patch new file mode 100644 index 00000000..ade51786 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8475/0.patch @@ -0,0 +1,27 @@ +From d906945fc287f9df48b99349fea962b921d4d39e Mon Sep 17 00:00:00 2001 +From: matt_huang +Date: Mon, 7 Nov 2016 16:22:57 +0800 +Subject: [PATCH] input: misc: fix security vulnerability + +initialize the structure before using +Bug: 32591129 + +Change-Id: I9a3af40175d929009522f6c93005d82535c4ccc3 +Signed-off-by: matt_huang +--- + drivers/input/misc/vl53L0/stmvl53l0_module.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/input/misc/vl53L0/stmvl53l0_module.c b/drivers/input/misc/vl53L0/stmvl53l0_module.c +index 0028e527857f5..cc27309fc4e20 100644 +--- a/drivers/input/misc/vl53L0/stmvl53l0_module.c ++++ b/drivers/input/misc/vl53L0/stmvl53l0_module.c +@@ -2483,6 +2483,8 @@ static int stmvl53l0_ioctl_handler(struct file *file, + if (!data->enable_ps_sensor) + stmvl53l0_start(data, 3, NORMAL_MODE); + ++ memset(&RangingMeasurementData, 0, sizeof(RangingMeasurementData)); ++ + for (i = 0; i < RANGE_MEASUREMENT_TIMES;) + { + Status = papi_func_tbl->PerformSingleRangingMeasurement(vl53l0_dev, &RangingMeasurementData); diff --git a/Patches/Linux_CVEs/CVE-2016-8476/0.patch b/Patches/Linux_CVEs/CVE-2016-8476/0.patch new file mode 100644 index 00000000..43e0e974 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8476/0.patch @@ -0,0 +1,51 @@ +From bfe8035bce6fec72ed1d064b94529fce8fb09799 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Fri, 18 Nov 2016 08:04:08 -0800 +Subject: qcacld-2.0: Validate "set passpoint list" network count + +Currently when processing the "set passpoint list" vendor command the +"number of networks" parameter is not limit checked. This value is +subsequently used to calculate the size of a buffer. Add a limit check +to ensure that an appropriately sized buffer is always allocated. + +Change-Id: Ibc2346b8a62898fc47e2d1efe457c57c08b0cada +CRs-Fixed: 1091940 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 7 ++++++- + CORE/MAC/inc/sirApi.h | 1 + + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 77a3ae9..a2ff8fe 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -5246,8 +5246,13 @@ static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, + } + num_networks = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]); +- hddLog(LOG1, FL("num networks %u"), num_networks); ++ if (num_networks > SIR_PASSPOINT_LIST_MAX_NETWORKS) { ++ hddLog(LOGE, FL("num networks %u exceeds max %u"), ++ num_networks, SIR_PASSPOINT_LIST_MAX_NETWORKS); ++ return -EINVAL; ++ } + ++ hddLog(LOG1, FL("num networks %u"), num_networks); + req_msg = vos_mem_malloc(sizeof(*req_msg) + + (num_networks * sizeof(req_msg->networks[0]))); + if (!req_msg) { +diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h +index c5074d2..fd0adb2 100644 +--- a/CORE/MAC/inc/sirApi.h ++++ b/CORE/MAC/inc/sirApi.h +@@ -5773,6 +5773,7 @@ struct wifi_epno_params + struct wifi_epno_network networks[]; + }; + ++#define SIR_PASSPOINT_LIST_MAX_NETWORKS 8 + #define SIR_PASSPOINT_REALM_LEN 256 + #define SIR_PASSPOINT_ROAMING_CONSORTIUM_ID_NUM 16 + #define SIR_PASSPOINT_PLMN_LEN 3 +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8476/1.patch b/Patches/Linux_CVEs/CVE-2016-8476/1.patch new file mode 100644 index 00000000..1e3111c5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8476/1.patch @@ -0,0 +1,50 @@ +From 391b6eea59269ce8962c2ae160de6c8ac8bb4967 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Mon, 21 Nov 2016 19:05:28 -0800 +Subject: [PATCH] qcacld-2.0: Validate "set passpoint list" network count + +Currently when processing the "set passpoint list" vendor command the +"number of networks" parameter is not limit checked. This value is +subsequently used to calculate the size of a buffer. Add a limit check +to ensure that an appropriately sized buffer is always allocated. + +Change-Id: Ibc2346b8a62898fc47e2d1efe457c57c08b0cada +CRs-Fixed: 1091940 +Bug: 32879283 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 7 ++++++- + drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h | 1 + + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index e628b575350e4..82275c27ae587 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -5111,8 +5111,13 @@ static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, + } + num_networks = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]); +- hddLog(LOG1, FL("num networks %u"), num_networks); ++ if (num_networks > SIR_PASSPOINT_LIST_MAX_NETWORKS) { ++ hddLog(LOGE, FL("num networks %u exceeds max %u"), ++ num_networks, SIR_PASSPOINT_LIST_MAX_NETWORKS); ++ return -EINVAL; ++ } + ++ hddLog(LOG1, FL("num networks %u"), num_networks); + req_msg = vos_mem_malloc(sizeof(*req_msg) + + (num_networks * sizeof(req_msg->networks[0]))); + if (!req_msg) { +diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h +index e6ff7c0967ddb..34287b3c3095d 100644 +--- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h ++++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h +@@ -5580,6 +5580,7 @@ struct wifi_epno_params + struct wifi_epno_network networks[]; + }; + ++#define SIR_PASSPOINT_LIST_MAX_NETWORKS 8 + #define SIR_PASSPOINT_REALM_LEN 256 + #define SIR_PASSPOINT_ROAMING_CONSORTIUM_ID_NUM 16 + #define SIR_PASSPOINT_PLMN_LEN 3 diff --git a/Patches/Linux_CVEs/CVE-2016-8477/0.patch b/Patches/Linux_CVEs/CVE-2016-8477/0.patch new file mode 100644 index 00000000..9501aef2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8477/0.patch @@ -0,0 +1,65 @@ +From 33c9042e38506b04461fa99e304482bc20923508 Mon Sep 17 00:00:00 2001 +From: guyang +Date: Tue, 6 Dec 2016 18:30:38 +0800 +Subject: msm: camera: sensor: Validate eeprom_name string length + +Validate eeprom_name string length before copying into +the userspace buffer. +If more data than required is copied, userspace has the access to +some of kernel data which is not intended. + +CRs-Fixed: 1090007 +Change-Id: Id40a287e0b1a93cc15d9b02c757fe9f347e285f2 +Signed-off-by: Rajesh Bondugula +Signed-off-by: VijayaKumar T M +Signed-off-by: Yang Guang +--- + .../media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c | 11 +++++++++-- + include/media/msm_cam_sensor.h | 2 +- + 2 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +index 059780d..13ad58e 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +@@ -140,15 +140,22 @@ static int msm_eeprom_config(struct msm_eeprom_ctrl_t *e_ctrl, + struct msm_eeprom_cfg_data *cdata = + (struct msm_eeprom_cfg_data *)argp; + int rc = 0; ++ size_t length = 0; + + CDBG("%s E\n", __func__); + switch (cdata->cfgtype) { + case CFG_EEPROM_GET_INFO: + CDBG("%s E CFG_EEPROM_GET_INFO\n", __func__); + cdata->is_supported = e_ctrl->is_supported; ++ length = strlen(e_ctrl->eboard_info->eeprom_name) + 1; ++ if (length > MAX_EEPROM_NAME) { ++ pr_err("%s:%d invalid eeprom_name length %d\n", ++ __func__,__LINE__, (int)length); ++ rc = -EINVAL; ++ break; ++ } + memcpy(cdata->cfg.eeprom_name, +- e_ctrl->eboard_info->eeprom_name, +- sizeof(cdata->cfg.eeprom_name)); ++ e_ctrl->eboard_info->eeprom_name, length); + break; + case CFG_EEPROM_GET_CAL_DATA: + CDBG("%s E CFG_EEPROM_GET_CAL_DATA\n", __func__); +diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h +index 9497875..7ff89a4 100644 +--- a/include/media/msm_cam_sensor.h ++++ b/include/media/msm_cam_sensor.h +@@ -446,7 +446,7 @@ struct msm_eeprom_cfg_data { + enum eeprom_cfg_type_t cfgtype; + uint8_t is_supported; + union { +- char eeprom_name[MAX_SENSOR_NAME]; ++ char eeprom_name[MAX_EEPROM_NAME]; + struct eeprom_get_t get_data; + struct eeprom_read_t read_data; + struct eeprom_write_t write_data; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8477/1.patch b/Patches/Linux_CVEs/CVE-2016-8477/1.patch new file mode 100644 index 00000000..f1f00026 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8477/1.patch @@ -0,0 +1,92 @@ +From 96145eb5f0631f0e105d47abebc8f940f7621eeb Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Tue, 15 Nov 2016 13:52:49 -0800 +Subject: msm: camera: sensor: Validate eeprom_name string length + +Validate eeprom_name string length before copying into +the userspace buffer. +If more data than required is copied, userspace has the access to +some of kernel data which is not intended. + +This change will fix the issue. + +CRs-Fixed: 1090007 +Signed-off-by: Rajesh Bondugula +Change-Id: Id40a287e0b1a93cc15d9b02c757fe9f347e285f2 +--- + .../msm/camera_v2/sensor/eeprom/msm_eeprom.c | 22 ++++++++++++++++++---- + include/uapi/media/msm_cam_sensor.h | 2 +- + 2 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +index 1f891ac..037e8b5 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +@@ -617,6 +617,7 @@ static int msm_eeprom_config(struct msm_eeprom_ctrl_t *e_ctrl, + struct msm_eeprom_cfg_data *cdata = + (struct msm_eeprom_cfg_data *)argp; + int rc = 0; ++ size_t length = 0; + + CDBG("%s E\n", __func__); + switch (cdata->cfgtype) { +@@ -629,9 +630,15 @@ static int msm_eeprom_config(struct msm_eeprom_ctrl_t *e_ctrl, + } + CDBG("%s E CFG_EEPROM_GET_INFO\n", __func__); + cdata->is_supported = e_ctrl->is_supported; ++ length = strlen(e_ctrl->eboard_info->eeprom_name) + 1; ++ if (length > MAX_EEPROM_NAME) { ++ pr_err("%s:%d invalid eeprom_name length %d\n", ++ __func__, __LINE__, (int)length); ++ rc = -EINVAL; ++ break; ++ } + memcpy(cdata->cfg.eeprom_name, +- e_ctrl->eboard_info->eeprom_name, +- sizeof(cdata->cfg.eeprom_name)); ++ e_ctrl->eboard_info->eeprom_name, length); + break; + case CFG_EEPROM_GET_CAL_DATA: + CDBG("%s E CFG_EEPROM_GET_CAL_DATA\n", __func__); +@@ -1479,6 +1486,7 @@ static int msm_eeprom_config32(struct msm_eeprom_ctrl_t *e_ctrl, + struct msm_eeprom_cfg_data32 *cdata = + (struct msm_eeprom_cfg_data32 *)argp; + int rc = 0; ++ size_t length = 0; + + CDBG("%s E\n", __func__); + switch (cdata->cfgtype) { +@@ -1491,9 +1499,15 @@ static int msm_eeprom_config32(struct msm_eeprom_ctrl_t *e_ctrl, + } + CDBG("%s E CFG_EEPROM_GET_INFO\n", __func__); + cdata->is_supported = e_ctrl->is_supported; ++ length = strlen(e_ctrl->eboard_info->eeprom_name) + 1; ++ if (length > MAX_EEPROM_NAME) { ++ pr_err("%s:%d invalid eeprom_name length %d\n", ++ __func__, __LINE__, (int)length); ++ rc = -EINVAL; ++ break; ++ } + memcpy(cdata->cfg.eeprom_name, +- e_ctrl->eboard_info->eeprom_name, +- sizeof(cdata->cfg.eeprom_name)); ++ e_ctrl->eboard_info->eeprom_name, length); + break; + case CFG_EEPROM_GET_CAL_DATA: + CDBG("%s E CFG_EEPROM_GET_CAL_DATA\n", __func__); +diff --git a/include/uapi/media/msm_cam_sensor.h b/include/uapi/media/msm_cam_sensor.h +index 540a96c..b8f4b41 100644 +--- a/include/uapi/media/msm_cam_sensor.h ++++ b/include/uapi/media/msm_cam_sensor.h +@@ -290,7 +290,7 @@ struct msm_eeprom_cfg_data { + enum eeprom_cfg_type_t cfgtype; + uint8_t is_supported; + union { +- char eeprom_name[MAX_SENSOR_NAME]; ++ char eeprom_name[MAX_EEPROM_NAME]; + struct eeprom_get_t get_data; + struct eeprom_read_t read_data; + struct eeprom_write_t write_data; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8478/0.patch b/Patches/Linux_CVEs/CVE-2016-8478/0.patch new file mode 100644 index 00000000..b08ceefb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8478/0.patch @@ -0,0 +1,73 @@ +From e3af5e89426f1c8d4e703d415eff5435b925649f Mon Sep 17 00:00:00 2001 +From: Benet Clark +Date: Thu, 10 Nov 2016 17:49:09 -0800 +Subject: msm: mdss: Clear compat structures before copying to user + +In the compat layer, the temporary structures used to convert +data from 32bit to 64bit structures need to be set to 0 before +being assigned values. + +CRs-Fixed: 1088206 +Change-Id: I04497bc11e01c3df4beadfd6d9b06ab4321f1723 +Signed-off-by: Benet Clark +--- + drivers/video/msm/mdss/mdss_compat_utils.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c +index 5ad51dd..a9ab5c1 100644 +--- a/drivers/video/msm/mdss/mdss_compat_utils.c ++++ b/drivers/video/msm/mdss/mdss_compat_utils.c +@@ -846,6 +846,7 @@ static int __from_user_pcc_coeff_v17( + return -EFAULT; + } + ++ memset(&pcc_cfg_payload, 0, sizeof(pcc_cfg_payload)); + pcc_cfg_payload.r.b = pcc_cfg_payload32.r.b; + pcc_cfg_payload.r.g = pcc_cfg_payload32.r.g; + pcc_cfg_payload.r.c = pcc_cfg_payload32.r.c; +@@ -1127,6 +1128,8 @@ static int __from_user_igc_lut_data_v17( + pr_err("failed to copy payload from user for igc\n"); + return -EFAULT; + } ++ ++ memset(&igc_cfg_payload, 0, sizeof(igc_cfg_payload)); + igc_cfg_payload.c0_c1_data = compat_ptr(igc_cfg_payload_32.c0_c1_data); + igc_cfg_payload.c2_data = compat_ptr(igc_cfg_payload_32.c2_data); + igc_cfg_payload.len = igc_cfg_payload_32.len; +@@ -1261,6 +1264,7 @@ static int __from_user_pgc_lut_data_v1_7( + pr_err("failed to copy from user the pgc32 payload\n"); + return -EFAULT; + } ++ memset(&pgc_cfg_payload, 0, sizeof(pgc_cfg_payload)); + pgc_cfg_payload.c0_data = compat_ptr(pgc_cfg_payload_32.c0_data); + pgc_cfg_payload.c1_data = compat_ptr(pgc_cfg_payload_32.c1_data); + pgc_cfg_payload.c2_data = compat_ptr(pgc_cfg_payload_32.c2_data); +@@ -1470,6 +1474,7 @@ static int __from_user_hist_lut_data_v1_7( + return -EFAULT; + } + ++ memset(&hist_lut_cfg_payload, 0, sizeof(hist_lut_cfg_payload)); + hist_lut_cfg_payload.len = hist_lut_cfg_payload32.len; + hist_lut_cfg_payload.data = compat_ptr(hist_lut_cfg_payload32.data); + +@@ -2024,6 +2029,7 @@ static int __from_user_pa_data_v1_7( + return -EFAULT; + } + ++ memset(&pa_cfg_payload, 0, sizeof(pa_cfg_payload)); + pa_cfg_payload.mode = pa_cfg_payload32.mode; + pa_cfg_payload.global_hue_adj = pa_cfg_payload32.global_hue_adj; + pa_cfg_payload.global_sat_adj = pa_cfg_payload32.global_sat_adj; +@@ -2280,6 +2286,8 @@ static int __from_user_gamut_cfg_data_v17( + pr_err("failed to copy the gamut payload from userspace\n"); + return -EFAULT; + } ++ ++ memset(&gamut_cfg_payload, 0, sizeof(gamut_cfg_payload)); + gamut_cfg_payload.mode = gamut_cfg_payload32.mode; + for (i = 0; i < MDP_GAMUT_TABLE_NUM_V1_7; i++) { + gamut_cfg_payload.tbl_size[i] = +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8479/0.patch b/Patches/Linux_CVEs/CVE-2016-8479/0.patch new file mode 100644 index 00000000..5e4067a8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8479/0.patch @@ -0,0 +1,87 @@ +From 14139f66e4f4a678e30ed06764603cd050e06ffd Mon Sep 17 00:00:00 2001 +From: Bulbul Dabi +Date: Tue, 31 May 2016 11:24:22 -0600 +Subject: [PATCH] msm: kgsl: Reserve a context ID slot but don't populate + immediately + +When creating a context allocate an ID but don't populate the slot +with the context pointer until we are done setup up the rest of the +process. This avoids a race if somebody tries to free the same +identifier before the create operation is complete. + +Bug: 31824853 +Change-Id: Ic0dedbadca5b4cc4ce567afad48a33078b549439 +Signed-off-by: Jordan Crouse +--- + drivers/gpu/msm/kgsl.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index f8ab3d042a728..4383e77776163 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -516,21 +516,18 @@ void kgsl_context_dump(struct kgsl_context *context) + EXPORT_SYMBOL(kgsl_context_dump); + + /* Allocate a new context ID */ +-int _kgsl_get_context_id(struct kgsl_device *device, +- struct kgsl_context *context) ++int _kgsl_get_context_id(struct kgsl_device *device) + { + int id; + + idr_preload(GFP_KERNEL); + write_lock(&device->context_lock); +- id = idr_alloc(&device->context_idr, context, 1, ++ /* Allocate the slot but don't put a pointer in it yet */ ++ id = idr_alloc(&device->context_idr, NULL, 1, + KGSL_MEMSTORE_MAX, GFP_NOWAIT); + write_unlock(&device->context_lock); + idr_preload_end(); + +- if (id > 0) +- context->id = id; +- + return id; + } + +@@ -554,7 +551,7 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, + char name[64]; + int ret = 0, id; + +- id = _kgsl_get_context_id(device, context); ++ id = _kgsl_get_context_id(device); + if (id == -ENOSPC) { + /* + * Before declaring that there are no contexts left try +@@ -565,7 +562,7 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, + mutex_unlock(&device->mutex); + flush_workqueue(device->events_wq); + mutex_lock(&device->mutex); +- id = _kgsl_get_context_id(device, context); ++ id = _kgsl_get_context_id(device); + } + + if (id < 0) { +@@ -577,6 +574,8 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, + return id; + } + ++ context->id = id; ++ + kref_init(&context->refcount); + /* + * Get a refernce to the process private so its not destroyed, until +@@ -2580,6 +2579,12 @@ long kgsl_ioctl_drawctxt_create(struct kgsl_device_private *dev_priv, + goto done; + } + trace_kgsl_context_create(dev_priv->device, context, param->flags); ++ ++ /* Commit the pointer to the context in context_idr */ ++ write_lock(&device->context_lock); ++ idr_replace(&device->context_idr, context, context->id); ++ write_unlock(&device->context_lock); ++ + param->drawctxt_id = context->id; + done: + mutex_unlock(&device->mutex); diff --git a/Patches/Linux_CVEs/CVE-2016-8480/0.patch b/Patches/Linux_CVEs/CVE-2016-8480/0.patch new file mode 100644 index 00000000..aebaeb00 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8480/0.patch @@ -0,0 +1,56 @@ +From 0ed0f061bcd71940ed65de2ba46e37e709e31471 Mon Sep 17 00:00:00 2001 +From: Mallikarjuna Reddy Amireddy +Date: Tue, 22 Nov 2016 17:24:46 +0530 +Subject: qseecom: remove entry from qseecom_registered_app_list + +In an error handling case, the QSEECOM_IOCTL_LOAD_APP_REQ ioctl +freed the entry for new TA, but didn't removed it from +qseecom_registered_app_list. Make change to remove it. + +Change-Id: Id681fbf3c923027d3db875d506cbe3f971919a8d +Signed-off-by: Zhen Kong +Signed-off-by: Mallikarjuna Reddy Amireddy +--- + drivers/misc/qseecom.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index b1c97ba..270fb95 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -1349,6 +1349,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) + struct qseecom_command_scm_resp resp; + struct qseecom_check_app_ireq req; + struct qseecom_load_app_ireq load_req; ++ bool first_time = false; + + /* Copy the relevant information needed for loading the image */ + if (copy_from_user(&load_img_req, +@@ -1395,6 +1396,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) + &qseecom.registered_app_list_lock, flags); + ret = 0; + } else { ++ first_time = true; + pr_warn("App (%s) does'nt exist, loading apps for first time\n", + (char *)(load_img_req.img_name)); + /* Get the handle of the shared fd */ +@@ -1499,8 +1501,15 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) + load_img_req.app_id = app_id; + if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) { + pr_err("copy_to_user failed\n"); +- kzfree(entry); + ret = -EFAULT; ++ if (first_time == true) { ++ spin_lock_irqsave( ++ &qseecom.registered_app_list_lock, flags); ++ list_del(&entry->list); ++ spin_unlock_irqrestore( ++ &qseecom.registered_app_list_lock, flags); ++ kzfree(entry); ++ } + } + + loadapp_err: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8480/1.patch b/Patches/Linux_CVEs/CVE-2016-8480/1.patch new file mode 100644 index 00000000..fcb29892 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8480/1.patch @@ -0,0 +1,55 @@ +From cd70f6025a7bbce89af7a7abf4c40a219fdea406 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Fri, 4 Nov 2016 17:35:19 -0700 +Subject: qseecom: remove entry from qseecom_registered_app_list + +In an error handling case, the QSEECOM_IOCTL_LOAD_APP_REQ ioctl +freed the entry for new TA, but didn't removed it from +qseecom_registered_app_list. Make change to remove it. + +Change-Id: Id681fbf3c923027d3db875d506cbe3f971919a8d +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index db603f0..e9ebbee 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -2183,6 +2183,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) + struct qseecom_load_app_64bit_ireq load_req_64bit; + void *cmd_buf = NULL; + size_t cmd_len; ++ bool first_time = false; + + /* Copy the relevant information needed for loading the image */ + if (copy_from_user(&load_img_req, +@@ -2254,6 +2255,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) + &qseecom.registered_app_list_lock, flags); + ret = 0; + } else { ++ first_time = true; + pr_warn("App (%s) does'nt exist, loading apps for first time\n", + (char *)(load_img_req.img_name)); + /* Get the handle of the shared fd */ +@@ -2385,8 +2387,15 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) + load_img_req.app_id = app_id; + if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) { + pr_err("copy_to_user failed\n"); +- kzfree(entry); + ret = -EFAULT; ++ if (first_time == true) { ++ spin_lock_irqsave( ++ &qseecom.registered_app_list_lock, flags); ++ list_del(&entry->list); ++ spin_unlock_irqrestore( ++ &qseecom.registered_app_list_lock, flags); ++ kzfree(entry); ++ } + } + + loadapp_err: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8481/0.patch b/Patches/Linux_CVEs/CVE-2016-8481/0.patch new file mode 100644 index 00000000..5651b6b3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8481/0.patch @@ -0,0 +1,185 @@ +From ce9db0874906f6aedd80bb28d457eadfe38bdd02 Mon Sep 17 00:00:00 2001 +From: Sudheer Papothi +Date: Wed, 26 Oct 2016 01:07:04 +0530 +Subject: drivers: qcom: ultrasound: Lock async driver calls + +Adds lock to ioctl and other external calls to driver. +Adds missing null check in __usf_set_stream_param. + +Change-Id: I142f31c6bb46d6a394ad012077e1703875a120ad +Signed-off-by: Sudheer Papothi +--- + drivers/misc/qcom/qdsp6v2/ultrasound/usf.c | 66 ++++++++++++++++++++++++++---- + 1 file changed, 59 insertions(+), 7 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c +index d535ccb..9270dbc 100644 +--- a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c ++++ b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include "q6usm.h" +@@ -128,6 +129,8 @@ struct usf_type { + uint16_t conflicting_event_filters; + /* The requested buttons bitmap */ + uint16_t req_buttons_bitmap; ++ /* Mutex for exclusive operations (all public APIs) */ ++ struct mutex mutex; + }; + + struct usf_input_dev_type { +@@ -1376,9 +1379,22 @@ static int __usf_set_stream_param(struct usf_xx_type *usf_xx, + int dir) + { + struct us_client *usc = usf_xx->usc; +- struct us_port_data *port = &usc->port[dir]; ++ struct us_port_data *port; + int rc = 0; + ++ if (usc == NULL) { ++ pr_err("%s: usc is null\n", ++ __func__); ++ return -EFAULT; ++ } ++ ++ port = &usc->port[dir]; ++ if (port == NULL) { ++ pr_err("%s: port is null\n", ++ __func__); ++ return -EFAULT; ++ } ++ + if (port->param_buf == NULL) { + pr_err("%s: parameter buffer is null\n", + __func__); +@@ -1503,10 +1519,12 @@ static int usf_get_stream_param(struct usf_xx_type *usf_xx, + return __usf_get_stream_param(usf_xx, &get_stream_param, dir); + } /* usf_get_stream_param */ + +-static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++static long __usf_ioctl(struct usf_type *usf, ++ unsigned int cmd, ++ unsigned long arg) + { ++ + int rc = 0; +- struct usf_type *usf = file->private_data; + struct usf_xx_type *usf_xx = NULL; + + switch (cmd) { +@@ -1669,6 +1687,18 @@ static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + release_xx(usf_xx); + + return rc; ++} /* __usf_ioctl */ ++ ++static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ struct usf_type *usf = file->private_data; ++ int rc = 0; ++ ++ mutex_lock(&usf->mutex); ++ rc = __usf_ioctl(usf, cmd, arg); ++ mutex_unlock(&usf->mutex); ++ ++ return rc; + } /* usf_ioctl */ + + #ifdef CONFIG_COMPAT +@@ -2106,12 +2136,11 @@ static int usf_get_stream_param32(struct usf_xx_type *usf_xx, + return __usf_get_stream_param(usf_xx, &get_stream_param, dir); + } /* usf_get_stream_param32 */ + +-static long usf_compat_ioctl(struct file *file, ++static long __usf_compat_ioctl(struct usf_type *usf, + unsigned int cmd, + unsigned long arg) + { + int rc = 0; +- struct usf_type *usf = file->private_data; + struct usf_xx_type *usf_xx = NULL; + + switch (cmd) { +@@ -2119,7 +2148,7 @@ static long usf_compat_ioctl(struct file *file, + case US_START_RX: + case US_STOP_TX: + case US_STOP_RX: { +- return usf_ioctl(file, cmd, arg); ++ return __usf_ioctl(usf, cmd, arg); + } + + case US_SET_TX_INFO32: { +@@ -2228,6 +2257,20 @@ static long usf_compat_ioctl(struct file *file, + release_xx(usf_xx); + + return rc; ++} /* __usf_compat_ioctl */ ++ ++static long usf_compat_ioctl(struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ struct usf_type *usf = file->private_data; ++ int rc = 0; ++ ++ mutex_lock(&usf->mutex); ++ rc = __usf_compat_ioctl(usf, cmd, arg); ++ mutex_unlock(&usf->mutex); ++ ++ return rc; + } /* usf_compat_ioctl */ + #endif /* CONFIG_COMPAT */ + +@@ -2236,13 +2279,17 @@ static int usf_mmap(struct file *file, struct vm_area_struct *vms) + struct usf_type *usf = file->private_data; + int dir = OUT; + struct usf_xx_type *usf_xx = &usf->usf_tx; ++ int rc = 0; + ++ mutex_lock(&usf->mutex); + if (vms->vm_flags & USF_VM_WRITE) { /* RX buf mapping */ + dir = IN; + usf_xx = &usf->usf_rx; + } ++ rc = q6usm_get_virtual_address(dir, usf_xx->usc, vms); ++ mutex_unlock(&usf->mutex); + +- return q6usm_get_virtual_address(dir, usf_xx->usc, vms); ++ return rc; + } + + static uint16_t add_opened_dev(int minor) +@@ -2294,6 +2341,8 @@ static int usf_open(struct inode *inode, struct file *file) + usf->usf_tx.us_detect_type = USF_US_DETECT_UNDEF; + usf->usf_rx.us_detect_type = USF_US_DETECT_UNDEF; + ++ mutex_init(&usf->mutex); ++ + pr_debug("%s:usf in open\n", __func__); + return 0; + } +@@ -2304,6 +2353,7 @@ static int usf_release(struct inode *inode, struct file *file) + + pr_debug("%s: release entry\n", __func__); + ++ mutex_lock(&usf->mutex); + usf_release_input(usf); + + usf_disable(&usf->usf_tx); +@@ -2311,6 +2361,8 @@ static int usf_release(struct inode *inode, struct file *file) + + s_opened_devs[usf->dev_ind] = 0; + ++ mutex_unlock(&usf->mutex); ++ mutex_destroy(&usf->mutex); + kfree(usf); + pr_debug("%s: release exit\n", __func__); + return 0; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8481/1.patch b/Patches/Linux_CVEs/CVE-2016-8481/1.patch new file mode 100644 index 00000000..ab99a331 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8481/1.patch @@ -0,0 +1,26 @@ +From 831da5d113d214db6894e9fd0ce98762ee8a544a Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Tue, 6 Dec 2016 09:57:57 -0800 +Subject: [PATCH] Kconfig: msm: disable ultrasound driver + +Bug: 31906415 +Bug: 31906657 +Bug: 32553868 +Change-Id: Iab736a5d5622098c89c76dbe6b0b395652bbae57 +Signed-off-by: Nick Desaulniers +--- + sound/soc/msm/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig +index 6eb168e4d10d5..2e6f642241ef3 100644 +--- a/sound/soc/msm/Kconfig ++++ b/sound/soc/msm/Kconfig +@@ -267,7 +267,6 @@ config SND_SOC_MSM8994 + select SND_SOC_MSM_HDMI_CODEC_RX + select QTI_PP + select SND_SOC_CPE +- select MSM_ULTRASOUND + select SND_HWDEP + help + To add support for SoC audio on MSM8994. diff --git a/Patches/Linux_CVEs/CVE-2016-8483/0.patch b/Patches/Linux_CVEs/CVE-2016-8483/0.patch new file mode 100644 index 00000000..0b57e4dd --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8483/0.patch @@ -0,0 +1,34 @@ +From 6997dcb7ade1315474855821e64782205cb0b53a Mon Sep 17 00:00:00 2001 +From: Mohammed Khajapasha +Date: Tue, 28 Jun 2016 11:55:34 +0530 +Subject: msm-core: use get_user() API to read userspace data/settings + +Currently userspace data is getting accessed directly +and leading to crash, So use get_user() API to copy +userspace data/settings to kernel space. + +Change-Id: I3a75ec9503d8207829640bf88e1c3160bf72c9f0 +Signed-off-by: Mohammed Khajapasha +--- + drivers/power/qcom/msm-core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/power/qcom/msm-core.c b/drivers/power/qcom/msm-core.c +index 286c89f..8a55fd0 100644 +--- a/drivers/power/qcom/msm-core.c ++++ b/drivers/power/qcom/msm-core.c +@@ -486,9 +486,9 @@ static long msm_core_ioctl(struct file *file, unsigned int cmd, + return -EINVAL; + + get_user(cluster, &argp->cluster); +- mpidr = (argp->cluster << (MAX_CORES_PER_CLUSTER * ++ mpidr = (cluster << (MAX_CORES_PER_CLUSTER * + MAX_NUM_OF_CLUSTERS)); +- cpumask = argp->cpumask; ++ get_user(cpumask, &argp->cpumask); + + switch (cmd) { + case EA_LEAKAGE: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8483/1.patch b/Patches/Linux_CVEs/CVE-2016-8483/1.patch new file mode 100644 index 00000000..e4c3c216 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8483/1.patch @@ -0,0 +1,48 @@ +From 7e147f4532394f06c3d7bce9cc6e682785754e45 Mon Sep 17 00:00:00 2001 +From: Mohammed Khajapasha +Date: Tue, 28 Jun 2016 11:55:34 +0530 +Subject: msm-core: use get_user() API to read userspace data/settings + +Currently userspace data is getting accessed directly +and leading to crash, So use get_user() API to copy +userspace data/settings to kernel space. + +Change-Id: I3a75ec9503d8207829640bf88e1c3160bf72c9f0 +Signed-off-by: Mohammed Khajapasha +Signed-off-by: Srinivasarao P +--- + drivers/power/qcom/msm-core.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/power/qcom/msm-core.c b/drivers/power/qcom/msm-core.c +index 406f097..f644950 100644 +--- a/drivers/power/qcom/msm-core.c ++++ b/drivers/power/qcom/msm-core.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The 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 +@@ -441,14 +441,15 @@ static long msm_core_ioctl(struct file *file, unsigned int cmd, + struct sched_params __user *argp = (struct sched_params __user *)arg; + int i, cpu = num_possible_cpus(); + int mpidr; +- int cpumask; ++ int cluster, cpumask; + + if (!argp) + return -EINVAL; + +- mpidr = (argp->cluster << (MAX_CORES_PER_CLUSTER * ++ get_user(cluster, &argp->cluster); ++ mpidr = (cluster << (MAX_CORES_PER_CLUSTER * + MAX_NUM_OF_CLUSTERS)); +- cpumask = argp->cpumask; ++ get_user(cpumask, &argp->cpumask); + + switch (cmd) { + case EA_LEAKAGE: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8650/0.patch b/Patches/Linux_CVEs/CVE-2016-8650/0.patch new file mode 100644 index 00000000..e449ab06 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8650/0.patch @@ -0,0 +1,100 @@ +From f5527fffff3f002b0a6b376163613b82f69de073 Mon Sep 17 00:00:00 2001 +From: Andrey Ryabinin +Date: Thu, 24 Nov 2016 13:23:10 +0000 +Subject: mpi: Fix NULL ptr dereference in mpi_powm() [ver #3] + +This fixes CVE-2016-8650. + +If mpi_powm() is given a zero exponent, it wants to immediately return +either 1 or 0, depending on the modulus. However, if the result was +initalised with zero limb space, no limbs space is allocated and a +NULL-pointer exception ensues. + +Fix this by allocating a minimal amount of limb space for the result when +the 0-exponent case when the result is 1 and not touching the limb space +when the result is 0. + +This affects the use of RSA keys and X.509 certificates that carry them. + +BUG: unable to handle kernel NULL pointer dereference at (null) +IP: [] mpi_powm+0x32/0x7e6 +PGD 0 +Oops: 0002 [#1] SMP +Modules linked in: +CPU: 3 PID: 3014 Comm: keyctl Not tainted 4.9.0-rc6-fscache+ #278 +Hardware name: ASUS All Series/H97-PLUS, BIOS 2306 10/09/2014 +task: ffff8804011944c0 task.stack: ffff880401294000 +RIP: 0010:[] [] mpi_powm+0x32/0x7e6 +RSP: 0018:ffff880401297ad8 EFLAGS: 00010212 +RAX: 0000000000000000 RBX: ffff88040868bec0 RCX: ffff88040868bba0 +RDX: ffff88040868b260 RSI: ffff88040868bec0 RDI: ffff88040868bee0 +RBP: ffff880401297ba8 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000047 R11: ffffffff8183b210 R12: 0000000000000000 +R13: ffff8804087c7600 R14: 000000000000001f R15: ffff880401297c50 +FS: 00007f7a7918c700(0000) GS:ffff88041fb80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000000 CR3: 0000000401250000 CR4: 00000000001406e0 +Stack: + ffff88040868bec0 0000000000000020 ffff880401297b00 ffffffff81376cd4 + 0000000000000100 ffff880401297b10 ffffffff81376d12 ffff880401297b30 + ffffffff81376f37 0000000000000100 0000000000000000 ffff880401297ba8 +Call Trace: + [] ? __sg_page_iter_next+0x43/0x66 + [] ? sg_miter_get_next_page+0x1b/0x5d + [] ? sg_miter_next+0x17/0xbd + [] ? mpi_read_raw_from_sgl+0xf2/0x146 + [] rsa_verify+0x9d/0xee + [] ? pkcs1pad_sg_set_buf+0x2e/0xbb + [] pkcs1pad_verify+0xc0/0xe1 + [] public_key_verify_signature+0x1b0/0x228 + [] x509_check_for_self_signed+0xa1/0xc4 + [] x509_cert_parse+0x167/0x1a1 + [] x509_key_preparse+0x21/0x1a1 + [] asymmetric_key_preparse+0x34/0x61 + [] key_create_or_update+0x145/0x399 + [] SyS_add_key+0x154/0x19e + [] do_syscall_64+0x80/0x191 + [] entry_SYSCALL64_slow_path+0x25/0x25 +Code: 56 41 55 41 54 53 48 81 ec a8 00 00 00 44 8b 71 04 8b 42 04 4c 8b 67 18 45 85 f6 89 45 80 0f 84 b4 06 00 00 85 c0 75 2f 41 ff ce <49> c7 04 24 01 00 00 00 b0 01 75 0b 48 8b 41 18 48 83 38 01 0f +RIP [] mpi_powm+0x32/0x7e6 + RSP +CR2: 0000000000000000 +---[ end trace d82015255d4a5d8d ]--- + +Basically, this is a backport of a libgcrypt patch: + + http://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=patch;h=6e1adb05d290aeeb1c230c763970695f4a538526 + +Fixes: cdec9cb5167a ("crypto: GnuPG based MPI lib - source files (part 1)") +Signed-off-by: Andrey Ryabinin +Signed-off-by: David Howells +cc: Dmitry Kasatkin +cc: linux-ima-devel@lists.sourceforge.net +cc: stable@vger.kernel.org +Signed-off-by: James Morris +--- + lib/mpi/mpi-pow.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c +index 5464c87..e24388a 100644 +--- a/lib/mpi/mpi-pow.c ++++ b/lib/mpi/mpi-pow.c +@@ -64,8 +64,13 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) + if (!esize) { + /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 + * depending on if MOD equals 1. */ +- rp[0] = 1; + res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; ++ if (res->nlimbs) { ++ if (mpi_resize(res, 1) < 0) ++ goto enomem; ++ rp = res->d; ++ rp[0] = 1; ++ } + res->sign = 0; + goto leave; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-8655/0.patch b/Patches/Linux_CVEs/CVE-2016-8655/0.patch new file mode 100644 index 00000000..0cded9fd --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-8655/0.patch @@ -0,0 +1,92 @@ +From 84ac7260236a49c79eede91617700174c2c19b0c Mon Sep 17 00:00:00 2001 +From: Philip Pettersson +Date: Wed, 30 Nov 2016 14:55:36 -0800 +Subject: packet: fix race condition in packet_set_ring + +When packet_set_ring creates a ring buffer it will initialize a +struct timer_list if the packet version is TPACKET_V3. This value +can then be raced by a different thread calling setsockopt to +set the version to TPACKET_V1 before packet_set_ring has finished. + +This leads to a use-after-free on a function pointer in the +struct timer_list when the socket is closed as the previously +initialized timer will not be deleted. + +The bug is fixed by taking lock_sock(sk) in packet_setsockopt when +changing the packet version while also taking the lock at the start +of packet_set_ring. + +Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.") +Signed-off-by: Philip Pettersson +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/packet/af_packet.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index d2238b2..dd23323 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3648,19 +3648,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv + + if (optlen != sizeof(val)) + return -EINVAL; +- if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) +- return -EBUSY; + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; + switch (val) { + case TPACKET_V1: + case TPACKET_V2: + case TPACKET_V3: +- po->tp_version = val; +- return 0; ++ break; + default: + return -EINVAL; + } ++ lock_sock(sk); ++ if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { ++ ret = -EBUSY; ++ } else { ++ po->tp_version = val; ++ ret = 0; ++ } ++ release_sock(sk); ++ return ret; + } + case PACKET_RESERVE: + { +@@ -4164,6 +4170,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + /* Added to avoid minimal code churn */ + struct tpacket_req *req = &req_u->req; + ++ lock_sock(sk); + /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ + if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { + net_warn_ratelimited("Tx-ring is not supported.\n"); +@@ -4245,7 +4252,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + goto out; + } + +- lock_sock(sk); + + /* Detach socket from network */ + spin_lock(&po->bind_lock); +@@ -4294,11 +4300,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + if (!tx_ring) + prb_shutdown_retire_blk_timer(po, rb_queue); + } +- release_sock(sk); + + if (pg_vec) + free_pg_vec(pg_vec, order, req->tp_block_nr); + out: ++ release_sock(sk); + return err; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-9120/0.patch b/Patches/Linux_CVEs/CVE-2016-9120/0.patch new file mode 100644 index 00000000..7f79fcd2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9120/0.patch @@ -0,0 +1,178 @@ +From 9590232bb4f4cc824f3425a6e1349afbe6d6d2b7 Mon Sep 17 00:00:00 2001 +From: EunTaik Lee +Date: Wed, 24 Feb 2016 04:38:06 +0000 +Subject: staging/android/ion : fix a race condition in the ion driver + +There is a use-after-free problem in the ion driver. +This is caused by a race condition in the ion_ioctl() +function. + +A handle has ref count of 1 and two tasks on different +cpus calls ION_IOC_FREE simultaneously. + +cpu 0 cpu 1 +------------------------------------------------------- +ion_handle_get_by_id() +(ref == 2) + ion_handle_get_by_id() + (ref == 3) + +ion_free() +(ref == 2) + +ion_handle_put() +(ref == 1) + + ion_free() + (ref == 0 so ion_handle_destroy() is + called + and the handle is freed.) + + ion_handle_put() is called and it + decreases the slub's next free pointer + +The problem is detected as an unaligned access in the +spin lock functions since it uses load exclusive + instruction. In some cases it corrupts the slub's +free pointer which causes a mis-aligned access to the +next free pointer.(kmalloc returns a pointer like +ffffc0745b4580aa). And it causes lots of other +hard-to-debug problems. + +This symptom is caused since the first member in the +ion_handle structure is the reference count and the +ion driver decrements the reference after it has been +freed. + +To fix this problem client->lock mutex is extended +to protect all the codes that uses the handle. + +Signed-off-by: Eun Taik Lee +Reviewed-by: Laura Abbott +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/android/ion/ion.c | 55 ++++++++++++++++++++++++++++++--------- + 1 file changed, 42 insertions(+), 13 deletions(-) + mode change 100644 => 100755 drivers/staging/android/ion/ion.c + +diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c +old mode 100644 +new mode 100755 +index 7ff2a7e..33b390e +--- a/drivers/staging/android/ion/ion.c ++++ b/drivers/staging/android/ion/ion.c +@@ -387,13 +387,22 @@ static void ion_handle_get(struct ion_handle *handle) + kref_get(&handle->ref); + } + +-static int ion_handle_put(struct ion_handle *handle) ++static int ion_handle_put_nolock(struct ion_handle *handle) ++{ ++ int ret; ++ ++ ret = kref_put(&handle->ref, ion_handle_destroy); ++ ++ return ret; ++} ++ ++int ion_handle_put(struct ion_handle *handle) + { + struct ion_client *client = handle->client; + int ret; + + mutex_lock(&client->lock); +- ret = kref_put(&handle->ref, ion_handle_destroy); ++ ret = ion_handle_put_nolock(handle); + mutex_unlock(&client->lock); + + return ret; +@@ -417,20 +426,30 @@ static struct ion_handle *ion_handle_lookup(struct ion_client *client, + return ERR_PTR(-EINVAL); + } + +-static struct ion_handle *ion_handle_get_by_id(struct ion_client *client, ++static struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + int id) + { + struct ion_handle *handle; + +- mutex_lock(&client->lock); + handle = idr_find(&client->idr, id); + if (handle) + ion_handle_get(handle); +- mutex_unlock(&client->lock); + + return handle ? handle : ERR_PTR(-EINVAL); + } + ++struct ion_handle *ion_handle_get_by_id(struct ion_client *client, ++ int id) ++{ ++ struct ion_handle *handle; ++ ++ mutex_lock(&client->lock); ++ handle = ion_handle_get_by_id_nolock(client, id); ++ mutex_unlock(&client->lock); ++ ++ return handle; ++} ++ + static bool ion_handle_validate(struct ion_client *client, + struct ion_handle *handle) + { +@@ -532,22 +551,28 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + } + EXPORT_SYMBOL(ion_alloc); + +-void ion_free(struct ion_client *client, struct ion_handle *handle) ++static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) + { + bool valid_handle; + + BUG_ON(client != handle->client); + +- mutex_lock(&client->lock); + valid_handle = ion_handle_validate(client, handle); + + if (!valid_handle) { + WARN(1, "%s: invalid handle passed to free.\n", __func__); +- mutex_unlock(&client->lock); + return; + } ++ ion_handle_put_nolock(handle); ++} ++ ++void ion_free(struct ion_client *client, struct ion_handle *handle) ++{ ++ BUG_ON(client != handle->client); ++ ++ mutex_lock(&client->lock); ++ ion_free_nolock(client, handle); + mutex_unlock(&client->lock); +- ion_handle_put(handle); + } + EXPORT_SYMBOL(ion_free); + +@@ -1332,11 +1357,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { + struct ion_handle *handle; + +- handle = ion_handle_get_by_id(client, data.handle.handle); +- if (IS_ERR(handle)) ++ mutex_lock(&client->lock); ++ handle = ion_handle_get_by_id_nolock(client, data.handle.handle); ++ if (IS_ERR(handle)) { ++ mutex_unlock(&client->lock); + return PTR_ERR(handle); +- ion_free(client, handle); +- ion_handle_put(handle); ++ } ++ ion_free_nolock(client, handle); ++ ion_handle_put_nolock(handle); ++ mutex_unlock(&client->lock); + break; + } + case ION_IOC_SHARE: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-9120/1.patch b/Patches/Linux_CVEs/CVE-2016-9120/1.patch new file mode 100644 index 00000000..6216356e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9120/1.patch @@ -0,0 +1,89 @@ +From e9fde8664651a566df43c7439e27d59cc5d60460 Mon Sep 17 00:00:00 2001 +From: Daniel Rosenberg +Date: Wed, 2 Nov 2016 17:43:51 -0700 +Subject: [PATCH] ion: Fix use after free during ION_IOC_ALLOC + +If a user happens to call ION_IOC_FREE during an +ION_IOC_ALLOC on the just allocated id, and the +copy_to_user fails, the cleanup code will attempt +to free an already freed handle. + +This adds a wrapper for ion_alloc that adds an +ion_handle_get to avoid this. + +Bug: 31568617 +Change-Id: I476e5bd5372b5178a213f1fea143d270cf9361ed +Signed-off-by: Daniel Rosenberg +--- + drivers/staging/android/ion/ion.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c +index 8bbbb38dc7c41..63e6b7d795f47 100755 +--- a/drivers/staging/android/ion/ion.c ++++ b/drivers/staging/android/ion/ion.c +@@ -507,9 +507,9 @@ static int ion_handle_add(struct ion_client *client, struct ion_handle *handle) + return 0; + } + +-struct ion_handle *ion_alloc(struct ion_client *client, size_t len, ++static struct ion_handle *__ion_alloc(struct ion_client *client, size_t len, + size_t align, unsigned int heap_id_mask, +- unsigned int flags) ++ unsigned int flags, bool grab_handle) + { + struct ion_handle *handle; + struct ion_device *dev = client->dev; +@@ -604,6 +604,8 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + return handle; + + mutex_lock(&client->lock); ++ if (grab_handle) ++ ion_handle_get(handle); + ret = ion_handle_add(client, handle); + mutex_unlock(&client->lock); + if (ret) { +@@ -613,6 +615,13 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, + + return handle; + } ++ ++struct ion_handle *ion_alloc(struct ion_client *client, size_t len, ++ size_t align, unsigned int heap_id_mask, ++ unsigned int flags) ++{ ++ return __ion_alloc(client, len, align, heap_id_mask, flags, false); ++} + EXPORT_SYMBOL(ion_alloc); + + static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle) +@@ -1488,10 +1497,10 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + { + struct ion_handle *handle; + +- handle = ion_alloc(client, data.allocation.len, ++ handle = __ion_alloc(client, data.allocation.len, + data.allocation.align, + data.allocation.heap_id_mask, +- data.allocation.flags); ++ data.allocation.flags, true); + if (IS_ERR(handle)) + return PTR_ERR(handle); + +@@ -1568,11 +1577,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + + if (dir & _IOC_READ) { + if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { +- if (cleanup_handle) ++ if (cleanup_handle) { + ion_free(client, cleanup_handle); ++ ion_handle_put(cleanup_handle); ++ } + return -EFAULT; + } + } ++ if (cleanup_handle) ++ ion_handle_put(cleanup_handle); + return ret; + } + diff --git a/Patches/Linux_CVEs/CVE-2016-9191/0.patch b/Patches/Linux_CVEs/CVE-2016-9191/0.patch new file mode 100644 index 00000000..cb95d37f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9191/0.patch @@ -0,0 +1,87 @@ +From 93362fa47fe98b62e4a34ab408c4a418432e7939 Mon Sep 17 00:00:00 2001 +From: Zhou Chengming +Date: Fri, 6 Jan 2017 09:32:32 +0800 +Subject: sysctl: Drop reference added by grab_header in proc_sys_readdir + +Fixes CVE-2016-9191, proc_sys_readdir doesn't drop reference +added by grab_header when return from !dir_emit_dots path. +It can cause any path called unregister_sysctl_table will +wait forever. + +The calltrace of CVE-2016-9191: + +[ 5535.960522] Call Trace: +[ 5535.963265] [] schedule+0x3f/0xa0 +[ 5535.968817] [] schedule_timeout+0x3db/0x6f0 +[ 5535.975346] [] ? wait_for_completion+0x45/0x130 +[ 5535.982256] [] wait_for_completion+0xc3/0x130 +[ 5535.988972] [] ? wake_up_q+0x80/0x80 +[ 5535.994804] [] drop_sysctl_table+0xc4/0xe0 +[ 5536.001227] [] drop_sysctl_table+0x77/0xe0 +[ 5536.007648] [] unregister_sysctl_table+0x4d/0xa0 +[ 5536.014654] [] unregister_sysctl_table+0x7f/0xa0 +[ 5536.021657] [] unregister_sched_domain_sysctl+0x15/0x40 +[ 5536.029344] [] partition_sched_domains+0x44/0x450 +[ 5536.036447] [] ? __mutex_unlock_slowpath+0x111/0x1f0 +[ 5536.043844] [] rebuild_sched_domains_locked+0x64/0xb0 +[ 5536.051336] [] update_flag+0x11d/0x210 +[ 5536.057373] [] ? mutex_lock_nested+0x2df/0x450 +[ 5536.064186] [] ? cpuset_css_offline+0x1b/0x60 +[ 5536.070899] [] ? trace_hardirqs_on+0xd/0x10 +[ 5536.077420] [] ? mutex_lock_nested+0x2df/0x450 +[ 5536.084234] [] ? css_killed_work_fn+0x25/0x220 +[ 5536.091049] [] cpuset_css_offline+0x35/0x60 +[ 5536.097571] [] css_killed_work_fn+0x5c/0x220 +[ 5536.104207] [] process_one_work+0x1df/0x710 +[ 5536.110736] [] ? process_one_work+0x160/0x710 +[ 5536.117461] [] worker_thread+0x12b/0x4a0 +[ 5536.123697] [] ? process_one_work+0x710/0x710 +[ 5536.130426] [] kthread+0xfe/0x120 +[ 5536.135991] [] ret_from_fork+0x1f/0x40 +[ 5536.142041] [] ? kthread_create_on_node+0x230/0x230 + +One cgroup maintainer mentioned that "cgroup is trying to offline +a cpuset css, which takes place under cgroup_mutex. The offlining +ends up trying to drain active usages of a sysctl table which apprently +is not happening." +The real reason is that proc_sys_readdir doesn't drop reference added +by grab_header when return from !dir_emit_dots path. So this cpuset +offline path will wait here forever. + +See here for details: http://www.openwall.com/lists/oss-security/2016/11/04/13 + +Fixes: f0c3b5093add ("[readdir] convert procfs") +Cc: stable@vger.kernel.org +Reported-by: CAI Qian +Tested-by: Yang Shukui +Signed-off-by: Zhou Chengming +Acked-by: Al Viro +Signed-off-by: Eric W. Biederman +--- + fs/proc/proc_sysctl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c +index 55313d9..d4e37ac 100644 +--- a/fs/proc/proc_sysctl.c ++++ b/fs/proc/proc_sysctl.c +@@ -709,7 +709,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx) + ctl_dir = container_of(head, struct ctl_dir, header); + + if (!dir_emit_dots(file, ctx)) +- return 0; ++ goto out; + + pos = 2; + +@@ -719,6 +719,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx) + break; + } + } ++out: + sysctl_head_finish(head); + return 0; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-9555/0.patch b/Patches/Linux_CVEs/CVE-2016-9555/0.patch new file mode 100644 index 00000000..c96ff897 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9555/0.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)); + diff --git a/Patches/Linux_CVEs/CVE-2016-9576/0.patch b/Patches/Linux_CVEs/CVE-2016-9576/0.patch new file mode 100644 index 00000000..a640c7fc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9576/0.patch @@ -0,0 +1,39 @@ +From a0ac402cfcdc904f9772e1762b3fda112dcc56a0 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 6 Dec 2016 16:18:14 -0800 +Subject: [PATCH] Don't feed anything but regular iovec's to + blk_rq_map_user_iov + +In theory we could map other things, but there's a reason that function +is called "user_iov". Using anything else (like splice can do) just +confuses it. + +Reported-and-tested-by: Johannes Thumshirn +Cc: Al Viro +Signed-off-by: Linus Torvalds +--- + block/blk-map.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/block/blk-map.c b/block/blk-map.c +index b8657fa8dc9af..27fd8d92892d4 100644 +--- a/block/blk-map.c ++++ b/block/blk-map.c +@@ -118,6 +118,9 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, + struct iov_iter i; + int ret; + ++ if (!iter_is_iovec(iter)) ++ goto fail; ++ + if (map_data) + copy = true; + else if (iov_iter_alignment(iter) & align) +@@ -140,6 +143,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, + + unmap_rq: + __blk_rq_unmap_user(bio); ++fail: + rq->bio = NULL; + return -EINVAL; + } diff --git a/Patches/Linux_CVEs/CVE-2016-9604/0.patch b/Patches/Linux_CVEs/CVE-2016-9604/0.patch new file mode 100644 index 00000000..3aeadfbb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9604/0.patch @@ -0,0 +1,82 @@ +From 44c037827f0aeddbbbb323930fa3d09a7b4fffca Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 18 Apr 2017 15:31:07 +0100 +Subject: KEYS: Disallow keyrings beginning with '.' to be joined as session + keyrings + +commit ee8f844e3c5a73b999edf733df1c529d6503ec2f upstream. + +This fixes CVE-2016-9604. + +Keyrings whose name begin with a '.' are special internal keyrings and so +userspace isn't allowed to create keyrings by this name to prevent +shadowing. However, the patch that added the guard didn't fix +KEYCTL_JOIN_SESSION_KEYRING. Not only can that create dot-named keyrings, +it can also subscribe to them as a session keyring if they grant SEARCH +permission to the user. + +This, for example, allows a root process to set .builtin_trusted_keys as +its session keyring, at which point it has full access because now the +possessor permissions are added. This permits root to add extra public +keys, thereby bypassing module verification. + +This also affects kexec and IMA. + +This can be tested by (as root): + + keyctl session .builtin_trusted_keys + keyctl add user a a @s + keyctl list @s + +which on my test box gives me: + + 2 keys in keyring: + 180010936: ---lswrv 0 0 asymmetric: Build time autogenerated kernel key: ae3d4a31b82daa8e1a75b49dc2bba949fd992a05 + 801382539: --alswrv 0 0 user: a + + +Fix this by rejecting names beginning with a '.' in the keyctl. + +Signed-off-by: David Howells +Acked-by: Mimi Zohar +cc: linux-ima-devel@lists.sourceforge.net +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/keyctl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index fee27fe..af86b35 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -277,7 +277,8 @@ error: + * Create and join an anonymous session keyring or join a named session + * keyring, creating it if necessary. A named session keyring must have Search + * permission for it to be joined. Session keyrings without this permit will +- * be skipped over. ++ * be skipped over. It is not permitted for userspace to create or join ++ * keyrings whose name begin with a dot. + * + * If successful, the ID of the joined session keyring will be returned. + */ +@@ -294,12 +295,16 @@ long keyctl_join_session_keyring(const char __user *_name) + ret = PTR_ERR(name); + goto error; + } ++ ++ ret = -EPERM; ++ if (name[0] == '.') ++ goto error_name; + } + + /* join the session */ + ret = join_session_keyring(name); ++error_name: + kfree(name); +- + error: + return ret; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-9754/0.patch b/Patches/Linux_CVEs/CVE-2016-9754/0.patch new file mode 100644 index 00000000..50952d96 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9754/0.patch @@ -0,0 +1,89 @@ +From 59643d1535eb220668692a5359de22545af579f6 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (Red Hat)" +Date: Fri, 13 May 2016 09:34:12 -0400 +Subject: ring-buffer: Prevent overflow of size in ring_buffer_resize() + +If the size passed to ring_buffer_resize() is greater than MAX_LONG - BUF_PAGE_SIZE +then the DIV_ROUND_UP() will return zero. + +Here's the details: + + # echo 18014398509481980 > /sys/kernel/debug/tracing/buffer_size_kb + +tracing_entries_write() processes this and converts kb to bytes. + + 18014398509481980 << 10 = 18446744073709547520 + +and this is passed to ring_buffer_resize() as unsigned long size. + + size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); + +Where DIV_ROUND_UP(a, b) is (a + b - 1)/b + +BUF_PAGE_SIZE is 4080 and here + + 18446744073709547520 + 4080 - 1 = 18446744073709551599 + +where 18446744073709551599 is still smaller than 2^64 + + 2^64 - 18446744073709551599 = 17 + +But now 18446744073709551599 / 4080 = 4521260802379792 + +and size = size * 4080 = 18446744073709551360 + +This is checked to make sure its still greater than 2 * 4080, +which it is. + +Then we convert to the number of buffer pages needed. + + nr_page = DIV_ROUND_UP(size, BUF_PAGE_SIZE) + +but this time size is 18446744073709551360 and + + 2^64 - (18446744073709551360 + 4080 - 1) = -3823 + +Thus it overflows and the resulting number is less than 4080, which makes + + 3823 / 4080 = 0 + +an nr_pages is set to this. As we already checked against the minimum that +nr_pages may be, this causes the logic to fail as well, and we crash the +kernel. + +There's no reason to have the two DIV_ROUND_UP() (that's just result of +historical code changes), clean up the code and fix this bug. + +Cc: stable@vger.kernel.org # 3.5+ +Fixes: 83f40318dab00 ("ring-buffer: Make removal of ring buffer pages atomic") +Signed-off-by: Steven Rostedt +--- + kernel/trace/ring_buffer.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 99d64cd..9c14373 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -1657,14 +1657,13 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size, + !cpumask_test_cpu(cpu_id, buffer->cpumask)) + return size; + +- size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); +- size *= BUF_PAGE_SIZE; ++ nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); + + /* we need a minimum of two pages */ +- if (size < BUF_PAGE_SIZE * 2) +- size = BUF_PAGE_SIZE * 2; ++ if (nr_pages < 2) ++ nr_pages = 2; + +- nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); ++ size = nr_pages * BUF_PAGE_SIZE; + + /* + * Don't succeed if resizing is disabled, as a reader might be +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-9793/0.patch b/Patches/Linux_CVEs/CVE-2016-9793/0.patch new file mode 100644 index 00000000..2f44e337 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9793/0.patch @@ -0,0 +1,49 @@ +From b98b0bc8c431e3ceb4b26b0dfc8db509518fb290 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 2 Dec 2016 09:44:53 -0800 +Subject: net: avoid signed overflows for SO_{SND|RCV}BUFFORCE + +CAP_NET_ADMIN users should not be allowed to set negative +sk_sndbuf or sk_rcvbuf values, as it can lead to various memory +corruptions, crashes, OOM... + +Note that before commit 82981930125a ("net: cleanups in +sock_setsockopt()"), the bug was even more serious, since SO_SNDBUF +and SO_RCVBUF were vulnerable. + +This needs to be backported to all known linux kernels. + +Again, many thanks to syzkaller team for discovering this gem. + +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +--- + net/core/sock.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index 5e3ca41..00a074d 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -715,7 +715,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, + val = min_t(u32, val, sysctl_wmem_max); + set_sndbuf: + sk->sk_userlocks |= SOCK_SNDBUF_LOCK; +- sk->sk_sndbuf = max_t(u32, val * 2, SOCK_MIN_SNDBUF); ++ sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF); + /* Wake up sending tasks if we upped the value. */ + sk->sk_write_space(sk); + break; +@@ -751,7 +751,7 @@ set_rcvbuf: + * returning the value we actually used in getsockopt + * is the most desirable behavior. + */ +- sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF); ++ sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF); + break; + + case SO_RCVBUFFORCE: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-9794/0.patch b/Patches/Linux_CVEs/CVE-2016-9794/0.patch new file mode 100644 index 00000000..0c23cfde --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9794/0.patch @@ -0,0 +1,44 @@ +From 3aa02cb664c5fb1042958c8d1aa8c35055a2ebc4 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 14 Apr 2016 18:02:37 +0200 +Subject: ALSA: pcm : Call kill_fasync() in stream lock + +Currently kill_fasync() is called outside the stream lock in +snd_pcm_period_elapsed(). This is potentially racy, since the stream +may get released even during the irq handler is running. Although +snd_pcm_release_substream() calls snd_pcm_drop(), this doesn't +guarantee that the irq handler finishes, thus the kill_fasync() call +outside the stream spin lock may be invoked after the substream is +detached, as recently reported by KASAN. + +As a quick workaround, move kill_fasync() call inside the stream +lock. The fasync is rarely used interface, so this shouldn't have a +big impact from the performance POV. + +Ideally, we should implement some sync mechanism for the proper finish +of stream and irq handler. But this oneliner should suffice for most +cases, so far. + +Reported-by: Baozeng Ding +Signed-off-by: Takashi Iwai +--- + sound/core/pcm_lib.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c +index 3a9b66c..0aca397 100644 +--- a/sound/core/pcm_lib.c ++++ b/sound/core/pcm_lib.c +@@ -1886,8 +1886,8 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) + snd_timer_interrupt(substream->timer, 1); + #endif + _end: +- snd_pcm_stream_unlock_irqrestore(substream, flags); + kill_fasync(&runtime->fasync, SIGIO, POLL_IN); ++ snd_pcm_stream_unlock_irqrestore(substream, flags); + } + + EXPORT_SYMBOL(snd_pcm_period_elapsed); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2016-9794/1.patch b/Patches/Linux_CVEs/CVE-2016-9794/1.patch new file mode 100644 index 00000000..777956cf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9794/1.patch @@ -0,0 +1,103 @@ + + + +kernel/git/stable/linux-stable.git - Linux kernel stable tree + + + + + + + + + + +
      + + + + +
      +aboutsummaryrefslogtreecommitdiffstats
      + + + +
      +
      +
      Bad object id: a27178e05b7c332522df40904f27674e36ee3757
      +
      + +
      + + diff --git a/Patches/Linux_CVEs/CVE-2016-9806/0.patch b/Patches/Linux_CVEs/CVE-2016-9806/0.patch new file mode 100644 index 00000000..9c899b7e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2016-9806/0.patch @@ -0,0 +1,50 @@ +From 92964c79b357efd980812c4de5c1fd2ec8bb5520 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Mon, 16 May 2016 17:28:16 +0800 +Subject: netlink: Fix dump skb leak/double free + +When we free cb->skb after a dump, we do it after releasing the +lock. This means that a new dump could have started in the time +being and we'll end up freeing their skb instead of ours. + +This patch saves the skb and module before we unlock so we free +the right memory. + +Fixes: 16b304f3404f ("netlink: Eliminate kmalloc in netlink dump operation.") +Reported-by: Baozeng Ding +Signed-off-by: Herbert Xu +Acked-by: Cong Wang +Signed-off-by: David S. Miller +--- + net/netlink/af_netlink.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index aeefe12..627f898 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2059,6 +2059,7 @@ static int netlink_dump(struct sock *sk) + struct netlink_callback *cb; + struct sk_buff *skb = NULL; + struct nlmsghdr *nlh; ++ struct module *module; + int len, err = -ENOBUFS; + int alloc_min_size; + int alloc_size; +@@ -2134,9 +2135,11 @@ static int netlink_dump(struct sock *sk) + cb->done(cb); + + nlk->cb_running = false; ++ module = cb->module; ++ skb = cb->skb; + mutex_unlock(nlk->cb_mutex); +- module_put(cb->module); +- consume_skb(cb->skb); ++ module_put(module); ++ consume_skb(skb); + return 0; + + errout_skb: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0403/0.patch b/Patches/Linux_CVEs/CVE-2017-0403/0.patch new file mode 100644 index 00000000..6de691a0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0403/0.patch @@ -0,0 +1,42 @@ +From 2c5c1fd0d2a2a96fab750fa332cb703022c16c04 Mon Sep 17 00:00:00 2001 +From: John Dias +Date: Wed, 9 Nov 2016 11:03:57 -0800 +Subject: [PATCH] perf: don't leave group_entry on sibling list + (use-after-free) + +When perf_group_detach is called on a group leader, +it should empty its sibling list. Otherwise, when +a sibling is later deallocated, list_del_event() +removes the sibling's group_entry from its current +list, which can be the now-deallocated group leader's +sibling list (use-after-free bug). + +Bug: 32402548 +Change-Id: I99f6bc97c8518df1cb0035814368012ba72ab1f1 +Signed-off-by: John Dias +--- + kernel/events/core.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 01eab13ec0e7e..b7e1e224f07e9 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -1449,10 +1449,17 @@ static void perf_group_detach(struct perf_event *event) + * If this was a group event with sibling events then + * upgrade the siblings to singleton events by adding them + * to whatever list we are on. ++ * If this isn't on a list, make sure we still remove the sibling's ++ * group_entry from this sibling_list; otherwise, when that sibling ++ * is later deallocated, it will try to remove itself from this ++ * sibling_list, which may well have been deallocated already, ++ * resulting in a use-after-free. + */ + list_for_each_entry_safe(sibling, tmp, &event->sibling_list, group_entry) { + if (list) + list_move_tail(&sibling->group_entry, list); ++ else ++ list_del_init(&sibling->group_entry); + sibling->group_leader = sibling; + + /* Inherit group flags from the previous leader */ diff --git a/Patches/Linux_CVEs/CVE-2017-0404/0.patch b/Patches/Linux_CVEs/CVE-2017-0404/0.patch new file mode 100644 index 00000000..3b802d6e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0404/0.patch @@ -0,0 +1,41 @@ +From 4faa6d2e9b53546823882d8889820ff9ce3c372f Mon Sep 17 00:00:00 2001 +From: Siqi Lin +Date: Wed, 2 Nov 2016 16:51:08 -0700 +Subject: [PATCH] ALSA: info: Check for integer overflow in + snd_info_entry_write() + +snd_info_entry_write() resizes the buffer with an unsigned long +size argument that gets truncated because resize_info_buffer() +takes the size parameter as an unsigned int. On 64-bit kernels, +this causes the following copy_to_user() to write out-of-bounds +if (pos + count) can't be represented by an unsigned int. + +Bug: 32510733 +Change-Id: I9e8b55f93f2bd606b4a73b5a4525b71ee88c7c23 +Signed-off-by: Siqi Lin +--- + sound/core/info.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sound/core/info.c b/sound/core/info.c +index 418b4ec43cadb..a4af0ba92d30f 100644 +--- a/sound/core/info.c ++++ b/sound/core/info.c +@@ -253,6 +253,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer + struct snd_info_buffer *buf; + ssize_t size = 0; + loff_t pos; ++ unsigned long realloc_size; + + data = file->private_data; + if (snd_BUG_ON(!data)) +@@ -261,7 +262,8 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer + pos = *offset; + if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) + return -EIO; +- if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) ++ realloc_size = (unsigned long) pos + (unsigned long) count; ++ if (realloc_size < (unsigned long) pos || realloc_size > UINT_MAX) + return -EIO; + switch (entry->content) { + case SNDRV_INFO_CONTENT_TEXT: diff --git a/Patches/Linux_CVEs/CVE-2017-0427/0.patch b/Patches/Linux_CVEs/CVE-2017-0427/0.patch new file mode 100644 index 00000000..f54f373a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0427/0.patch @@ -0,0 +1,76 @@ +From 1d6d364ee174676a225a77dc7ca8dac887199718 Mon Sep 17 00:00:00 2001 +From: Adrian Salido +Date: Thu, 1 Dec 2016 18:07:42 -0800 +Subject: [PATCH] fs/proc/array.c: make safe access to group_leader + +As mentioned in commit 52ee2dfdd4f51cf422ea6a96a0846dc94244aa37 +("pids: refactor vnr/nr_ns helpers to make them safe"). *_nr_ns +helpers used to be buggy. The commit addresses most of the helpers but +is missing task_tgid_xxx() + +Without this protection there is a possible use after free reported by +kasan instrumented kernel: + +================================================================== +BUG: KASAN: use-after-free in task_tgid_nr_ns+0x2c/0x44 at addr *** +Read of size 8 by task cat/2472 +CPU: 1 PID: 2472 Comm: cat Tainted: **** +Hardware name: Google Tegra210 Smaug Rev 1,3+ (DT) +Call trace: +[] dump_backtrace+0x0/0x17c +[] show_stack+0x18/0x24 +[] dump_stack+0x94/0x100 +[] kasan_report+0x308/0x554 +[] __asan_load8+0x20/0x7c +[] task_tgid_nr_ns+0x28/0x44 +[] proc_pid_status+0x444/0x1080 +[] proc_single_show+0x8c/0xdc +[] seq_read+0x2e8/0x6f0 +[] vfs_read+0xd8/0x1e0 +[] SyS_read+0x68/0xd4 + +Accessing group_leader while holding rcu_lock and using the now safe +helpers introduced in the commit mentioned, this race condition is +addressed. + +Signed-off-by: Adrian Salido +Change-Id: I4315217922dda375a30a3581c0c1740dda7b531b +Bug: 31495866 +--- + fs/proc/array.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 864f2e52cf1bc..6307f8774a11d 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -159,16 +159,16 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, + int g; + struct fdtable *fdt = NULL; + const struct cred *cred; +- pid_t ppid, tpid; ++ pid_t ppid = 0, tpid = 0; ++ struct task_struct *leader = NULL; + + rcu_read_lock(); +- ppid = pid_alive(p) ? +- task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; +- tpid = 0; + if (pid_alive(p)) { + struct task_struct *tracer = ptrace_parent(p); + if (tracer) + tpid = task_pid_nr_ns(tracer, ns); ++ ppid = task_tgid_nr_ns(rcu_dereference(p->real_parent), ns); ++ leader = p->group_leader; + } + cred = get_task_cred(p); + seq_printf(m, +@@ -181,7 +181,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, + "Gid:\t%d\t%d\t%d\t%d\n" + "Ngid:\t%d\n", + get_task_state(p), +- task_tgid_nr_ns(p, ns), ++ leader ? task_pid_nr_ns(leader, ns) : 0, + pid_nr_ns(pid, ns), + ppid, tpid, + from_kuid_munged(user_ns, cred->uid), diff --git a/Patches/Linux_CVEs/CVE-2017-0427/1.patch b/Patches/Linux_CVEs/CVE-2017-0427/1.patch new file mode 100644 index 00000000..8e686e81 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0427/1.patch @@ -0,0 +1,76 @@ +From 5db4167c9924c68ab9554bba3a98ecfd14b91a8e Mon Sep 17 00:00:00 2001 +From: Adrian Salido +Date: Thu, 1 Dec 2016 18:07:42 -0800 +Subject: [PATCH] fs/proc/array.c: make safe access to group_leader + +As mentioned in commit 52ee2dfdd4f51cf422ea6a96a0846dc94244aa37 +("pids: refactor vnr/nr_ns helpers to make them safe"). *_nr_ns +helpers used to be buggy. The commit addresses most of the helpers but +is missing task_tgid_xxx() + +Without this protection there is a possible use after free reported by +kasan instrumented kernel: + +================================================================== +BUG: KASAN: use-after-free in task_tgid_nr_ns+0x2c/0x44 at addr *** +Read of size 8 by task cat/2472 +CPU: 1 PID: 2472 Comm: cat Tainted: **** +Hardware name: Google Tegra210 Smaug Rev 1,3+ (DT) +Call trace: +[] dump_backtrace+0x0/0x17c +[] show_stack+0x18/0x24 +[] dump_stack+0x94/0x100 +[] kasan_report+0x308/0x554 +[] __asan_load8+0x20/0x7c +[] task_tgid_nr_ns+0x28/0x44 +[] proc_pid_status+0x444/0x1080 +[] proc_single_show+0x8c/0xdc +[] seq_read+0x2e8/0x6f0 +[] vfs_read+0xd8/0x1e0 +[] SyS_read+0x68/0xd4 + +Accessing group_leader while holding rcu_lock and using the now safe +helpers introduced in the commit mentioned, this race condition is +addressed. + +Signed-off-by: Adrian Salido +Change-Id: I4315217922dda375a30a3581c0c1740dda7b531b +Bug: 31495866 +--- + fs/proc/array.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/fs/proc/array.c b/fs/proc/array.c +index 09f0d9c374a32..6ed95802239df 100644 +--- a/fs/proc/array.c ++++ b/fs/proc/array.c +@@ -168,16 +168,16 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, + int g; + struct fdtable *fdt = NULL; + const struct cred *cred; +- pid_t ppid, tpid; ++ pid_t ppid = 0, tpid = 0; ++ struct task_struct *leader = NULL; + + rcu_read_lock(); +- ppid = pid_alive(p) ? +- task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; +- tpid = 0; + if (pid_alive(p)) { + struct task_struct *tracer = ptrace_parent(p); + if (tracer) + tpid = task_pid_nr_ns(tracer, ns); ++ ppid = task_tgid_nr_ns(rcu_dereference(p->real_parent), ns); ++ leader = p->group_leader; + } + cred = get_task_cred(p); + seq_printf(m, +@@ -189,7 +189,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, + "Uid:\t%d\t%d\t%d\t%d\n" + "Gid:\t%d\t%d\t%d\t%d\n", + get_task_state(p), +- task_tgid_nr_ns(p, ns), ++ leader ? task_pid_nr_ns(leader, ns) : 0, + pid_nr_ns(pid, ns), + ppid, tpid, + from_kuid_munged(user_ns, cred->uid), diff --git a/Patches/Linux_CVEs/CVE-2017-0430/0.patch b/Patches/Linux_CVEs/CVE-2017-0430/0.patch new file mode 100644 index 00000000..0e8a3d80 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0430/0.patch @@ -0,0 +1,30 @@ +From 709105c301aa53fb86c46b36f882998558b19652 Mon Sep 17 00:00:00 2001 +From: Greg Hackmann +Date: Tue, 15 Nov 2016 15:17:24 -0800 +Subject: [PATCH] net: wireless: bcmdhd: fix use-after-free in + _dhd_pno_get_for_batch() + +Bug: 32838767 +Change-Id: I987b07c30b3ed76865a002e7c154a5fa36b1bf29 +Signed-off-by: Greg Hackmann +--- + drivers/net/wireless/bcmdhd/dhd_pno.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index 3e4c6d8191f47..93642ed12bc04 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -3069,9 +3069,10 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) + list_del(&pscan_results->list); + MFREE(dhd->osh, pscan_results, SCAN_RESULTS_SIZE); + _params->params_batch.get_batch.top_node_cnt--; ++ } else { ++ /* increase total scan count using current scan count */ ++ _params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header; + } +- /* increase total scan count using current scan count */ +- _params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header; + + if (buf && bufsize) { + /* This is a first try to get batching results */ diff --git a/Patches/Linux_CVEs/CVE-2017-0433/0.patch b/Patches/Linux_CVEs/CVE-2017-0433/0.patch new file mode 100644 index 00000000..ed4d450e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0433/0.patch @@ -0,0 +1,181 @@ +From fe160e51f02ee5db529c2e84ac8364c89cce005e Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Tue, 6 Dec 2016 20:59:01 -0800 +Subject: [PATCH] input: synaptics_dsx: remove some sysfs nodes. + +Remove most sysfs entrypoints to fw_update module. +Retains check_fw, which is triggered from an +init script. + +BUG: 32769717 +Change-Id: I710cb37a8b5382dce7aa6a1d8748be5853a18a7a +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/Kconfig | 10 ++++++++++ + drivers/input/touchscreen/synaptics_fw_update.c | 20 ++++++++++++++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index a42fea5862af2..64266998c2290 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -1019,6 +1019,16 @@ config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_fw_update. + ++config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS ++ bool "Synaptics DSX firmware update extra sysfs attributes" ++ depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE ++ help ++ Say Y here to enable support for extra sysfs attributes ++ supporting firmware update in a development environment. ++ This does not affect the core or other subsystem attributes. ++ ++ If unsure, say N. ++ + config SECURE_TOUCH + bool "Secure Touch" + depends on (TOUCHSCREEN_ATMEL_MXT || TOUCHSCREEN_SYNAPTICS_I2C_RMI4 || \ +diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c +index 8891f1c836684..360e455a5a51b 100644 +--- a/drivers/input/touchscreen/synaptics_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_fw_update.c +@@ -1331,6 +1331,7 @@ static int fwu_do_write_config(void) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static int fwu_start_write_config(void) + { + int retval; +@@ -1383,6 +1384,7 @@ static int fwu_start_write_config(void) + + return retval; + } ++#endif + + static int fwu_do_write_lockdown(bool reset) + { +@@ -1430,6 +1432,7 @@ static int fwu_do_write_lockdown(bool reset) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static int fwu_start_write_lockdown(void) + { + if (parse_header()) +@@ -1533,6 +1536,7 @@ static int fwu_do_read_config(void) + exit: + return retval; + } ++#endif + + static int fwu_do_reflash(void) + { +@@ -1767,6 +1771,7 @@ int synaptics_fw_updater(void) + } + EXPORT_SYMBOL(synaptics_fw_updater); + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +@@ -2021,6 +2026,7 @@ static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev, + mutex_unlock(&fwu_sysfs_mutex); + return retval; + } ++#endif + + static ssize_t fwu_sysfs_check_fw_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +@@ -2044,6 +2050,7 @@ static ssize_t fwu_sysfs_check_fw_store(struct device *dev, + return count; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) + { +@@ -2265,6 +2272,7 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev, + (pkg_id[1] << 8) | pkg_id[0], + (pkg_id[3] << 8) | pkg_id[2]); + } ++#endif + + static int synaptics_rmi4_debug_dump_info(struct seq_file *m, void *v) + { +@@ -2298,6 +2306,7 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + return; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", +@@ -2307,8 +2316,10 @@ static struct bin_attribute dev_attr_data = { + .read = fwu_sysfs_show_image, + .write = fwu_sysfs_store_image, + }; ++#endif + + static struct device_attribute attrs[] = { ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP, + fwu_sysfs_image_name_show, + fwu_sysfs_image_name_store), +@@ -2318,9 +2329,11 @@ static struct device_attribute attrs[] = { + __ATTR(update_fw, S_IWUSR | S_IWGRP, + NULL, + fwu_sysfs_do_reflash_store), ++#endif + __ATTR(check_fw, S_IWUSR | S_IWGRP, + NULL, + fwu_sysfs_check_fw_store), ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + __ATTR(writeconfig, S_IWUSR | S_IWGRP, + NULL, + fwu_sysfs_write_config_store), +@@ -2360,6 +2373,7 @@ static struct device_attribute attrs[] = { + __ATTR(package_id, S_IRUGO, + fwu_sysfs_package_id_show, + synaptics_rmi4_store_error), ++#endif + }; + + +@@ -2470,6 +2484,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work); + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, + &dev_attr_data); + if (retval < 0) { +@@ -2478,6 +2493,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + __func__); + goto exit_free_mem; + } ++#endif + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj, +@@ -2511,7 +2527,9 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + &attrs[attr_count].attr); + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); ++#endif + + exit_free_mem: + kfree(fwu->fn_ptr); +@@ -2528,7 +2546,9 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) + { + unsigned char attr_count; + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); ++#endif + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, diff --git a/Patches/Linux_CVEs/CVE-2017-0433/1.patch b/Patches/Linux_CVEs/CVE-2017-0433/1.patch new file mode 100644 index 00000000..c2e986ef --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0433/1.patch @@ -0,0 +1,210 @@ +From 2615c5f302441568e6dd20007bc5246d72837e80 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Tue, 6 Dec 2016 19:19:26 -0800 +Subject: [PATCH] input: synaptics_dsx: remove update sysfs entries + +Remove sysfs entrypoints to fw_update module. + +BUG: 32769717 +Change-Id: I425761af84ed5c31cc5902b4f49c4981a49f3af0 +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/synaptics_dsx25/Kconfig | 10 ++++++++ + .../synaptics_dsx25/synaptics_dsx_fw_update.c | 27 ++++++++++++++++++++-- + 2 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx25/Kconfig b/drivers/input/touchscreen/synaptics_dsx25/Kconfig +index 36661fc9d6a2d..218a6c3c96467 100644 +--- a/drivers/input/touchscreen/synaptics_dsx25/Kconfig ++++ b/drivers/input/touchscreen/synaptics_dsx25/Kconfig +@@ -59,6 +59,16 @@ config TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_fw_update. + ++config TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS ++ bool "Synaptics DSX firmware update sysfs attributes" ++ depends on TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE ++ help ++ Say Y here to enable support for sysfs attributes for ++ performing firmware update in a development environment. ++ This does not affect the core or other subsystem attributes. ++ ++ If unsure, say N. ++ + config TOUCHSCREEN_SYNAPTICS_DSX25_ACTIVE_PEN + tristate "Synaptics DSX active pen module" + depends on TOUCHSCREEN_SYNAPTICS25_DSX_CORE +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 323f65891b458..8cad4d3b3a9d9 100755 +--- a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c +@@ -105,6 +105,7 @@ static int fwu_do_reflash(void); + + static int fwu_recovery_check_status(void); + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); +@@ -157,6 +158,7 @@ static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + + static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); ++#endif + + enum f34_version { + F34_V0 = 0, +@@ -595,6 +597,7 @@ struct synaptics_rmi4_fwu_handle { + struct work_struct fwu_work; + }; + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", +@@ -652,12 +655,14 @@ static struct device_attribute attrs[] = { + synaptics_rmi4_show_error, + fwu_sysfs_write_guest_code_store), + }; ++#endif + + static struct synaptics_rmi4_fwu_handle *fwu; + + DECLARE_COMPLETION(dsx_fwu_remove_complete); ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + DEFINE_MUTEX(fwu_sysfs_mutex); +- ++#endif + static bool tp_2k_panel = false; + /** + * early_param: Parse system early startup parameters. +@@ -3057,6 +3062,7 @@ static int fwu_do_reflash(void) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static int fwu_do_read_config(void) + { + int retval; +@@ -3136,6 +3142,7 @@ static int fwu_do_read_config(void) + + return retval; + } ++#endif + + static int fwu_do_lockdown(void) + { +@@ -3173,6 +3180,7 @@ static int fwu_do_lockdown(void) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static int fwu_start_write_guest_code(void) + { + int retval; +@@ -3348,6 +3356,7 @@ static int fwu_start_write_config(void) + + return retval; + } ++#endif + + static void synaptics_refresh_configid(void) + { +@@ -3584,6 +3593,7 @@ static int fwu_recovery_check_status(void) + return 0; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static int fwu_recovery_erase_all(void) + { + int retval; +@@ -3778,6 +3788,7 @@ static int fwu_start_recovery(void) + + return retval; + } ++#endif + + int synaptics_dsx25_fw_updater(const unsigned char *fw_data) + { +@@ -3838,6 +3849,7 @@ static void fwu_startup_fw_update_work(struct work_struct *work) + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +@@ -4236,6 +4248,7 @@ static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + mutex_unlock(&fwu_sysfs_mutex); + return retval; + } ++#endif + + static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +@@ -4252,7 +4265,9 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + { + int retval; ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + unsigned char attr_count; ++#endif + struct pdt_properties pdt_props; + + if (fwu) { +@@ -4319,6 +4334,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + &fwu->fwu_work); + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, + &dev_attr_data); + if (retval < 0) { +@@ -4339,9 +4355,11 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + goto exit_remove_attrs; + } + } ++#endif + + return 0; + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + exit_remove_attrs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, +@@ -4349,8 +4367,9 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +- + exit_destroy_work: ++#endif ++ + #ifdef DO_STARTUP_FW_UPDATE + cancel_work_sync(&fwu->fwu_work); + flush_workqueue(fwu->fwu_workqueue); +@@ -4370,7 +4389,9 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + + static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) + { ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + unsigned char attr_count; ++#endif + + if (!fwu) + goto exit; +@@ -4381,12 +4402,14 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) + destroy_workqueue(fwu->fwu_workqueue); + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); ++#endif + + kfree(fwu->read_config_buf); + kfree(fwu->image_name); diff --git a/Patches/Linux_CVEs/CVE-2017-0434/0.patch b/Patches/Linux_CVEs/CVE-2017-0434/0.patch new file mode 100644 index 00000000..72cf9708 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0434/0.patch @@ -0,0 +1,34 @@ +From d740e7228bd1578ed01762998b2a86e7df56e608 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Fri, 2 Dec 2016 20:49:26 -0800 +Subject: [PATCH] input: synaptics_dsx: reallocate buffer under lock. + +Prevent concurrent usage & re-allocation of the wr_buf variable. +Based off patch by chengengjia . + +BUG: 33001936 +Change-Id: I88d78e1ec0fc9e88b1e6824c06161b67d01136ec +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_i2c.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_i2c.c +index 5312f86a93470..3acd4d54bb6d5 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_i2c.c ++++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_i2c.c +@@ -557,11 +557,11 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[1]; + ++ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); ++ + retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, length + 1); + if (retval < 0) +- return retval; +- +- mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); ++ goto exit; + + retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { diff --git a/Patches/Linux_CVEs/CVE-2017-0435/0.patch b/Patches/Linux_CVEs/CVE-2017-0435/0.patch new file mode 100644 index 00000000..5651b6b3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0435/0.patch @@ -0,0 +1,185 @@ +From ce9db0874906f6aedd80bb28d457eadfe38bdd02 Mon Sep 17 00:00:00 2001 +From: Sudheer Papothi +Date: Wed, 26 Oct 2016 01:07:04 +0530 +Subject: drivers: qcom: ultrasound: Lock async driver calls + +Adds lock to ioctl and other external calls to driver. +Adds missing null check in __usf_set_stream_param. + +Change-Id: I142f31c6bb46d6a394ad012077e1703875a120ad +Signed-off-by: Sudheer Papothi +--- + drivers/misc/qcom/qdsp6v2/ultrasound/usf.c | 66 ++++++++++++++++++++++++++---- + 1 file changed, 59 insertions(+), 7 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c +index d535ccb..9270dbc 100644 +--- a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c ++++ b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include "q6usm.h" +@@ -128,6 +129,8 @@ struct usf_type { + uint16_t conflicting_event_filters; + /* The requested buttons bitmap */ + uint16_t req_buttons_bitmap; ++ /* Mutex for exclusive operations (all public APIs) */ ++ struct mutex mutex; + }; + + struct usf_input_dev_type { +@@ -1376,9 +1379,22 @@ static int __usf_set_stream_param(struct usf_xx_type *usf_xx, + int dir) + { + struct us_client *usc = usf_xx->usc; +- struct us_port_data *port = &usc->port[dir]; ++ struct us_port_data *port; + int rc = 0; + ++ if (usc == NULL) { ++ pr_err("%s: usc is null\n", ++ __func__); ++ return -EFAULT; ++ } ++ ++ port = &usc->port[dir]; ++ if (port == NULL) { ++ pr_err("%s: port is null\n", ++ __func__); ++ return -EFAULT; ++ } ++ + if (port->param_buf == NULL) { + pr_err("%s: parameter buffer is null\n", + __func__); +@@ -1503,10 +1519,12 @@ static int usf_get_stream_param(struct usf_xx_type *usf_xx, + return __usf_get_stream_param(usf_xx, &get_stream_param, dir); + } /* usf_get_stream_param */ + +-static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++static long __usf_ioctl(struct usf_type *usf, ++ unsigned int cmd, ++ unsigned long arg) + { ++ + int rc = 0; +- struct usf_type *usf = file->private_data; + struct usf_xx_type *usf_xx = NULL; + + switch (cmd) { +@@ -1669,6 +1687,18 @@ static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + release_xx(usf_xx); + + return rc; ++} /* __usf_ioctl */ ++ ++static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ struct usf_type *usf = file->private_data; ++ int rc = 0; ++ ++ mutex_lock(&usf->mutex); ++ rc = __usf_ioctl(usf, cmd, arg); ++ mutex_unlock(&usf->mutex); ++ ++ return rc; + } /* usf_ioctl */ + + #ifdef CONFIG_COMPAT +@@ -2106,12 +2136,11 @@ static int usf_get_stream_param32(struct usf_xx_type *usf_xx, + return __usf_get_stream_param(usf_xx, &get_stream_param, dir); + } /* usf_get_stream_param32 */ + +-static long usf_compat_ioctl(struct file *file, ++static long __usf_compat_ioctl(struct usf_type *usf, + unsigned int cmd, + unsigned long arg) + { + int rc = 0; +- struct usf_type *usf = file->private_data; + struct usf_xx_type *usf_xx = NULL; + + switch (cmd) { +@@ -2119,7 +2148,7 @@ static long usf_compat_ioctl(struct file *file, + case US_START_RX: + case US_STOP_TX: + case US_STOP_RX: { +- return usf_ioctl(file, cmd, arg); ++ return __usf_ioctl(usf, cmd, arg); + } + + case US_SET_TX_INFO32: { +@@ -2228,6 +2257,20 @@ static long usf_compat_ioctl(struct file *file, + release_xx(usf_xx); + + return rc; ++} /* __usf_compat_ioctl */ ++ ++static long usf_compat_ioctl(struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ struct usf_type *usf = file->private_data; ++ int rc = 0; ++ ++ mutex_lock(&usf->mutex); ++ rc = __usf_compat_ioctl(usf, cmd, arg); ++ mutex_unlock(&usf->mutex); ++ ++ return rc; + } /* usf_compat_ioctl */ + #endif /* CONFIG_COMPAT */ + +@@ -2236,13 +2279,17 @@ static int usf_mmap(struct file *file, struct vm_area_struct *vms) + struct usf_type *usf = file->private_data; + int dir = OUT; + struct usf_xx_type *usf_xx = &usf->usf_tx; ++ int rc = 0; + ++ mutex_lock(&usf->mutex); + if (vms->vm_flags & USF_VM_WRITE) { /* RX buf mapping */ + dir = IN; + usf_xx = &usf->usf_rx; + } ++ rc = q6usm_get_virtual_address(dir, usf_xx->usc, vms); ++ mutex_unlock(&usf->mutex); + +- return q6usm_get_virtual_address(dir, usf_xx->usc, vms); ++ return rc; + } + + static uint16_t add_opened_dev(int minor) +@@ -2294,6 +2341,8 @@ static int usf_open(struct inode *inode, struct file *file) + usf->usf_tx.us_detect_type = USF_US_DETECT_UNDEF; + usf->usf_rx.us_detect_type = USF_US_DETECT_UNDEF; + ++ mutex_init(&usf->mutex); ++ + pr_debug("%s:usf in open\n", __func__); + return 0; + } +@@ -2304,6 +2353,7 @@ static int usf_release(struct inode *inode, struct file *file) + + pr_debug("%s: release entry\n", __func__); + ++ mutex_lock(&usf->mutex); + usf_release_input(usf); + + usf_disable(&usf->usf_tx); +@@ -2311,6 +2361,8 @@ static int usf_release(struct inode *inode, struct file *file) + + s_opened_devs[usf->dev_ind] = 0; + ++ mutex_unlock(&usf->mutex); ++ mutex_destroy(&usf->mutex); + kfree(usf); + pr_debug("%s: release exit\n", __func__); + return 0; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0435/1.patch b/Patches/Linux_CVEs/CVE-2017-0435/1.patch new file mode 100644 index 00000000..ab99a331 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0435/1.patch @@ -0,0 +1,26 @@ +From 831da5d113d214db6894e9fd0ce98762ee8a544a Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Tue, 6 Dec 2016 09:57:57 -0800 +Subject: [PATCH] Kconfig: msm: disable ultrasound driver + +Bug: 31906415 +Bug: 31906657 +Bug: 32553868 +Change-Id: Iab736a5d5622098c89c76dbe6b0b395652bbae57 +Signed-off-by: Nick Desaulniers +--- + sound/soc/msm/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig +index 6eb168e4d10d5..2e6f642241ef3 100644 +--- a/sound/soc/msm/Kconfig ++++ b/sound/soc/msm/Kconfig +@@ -267,7 +267,6 @@ config SND_SOC_MSM8994 + select SND_SOC_MSM_HDMI_CODEC_RX + select QTI_PP + select SND_SOC_CPE +- select MSM_ULTRASOUND + select SND_HWDEP + help + To add support for SoC audio on MSM8994. diff --git a/Patches/Linux_CVEs/CVE-2017-0436/0.patch b/Patches/Linux_CVEs/CVE-2017-0436/0.patch new file mode 100644 index 00000000..5651b6b3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0436/0.patch @@ -0,0 +1,185 @@ +From ce9db0874906f6aedd80bb28d457eadfe38bdd02 Mon Sep 17 00:00:00 2001 +From: Sudheer Papothi +Date: Wed, 26 Oct 2016 01:07:04 +0530 +Subject: drivers: qcom: ultrasound: Lock async driver calls + +Adds lock to ioctl and other external calls to driver. +Adds missing null check in __usf_set_stream_param. + +Change-Id: I142f31c6bb46d6a394ad012077e1703875a120ad +Signed-off-by: Sudheer Papothi +--- + drivers/misc/qcom/qdsp6v2/ultrasound/usf.c | 66 ++++++++++++++++++++++++++---- + 1 file changed, 59 insertions(+), 7 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c +index d535ccb..9270dbc 100644 +--- a/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c ++++ b/drivers/misc/qcom/qdsp6v2/ultrasound/usf.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include "q6usm.h" +@@ -128,6 +129,8 @@ struct usf_type { + uint16_t conflicting_event_filters; + /* The requested buttons bitmap */ + uint16_t req_buttons_bitmap; ++ /* Mutex for exclusive operations (all public APIs) */ ++ struct mutex mutex; + }; + + struct usf_input_dev_type { +@@ -1376,9 +1379,22 @@ static int __usf_set_stream_param(struct usf_xx_type *usf_xx, + int dir) + { + struct us_client *usc = usf_xx->usc; +- struct us_port_data *port = &usc->port[dir]; ++ struct us_port_data *port; + int rc = 0; + ++ if (usc == NULL) { ++ pr_err("%s: usc is null\n", ++ __func__); ++ return -EFAULT; ++ } ++ ++ port = &usc->port[dir]; ++ if (port == NULL) { ++ pr_err("%s: port is null\n", ++ __func__); ++ return -EFAULT; ++ } ++ + if (port->param_buf == NULL) { + pr_err("%s: parameter buffer is null\n", + __func__); +@@ -1503,10 +1519,12 @@ static int usf_get_stream_param(struct usf_xx_type *usf_xx, + return __usf_get_stream_param(usf_xx, &get_stream_param, dir); + } /* usf_get_stream_param */ + +-static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++static long __usf_ioctl(struct usf_type *usf, ++ unsigned int cmd, ++ unsigned long arg) + { ++ + int rc = 0; +- struct usf_type *usf = file->private_data; + struct usf_xx_type *usf_xx = NULL; + + switch (cmd) { +@@ -1669,6 +1687,18 @@ static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + release_xx(usf_xx); + + return rc; ++} /* __usf_ioctl */ ++ ++static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ struct usf_type *usf = file->private_data; ++ int rc = 0; ++ ++ mutex_lock(&usf->mutex); ++ rc = __usf_ioctl(usf, cmd, arg); ++ mutex_unlock(&usf->mutex); ++ ++ return rc; + } /* usf_ioctl */ + + #ifdef CONFIG_COMPAT +@@ -2106,12 +2136,11 @@ static int usf_get_stream_param32(struct usf_xx_type *usf_xx, + return __usf_get_stream_param(usf_xx, &get_stream_param, dir); + } /* usf_get_stream_param32 */ + +-static long usf_compat_ioctl(struct file *file, ++static long __usf_compat_ioctl(struct usf_type *usf, + unsigned int cmd, + unsigned long arg) + { + int rc = 0; +- struct usf_type *usf = file->private_data; + struct usf_xx_type *usf_xx = NULL; + + switch (cmd) { +@@ -2119,7 +2148,7 @@ static long usf_compat_ioctl(struct file *file, + case US_START_RX: + case US_STOP_TX: + case US_STOP_RX: { +- return usf_ioctl(file, cmd, arg); ++ return __usf_ioctl(usf, cmd, arg); + } + + case US_SET_TX_INFO32: { +@@ -2228,6 +2257,20 @@ static long usf_compat_ioctl(struct file *file, + release_xx(usf_xx); + + return rc; ++} /* __usf_compat_ioctl */ ++ ++static long usf_compat_ioctl(struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ struct usf_type *usf = file->private_data; ++ int rc = 0; ++ ++ mutex_lock(&usf->mutex); ++ rc = __usf_compat_ioctl(usf, cmd, arg); ++ mutex_unlock(&usf->mutex); ++ ++ return rc; + } /* usf_compat_ioctl */ + #endif /* CONFIG_COMPAT */ + +@@ -2236,13 +2279,17 @@ static int usf_mmap(struct file *file, struct vm_area_struct *vms) + struct usf_type *usf = file->private_data; + int dir = OUT; + struct usf_xx_type *usf_xx = &usf->usf_tx; ++ int rc = 0; + ++ mutex_lock(&usf->mutex); + if (vms->vm_flags & USF_VM_WRITE) { /* RX buf mapping */ + dir = IN; + usf_xx = &usf->usf_rx; + } ++ rc = q6usm_get_virtual_address(dir, usf_xx->usc, vms); ++ mutex_unlock(&usf->mutex); + +- return q6usm_get_virtual_address(dir, usf_xx->usc, vms); ++ return rc; + } + + static uint16_t add_opened_dev(int minor) +@@ -2294,6 +2341,8 @@ static int usf_open(struct inode *inode, struct file *file) + usf->usf_tx.us_detect_type = USF_US_DETECT_UNDEF; + usf->usf_rx.us_detect_type = USF_US_DETECT_UNDEF; + ++ mutex_init(&usf->mutex); ++ + pr_debug("%s:usf in open\n", __func__); + return 0; + } +@@ -2304,6 +2353,7 @@ static int usf_release(struct inode *inode, struct file *file) + + pr_debug("%s: release entry\n", __func__); + ++ mutex_lock(&usf->mutex); + usf_release_input(usf); + + usf_disable(&usf->usf_tx); +@@ -2311,6 +2361,8 @@ static int usf_release(struct inode *inode, struct file *file) + + s_opened_devs[usf->dev_ind] = 0; + ++ mutex_unlock(&usf->mutex); ++ mutex_destroy(&usf->mutex); + kfree(usf); + pr_debug("%s: release exit\n", __func__); + return 0; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0437/0.patch b/Patches/Linux_CVEs/CVE-2017-0437/0.patch new file mode 100644 index 00000000..3e7bc3db --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0437/0.patch @@ -0,0 +1,128 @@ +From 1f0b036dc74ccb6e9f0a03a540efdb0876f5ca77 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Mon, 28 Nov 2016 09:19:02 -0800 +Subject: qcacld-2.0: Avoid overflow of roam subcmd params + +Currently when processing the QCA_NL80211_VENDOR_SUBCMD_ROAM vendor +command, for the following roam commands there are input validation +issues: + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID + +Both of these commands have a "number of BSSIDs" attribute as well as a +list of BSSIDs. However there is no validation that the number of +BSSIDs provided won't overflow the destination buffer. In addition +there is no validation that the number of BSSIDs actually provided +matches the number of BSSIDs expected. + +To address these issues, for the above mentioned commands: +* Verify that the expected number of BSSIDs doesn't exceed the maximum + allowed number of BSSIDs +* Verify that the actual number of BSSIDs supplied doesn't exceed the + expected number of BSSIDs +* Only process the actual number of supplied BSSIDs if it is less than + the expected number of BSSIDs. + +Change-Id: Ifa6121ee1b1441ec415198897ef815b40cb5aff6 +CRs-Fixed: 1092497 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 43 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index b3c265c..800d123 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1870,6 +1870,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; ++ uint32_t count; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { +@@ -2045,15 +2046,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } +- roam_params.num_bssid_favored = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); ++ if (count > MAX_BSSID_FAVORED) { ++ hddLog(LOGE, FL("Preferred BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_FAVORED); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of Preferred BSSID (%d)"), +- roam_params.num_bssid_favored); ++ FL("Num of Preferred BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Preferred BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2083,6 +2094,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_favored_factor[i]); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Preferred BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_favored = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; +@@ -2092,15 +2108,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } +- roam_params.num_bssid_avoid_list = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); ++ if (count > MAX_BSSID_AVOID_LIST) { ++ hddLog(LOGE, FL("Blacklist BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_AVOID_LIST); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of blacklist BSSID (%d)"), +- roam_params.num_bssid_avoid_list); ++ FL("Num of blacklist BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Blacklist BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2121,6 +2147,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_avoid_list[i])); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Blacklist BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_avoid_list = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0437/1.patch b/Patches/Linux_CVEs/CVE-2017-0437/1.patch new file mode 100644 index 00000000..acb3c306 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0437/1.patch @@ -0,0 +1,127 @@ +From 138c690bd39a3f1ba14450e308ebc56bbda1f5b2 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Mon, 28 Nov 2016 20:47:30 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of roam subcmd params + +Currently when processing the QCA_NL80211_VENDOR_SUBCMD_ROAM vendor +command, for the following roam commands there are input validation +issues: + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID + +Both of these commands have a "number of BSSIDs" attribute as well as a +list of BSSIDs. However there is no validation that the number of +BSSIDs provided won't overflow the destination buffer. In addition +there is no validation that the number of BSSIDs actually provided +matches the number of BSSIDs expected. + +To address these issues, for the above mentioned commands: +* Verify that the expected number of BSSIDs doesn't exceed the maximum + allowed number of BSSIDs +* Verify that the actual number of BSSIDs supplied doesn't exceed the + expected number of BSSIDs +* Only process the actual number of supplied BSSIDs if it is less than + the expected number of BSSIDs. + +Change-Id: Ifa6121ee1b1441ec415198897ef815b40cb5aff6 +CRs-Fixed: 1092497 +Bug: 32402310 32402604 32871330 +Signed-off-by: Srinivas Girigowda +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 43 +++++++++++++++++++--- + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 89dba5d54b627..fd23a304b93bd 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1799,6 +1799,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; ++ uint32_t count; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { +@@ -1974,15 +1975,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } +- roam_params.num_bssid_favored = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); ++ if (count > MAX_BSSID_FAVORED) { ++ hddLog(LOGE, FL("Preferred BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_FAVORED); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of Preferred BSSID (%d)"), +- roam_params.num_bssid_favored); ++ FL("Num of Preferred BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Preferred BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2012,6 +2023,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_favored_factor[i]); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Preferred BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_favored = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; +@@ -2021,15 +2037,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } +- roam_params.num_bssid_avoid_list = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); ++ if (count > MAX_BSSID_AVOID_LIST) { ++ hddLog(LOGE, FL("Blacklist BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_AVOID_LIST); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of blacklist BSSID (%d)"), +- roam_params.num_bssid_avoid_list); ++ FL("Num of blacklist BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Blacklist BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2050,6 +2076,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_avoid_list[i])); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Blacklist BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_avoid_list = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; diff --git a/Patches/Linux_CVEs/CVE-2017-0438/0.patch b/Patches/Linux_CVEs/CVE-2017-0438/0.patch new file mode 100644 index 00000000..3e7bc3db --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0438/0.patch @@ -0,0 +1,128 @@ +From 1f0b036dc74ccb6e9f0a03a540efdb0876f5ca77 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Mon, 28 Nov 2016 09:19:02 -0800 +Subject: qcacld-2.0: Avoid overflow of roam subcmd params + +Currently when processing the QCA_NL80211_VENDOR_SUBCMD_ROAM vendor +command, for the following roam commands there are input validation +issues: + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID + +Both of these commands have a "number of BSSIDs" attribute as well as a +list of BSSIDs. However there is no validation that the number of +BSSIDs provided won't overflow the destination buffer. In addition +there is no validation that the number of BSSIDs actually provided +matches the number of BSSIDs expected. + +To address these issues, for the above mentioned commands: +* Verify that the expected number of BSSIDs doesn't exceed the maximum + allowed number of BSSIDs +* Verify that the actual number of BSSIDs supplied doesn't exceed the + expected number of BSSIDs +* Only process the actual number of supplied BSSIDs if it is less than + the expected number of BSSIDs. + +Change-Id: Ifa6121ee1b1441ec415198897ef815b40cb5aff6 +CRs-Fixed: 1092497 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 43 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index b3c265c..800d123 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1870,6 +1870,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; ++ uint32_t count; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { +@@ -2045,15 +2046,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } +- roam_params.num_bssid_favored = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); ++ if (count > MAX_BSSID_FAVORED) { ++ hddLog(LOGE, FL("Preferred BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_FAVORED); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of Preferred BSSID (%d)"), +- roam_params.num_bssid_favored); ++ FL("Num of Preferred BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Preferred BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2083,6 +2094,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_favored_factor[i]); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Preferred BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_favored = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; +@@ -2092,15 +2108,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } +- roam_params.num_bssid_avoid_list = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); ++ if (count > MAX_BSSID_AVOID_LIST) { ++ hddLog(LOGE, FL("Blacklist BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_AVOID_LIST); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of blacklist BSSID (%d)"), +- roam_params.num_bssid_avoid_list); ++ FL("Num of blacklist BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Blacklist BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2121,6 +2147,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_avoid_list[i])); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Blacklist BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_avoid_list = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0438/1.patch b/Patches/Linux_CVEs/CVE-2017-0438/1.patch new file mode 100644 index 00000000..acb3c306 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0438/1.patch @@ -0,0 +1,127 @@ +From 138c690bd39a3f1ba14450e308ebc56bbda1f5b2 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Mon, 28 Nov 2016 20:47:30 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of roam subcmd params + +Currently when processing the QCA_NL80211_VENDOR_SUBCMD_ROAM vendor +command, for the following roam commands there are input validation +issues: + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID + +Both of these commands have a "number of BSSIDs" attribute as well as a +list of BSSIDs. However there is no validation that the number of +BSSIDs provided won't overflow the destination buffer. In addition +there is no validation that the number of BSSIDs actually provided +matches the number of BSSIDs expected. + +To address these issues, for the above mentioned commands: +* Verify that the expected number of BSSIDs doesn't exceed the maximum + allowed number of BSSIDs +* Verify that the actual number of BSSIDs supplied doesn't exceed the + expected number of BSSIDs +* Only process the actual number of supplied BSSIDs if it is less than + the expected number of BSSIDs. + +Change-Id: Ifa6121ee1b1441ec415198897ef815b40cb5aff6 +CRs-Fixed: 1092497 +Bug: 32402310 32402604 32871330 +Signed-off-by: Srinivas Girigowda +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 43 +++++++++++++++++++--- + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 89dba5d54b627..fd23a304b93bd 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1799,6 +1799,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; ++ uint32_t count; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { +@@ -1974,15 +1975,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } +- roam_params.num_bssid_favored = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); ++ if (count > MAX_BSSID_FAVORED) { ++ hddLog(LOGE, FL("Preferred BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_FAVORED); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of Preferred BSSID (%d)"), +- roam_params.num_bssid_favored); ++ FL("Num of Preferred BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Preferred BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2012,6 +2023,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_favored_factor[i]); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Preferred BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_favored = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; +@@ -2021,15 +2037,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } +- roam_params.num_bssid_avoid_list = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); ++ if (count > MAX_BSSID_AVOID_LIST) { ++ hddLog(LOGE, FL("Blacklist BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_AVOID_LIST); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of blacklist BSSID (%d)"), +- roam_params.num_bssid_avoid_list); ++ FL("Num of blacklist BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Blacklist BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2050,6 +2076,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_avoid_list[i])); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Blacklist BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_avoid_list = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; diff --git a/Patches/Linux_CVEs/CVE-2017-0439/0.patch b/Patches/Linux_CVEs/CVE-2017-0439/0.patch new file mode 100644 index 00000000..14c1d49c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0439/0.patch @@ -0,0 +1,57 @@ +From 81b6b5538d3227ed4b925fcceedb109abb2a4c61 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Fri, 18 Nov 2016 11:35:01 -0800 +Subject: qcacld-2.0: Avoid overflow of passpoint network list + +Currently when processing a passpoint vendor command the "num +networks" attribute is limit checked and if it exceeds a MAX value +then the command is rejected. Otherwise this value is used to +calculate the size of the buffer allocated to hold the internal +representation of the request. However later when the network +attributes are parsed there is no check to make sure the number of +networks processed does not exceed the "num networks" used to allocate +memory, and as a result a buffer overflow can occur. Address this +issue by aborting the network parsing once "num networks" records have +been parsed. + +Change-Id: I38d9f19b08b42fa9a850eb70a42920fbc3b99cf6 +CRs-Fixed: 1092059 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index a2ff8fe..54c5e54 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -5127,11 +5127,19 @@ static int hdd_extscan_passpoint_fill_network_list( + struct nlattr *networks; + int rem1, len; + uint8_t index; ++ uint32_t expected_networks; + ++ expected_networks = req_msg->num_networks; + index = 0; + nla_for_each_nested(networks, + tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY], + rem1) { ++ ++ if (index == expected_networks) { ++ hddLog(LOGW, FL("ignoring excess networks")); ++ break; ++ } ++ + if (nla_parse(network, + QCA_WLAN_VENDOR_ATTR_PNO_MAX, + nla_data(networks), nla_len(networks), NULL)) { +@@ -5193,6 +5201,7 @@ static int hdd_extscan_passpoint_fill_network_list( + + index++; + } ++ req_msg->num_networks = index; + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0439/1.patch b/Patches/Linux_CVEs/CVE-2017-0439/1.patch new file mode 100644 index 00000000..e577a3e3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0439/1.patch @@ -0,0 +1,56 @@ +From 5b3f9bb678b1f5a57f7664965ee6e082553c1e40 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Mon, 21 Nov 2016 19:10:09 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of passpoint network list + +Currently when processing a passpoint vendor command the "num +networks" attribute is limit checked and if it exceeds a MAX value +then the command is rejected. Otherwise this value is used to +calculate the size of the buffer allocated to hold the internal +representation of the request. However later when the network +attributes are parsed there is no check to make sure the number of +networks processed does not exceed the "num networks" used to allocate +memory, and as a result a buffer overflow can occur. Address this +issue by aborting the network parsing once "num networks" records have +been parsed. + +Change-Id: I38d9f19b08b42fa9a850eb70a42920fbc3b99cf6 +CRs-Fixed: 1092059 +Bug: 32450647 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 82275c27ae587..89dba5d54b627 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -4992,11 +4992,19 @@ static int hdd_extscan_passpoint_fill_network_list( + struct nlattr *networks; + int rem1, len; + uint8_t index; ++ uint32_t expected_networks; + ++ expected_networks = req_msg->num_networks; + index = 0; + nla_for_each_nested(networks, + tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY], + rem1) { ++ ++ if (index == expected_networks) { ++ hddLog(LOGW, FL("ignoring excess networks")); ++ break; ++ } ++ + if (nla_parse(network, + QCA_WLAN_VENDOR_ATTR_PNO_MAX, + nla_data(networks), nla_len(networks), NULL)) { +@@ -5058,6 +5066,7 @@ static int hdd_extscan_passpoint_fill_network_list( + + index++; + } ++ req_msg->num_networks = index; + return 0; + } + diff --git a/Patches/Linux_CVEs/CVE-2017-0440/0.patch b/Patches/Linux_CVEs/CVE-2017-0440/0.patch new file mode 100644 index 00000000..d78b4149 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0440/0.patch @@ -0,0 +1,88 @@ +From 10f0051f7b3b9a7635b0762a8cf102f595f7a268 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Wed, 30 Nov 2016 12:27:44 -0800 +Subject: qcacld-2.0: Avoid overflow of "set_bssid_hotlist" params + +The wlan driver supports the following vendor command: + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST + +This command supplies a "number of APs" attribute as well as a list of +per-AP attributes. However there is no validation that the number of +APs provided won't overflow the destination buffer. In addition there +is no validation that the number of APs actually provided matches the +number of APs expected. + +To address these issues: +* Verify that the expected number of APs doesn't exceed the maximum + allowed number of APs +* Verify that the actual number of APs supplied doesn't exceed the + expected number of APs +* Only process the actual number of supplied APs if it is less than + the expected number of APs. + +Change-Id: I41e36d11bc3e71928866a27afc2fbf046b59f0f5 +CRs-Fixed: 1095770 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 16 ++++++++++++++++ + CORE/SERVICES/WMA/wma.c | 4 ++-- + 2 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index d91859f..1991204 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -2893,6 +2893,11 @@ static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + } + pReqMsg->numAp = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]); ++ if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_HOTLIST_APS) { ++ hddLog(LOGE, FL("Number of AP: %u exceeds max: %u"), ++ pReqMsg->numAp, WLAN_EXTSCAN_MAX_HOTLIST_APS); ++ goto fail; ++ } + hddLog(LOG1, FL("Number of AP %d"), pReqMsg->numAp); + + /* Parse and fetch lost ap sample size */ +@@ -2911,6 +2916,11 @@ static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + i = 0; + nla_for_each_nested(apTh, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) { ++ if (i == pReqMsg->numAp) { ++ hddLog(LOGW, FL("Ignoring excess AP")); ++ break; ++ } ++ + if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(apTh), nla_len(apTh), + wlan_hdd_extscan_config_policy)) { +@@ -2949,6 +2959,12 @@ static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + i++; + } + ++ if (i < pReqMsg->numAp) { ++ hddLog(LOGW, FL("Number of AP %u less than expected %u"), ++ i, pReqMsg->numAp); ++ pReqMsg->numAp = i; ++ } ++ + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); +diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c +index 2cf66bf..8ab1d2d 100644 +--- a/CORE/SERVICES/WMA/wma.c ++++ b/CORE/SERVICES/WMA/wma.c +@@ -28633,8 +28633,8 @@ VOS_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle, + /* setbssid hotlist expects the bssid list + * to be non zero value + */ +- if (!numap) { +- WMA_LOGE("%s: Invalid number of bssid's", __func__); ++ if ((numap <= 0) || (numap > WLAN_EXTSCAN_MAX_HOTLIST_APS)) { ++ WMA_LOGE("%s: Invalid number of APs: %d", __func__, numap); + return VOS_STATUS_E_INVAL; + } + num_entries = wma_get_hotlist_entries_per_page(wma_handle->wmi_handle, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0440/1.patch b/Patches/Linux_CVEs/CVE-2017-0440/1.patch new file mode 100644 index 00000000..5c58be37 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0440/1.patch @@ -0,0 +1,71 @@ +From 054ce0761e900c5f63089393f8b6cadf17d55ade Mon Sep 17 00:00:00 2001 +From: Hanumanth Reddy Pothula +Date: Fri, 27 Jan 2017 16:43:45 +0530 +Subject: prima: Avoid overflow of "set_bssid_hotlist" params + +qcacld2.0 to prima propgation + +The wlan driver supports the following vendor command: + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST + +This command supplies a "number of APs" attribute as well as a list of +per-AP attributes. However there is no validation that the number of +APs provided won't overflow the destination buffer. In addition there +is no validation that the number of APs actually provided matches the +number of APs expected. + +To address these issues: +* Verify that the expected number of APs doesn't exceed the maximum + allowed number of APs +* Verify that the actual number of APs supplied doesn't exceed the + expected number of APs +* Only process the actual number of supplied APs if it is less than + the expected number of APs. + +Change-Id: I41e36d11bc3e71928866a27afc2fbf046b59f0f5 +CRs-Fixed: 1095770 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 8aa38d1..f130174 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -3764,10 +3764,20 @@ static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + + pReqMsg->numBssid = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]); ++ if (pReqMsg->numBssid > WLAN_EXTSCAN_MAX_HOTLIST_APS) { ++ hddLog(LOGE, FL("Number of AP: %u exceeds max: %u"), ++ pReqMsg->numBssid, WLAN_EXTSCAN_MAX_HOTLIST_APS); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_INFO, FL("Number of AP (%d)"), pReqMsg->numBssid); + + nla_for_each_nested(apTh, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) { ++ if (i == pReqMsg->numBssid) { ++ hddLog(LOGW, FL("Ignoring excess AP")); ++ break; ++ } ++ + if(nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(apTh), nla_len(apTh), + NULL)) { +@@ -3806,6 +3816,12 @@ static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + i++; + } + ++ if (i < pReqMsg->numBssid) { ++ hddLog(LOGW, FL("Number of AP %u less than expected %u"), ++ i, pReqMsg->numBssid); ++ pReqMsg->numBssid = i; ++ } ++ + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0440/2.patch b/Patches/Linux_CVEs/CVE-2017-0440/2.patch new file mode 100644 index 00000000..9ec0e384 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0440/2.patch @@ -0,0 +1,96 @@ +From 8fc2d90f0be55051ff2efa8d3fbea1097f910458 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Wed, 30 Nov 2016 19:21:30 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of "set_bssid_hotlist" params + +The wlan driver supports the following vendor command: + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST + +This command supplies a "number of APs" attribute as well as a list of +per-AP attributes. However there is no validation that the number of +APs provided won't overflow the destination buffer. In addition there +is no validation that the number of APs actually provided matches the +number of APs expected. + +To address these issues: +* Verify that the expected number of APs doesn't exceed the maximum + allowed number of APs +* Verify that the actual number of APs supplied doesn't exceed the + expected number of APs +* Only process the actual number of supplied APs if it is less than + the expected number of APs. + +Change-Id: I41e36d11bc3e71928866a27afc2fbf046b59f0f5 +CRs-Fixed: 1095770 +Bug: 33252788 +Signed-off-by: Srinivas Girigowda +--- + .../staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 16 ++++++++++++++++ + drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c | 6 +++--- + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 301ef98c20d13..9ed9f6335834d 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -2752,6 +2752,11 @@ static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + } + pReqMsg->numAp = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]); ++ if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_HOTLIST_APS) { ++ hddLog(LOGE, FL("Number of AP: %u exceeds max: %u"), ++ pReqMsg->numAp, WLAN_EXTSCAN_MAX_HOTLIST_APS); ++ goto fail; ++ } + hddLog(LOG1, FL("Number of AP %d"), pReqMsg->numAp); + + /* Parse and fetch lost ap sample size */ +@@ -2770,6 +2775,11 @@ static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + i = 0; + nla_for_each_nested(apTh, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) { ++ if (i == pReqMsg->numAp) { ++ hddLog(LOGW, FL("Ignoring excess AP")); ++ break; ++ } ++ + if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(apTh), nla_len(apTh), + wlan_hdd_extscan_config_policy)) { +@@ -2808,6 +2818,12 @@ static int __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + i++; + } + ++ if (i < pReqMsg->numAp) { ++ hddLog(LOGW, FL("Number of AP %u less than expected %u"), ++ i, pReqMsg->numAp); ++ pReqMsg->numAp = i; ++ } ++ + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); + INIT_COMPLETION(context->response_event); +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +index 53898a83d9d45..ec41442b4b240 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +@@ -27091,7 +27091,7 @@ VOS_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle, + int cmd_len = 0; + int num_entries = 0; + int min_entries = 0; +- int numap = photlist->numAp; ++ uint32_t numap = photlist->numAp; + int len = sizeof(*cmd); + + len += WMI_TLV_HDR_SIZE; +@@ -27100,8 +27100,8 @@ VOS_STATUS wma_get_buf_extscan_hotlist_cmd(tp_wma_handle wma_handle, + /* setbssid hotlist expects the bssid list + * to be non zero value + */ +- if (!numap) { +- WMA_LOGE("%s: Invalid number of bssid's", __func__); ++ if (!numap || (numap > WLAN_EXTSCAN_MAX_HOTLIST_APS)) { ++ WMA_LOGE("%s: Invalid number of APs: %d", __func__, numap); + return VOS_STATUS_E_INVAL; + } + num_entries = wma_get_hotlist_entries_per_page(wma_handle->wmi_handle, diff --git a/Patches/Linux_CVEs/CVE-2017-0441/0.patch b/Patches/Linux_CVEs/CVE-2017-0441/0.patch new file mode 100644 index 00000000..5ec531e3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0441/0.patch @@ -0,0 +1,90 @@ +From da87131740351b833f17f05dfa859977bc1e7684 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Tue, 29 Nov 2016 08:19:13 -0800 +Subject: qcacld-2.0: Avoid overflow of "significant change" params + +The wlan driver supports the following vendor command: + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE + +This command supplies a "number of APs" attribute as well as a list of +per-AP attributes. However there is no validation that the number of +APs provided won't overflow the destination buffer. In addition there +is no validation that the number of APs actually provided matches the +number of APs expected. + +To address these issues: +* Verify that the expected number of APs doesn't exceed the maximum + allowed number of APs +* Verify that the actual number of APs supplied doesn't exceed the + expected number of APs +* Only process the actual number of supplied APs if it is less than + the expected number of APs. + +Change-Id: I0513ffbc4a38f1d7ddbc0815d3618fc9a2ea4f77 +CRs-Fixed: 1095009 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 16 ++++++++++++++++ + CORE/SERVICES/WMA/wma.c | 6 +++--- + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 800d123..d91859f 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -3342,6 +3342,11 @@ static int __wlan_hdd_cfg80211_extscan_set_significant_change( + } + pReqMsg->numAp = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]); ++ if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS) { ++ hddLog(LOGE, FL("Number of AP %u exceeds max %u"), ++ pReqMsg->numAp, WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS); ++ goto fail; ++ } + + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Number of AP %d Session Id %d"), pReqMsg->numAp, +@@ -3350,6 +3355,12 @@ static int __wlan_hdd_cfg80211_extscan_set_significant_change( + i = 0; + nla_for_each_nested(apTh, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) { ++ ++ if (i == pReqMsg->numAp) { ++ hddLog(LOGW, FL("Ignoring excess AP")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(apTh), nla_len(apTh), +@@ -3389,6 +3400,11 @@ static int __wlan_hdd_cfg80211_extscan_set_significant_change( + + i++; + } ++ if (i < pReqMsg->numAp) { ++ hddLog(LOGW, FL("Number of AP %u less than expected %u"), ++ i, pReqMsg->numAp); ++ pReqMsg->numAp = i; ++ } + + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); +diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c +index 0f803d4..2cf66bf 100644 +--- a/CORE/SERVICES/WMA/wma.c ++++ b/CORE/SERVICES/WMA/wma.c +@@ -28926,9 +28926,9 @@ VOS_STATUS wma_get_buf_extscan_change_monitor_cmd(tp_wma_handle wma_handle, + int numap = psigchange->numAp; + tSirAPThresholdParam *src_ap = psigchange->ap; + +- if (!numap) { +- WMA_LOGE("%s: Invalid number of bssid's", +- __func__); ++ if ((numap <= 0) || (numap > WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS)) { ++ WMA_LOGE("%s: Invalid number of APs: %d", ++ __func__, numap); + return VOS_STATUS_E_INVAL; + } + len += WMI_TLV_HDR_SIZE; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0441/1.patch b/Patches/Linux_CVEs/CVE-2017-0441/1.patch new file mode 100644 index 00000000..79872663 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0441/1.patch @@ -0,0 +1,93 @@ +From 26e873d1ea24db46362ed80fc53f74c1201af0b1 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Wed, 30 Nov 2016 19:20:45 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of "significant change" params + +The wlan driver supports the following vendor command: + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE + +This command supplies a "number of APs" attribute as well as a list of +per-AP attributes. However there is no validation that the number of +APs provided won't overflow the destination buffer. In addition there +is no validation that the number of APs actually provided matches the +number of APs expected. + +To address these issues: +* Verify that the expected number of APs doesn't exceed the maximum + allowed number of APs +* Verify that the actual number of APs supplied doesn't exceed the + expected number of APs +* Only process the actual number of supplied APs if it is less than + the expected number of APs. + +Change-Id: I0513ffbc4a38f1d7ddbc0815d3618fc9a2ea4f77 +CRs-Fixed: 1095009 +Bug: 32872662 +Signed-off-by: Srinivas Girigowda +--- + .../staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 16 ++++++++++++++++ + drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c | 8 ++++---- + 2 files changed, 20 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index fd23a304b93bd..301ef98c20d13 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -3201,6 +3201,11 @@ static int __wlan_hdd_cfg80211_extscan_set_significant_change( + } + pReqMsg->numAp = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]); ++ if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS) { ++ hddLog(LOGE, FL("Number of AP %u exceeds max %u"), ++ pReqMsg->numAp, WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS); ++ goto fail; ++ } + + pReqMsg->sessionId = pAdapter->sessionId; + hddLog(LOG1, FL("Number of AP %d Session Id %d"), pReqMsg->numAp, +@@ -3209,6 +3214,12 @@ static int __wlan_hdd_cfg80211_extscan_set_significant_change( + i = 0; + nla_for_each_nested(apTh, + tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM], rem) { ++ ++ if (i == pReqMsg->numAp) { ++ hddLog(LOGW, FL("Ignoring excess AP")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, + nla_data(apTh), nla_len(apTh), +@@ -3248,6 +3259,11 @@ static int __wlan_hdd_cfg80211_extscan_set_significant_change( + + i++; + } ++ if (i < pReqMsg->numAp) { ++ hddLog(LOGW, FL("Number of AP %u less than expected %u"), ++ i, pReqMsg->numAp); ++ pReqMsg->numAp = i; ++ } + + context = &pHddCtx->ext_scan_context; + spin_lock(&hdd_context_lock); +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +index f1c4eb4e2c5db..53898a83d9d45 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +@@ -27390,12 +27390,12 @@ VOS_STATUS wma_get_buf_extscan_change_monitor_cmd(tp_wma_handle wma_handle, + u_int8_t *buf_ptr; + int j; + int len = sizeof(*cmd); +- int numap = psigchange->numAp; ++ uint32_t numap = psigchange->numAp; + tSirAPThresholdParam *src_ap = psigchange->ap; + +- if (!numap) { +- WMA_LOGE("%s: Invalid number of bssid's", +- __func__); ++ if (!numap || (numap > WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS)) { ++ WMA_LOGE("%s: Invalid number of APs: %d", ++ __func__, numap); + return VOS_STATUS_E_INVAL; + } + len += WMI_TLV_HDR_SIZE; diff --git a/Patches/Linux_CVEs/CVE-2017-0442/0.patch b/Patches/Linux_CVEs/CVE-2017-0442/0.patch new file mode 100644 index 00000000..3e7bc3db --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0442/0.patch @@ -0,0 +1,128 @@ +From 1f0b036dc74ccb6e9f0a03a540efdb0876f5ca77 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Mon, 28 Nov 2016 09:19:02 -0800 +Subject: qcacld-2.0: Avoid overflow of roam subcmd params + +Currently when processing the QCA_NL80211_VENDOR_SUBCMD_ROAM vendor +command, for the following roam commands there are input validation +issues: + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID + +Both of these commands have a "number of BSSIDs" attribute as well as a +list of BSSIDs. However there is no validation that the number of +BSSIDs provided won't overflow the destination buffer. In addition +there is no validation that the number of BSSIDs actually provided +matches the number of BSSIDs expected. + +To address these issues, for the above mentioned commands: +* Verify that the expected number of BSSIDs doesn't exceed the maximum + allowed number of BSSIDs +* Verify that the actual number of BSSIDs supplied doesn't exceed the + expected number of BSSIDs +* Only process the actual number of supplied BSSIDs if it is less than + the expected number of BSSIDs. + +Change-Id: Ifa6121ee1b1441ec415198897ef815b40cb5aff6 +CRs-Fixed: 1092497 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 43 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index b3c265c..800d123 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1870,6 +1870,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; ++ uint32_t count; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { +@@ -2045,15 +2046,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } +- roam_params.num_bssid_favored = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); ++ if (count > MAX_BSSID_FAVORED) { ++ hddLog(LOGE, FL("Preferred BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_FAVORED); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of Preferred BSSID (%d)"), +- roam_params.num_bssid_favored); ++ FL("Num of Preferred BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Preferred BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2083,6 +2094,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_favored_factor[i]); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Preferred BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_favored = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; +@@ -2092,15 +2108,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } +- roam_params.num_bssid_avoid_list = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); ++ if (count > MAX_BSSID_AVOID_LIST) { ++ hddLog(LOGE, FL("Blacklist BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_AVOID_LIST); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of blacklist BSSID (%d)"), +- roam_params.num_bssid_avoid_list); ++ FL("Num of blacklist BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Blacklist BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2121,6 +2147,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_avoid_list[i])); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Blacklist BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_avoid_list = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0442/1.patch b/Patches/Linux_CVEs/CVE-2017-0442/1.patch new file mode 100644 index 00000000..acb3c306 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0442/1.patch @@ -0,0 +1,127 @@ +From 138c690bd39a3f1ba14450e308ebc56bbda1f5b2 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Mon, 28 Nov 2016 20:47:30 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of roam subcmd params + +Currently when processing the QCA_NL80211_VENDOR_SUBCMD_ROAM vendor +command, for the following roam commands there are input validation +issues: + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID + +Both of these commands have a "number of BSSIDs" attribute as well as a +list of BSSIDs. However there is no validation that the number of +BSSIDs provided won't overflow the destination buffer. In addition +there is no validation that the number of BSSIDs actually provided +matches the number of BSSIDs expected. + +To address these issues, for the above mentioned commands: +* Verify that the expected number of BSSIDs doesn't exceed the maximum + allowed number of BSSIDs +* Verify that the actual number of BSSIDs supplied doesn't exceed the + expected number of BSSIDs +* Only process the actual number of supplied BSSIDs if it is less than + the expected number of BSSIDs. + +Change-Id: Ifa6121ee1b1441ec415198897ef815b40cb5aff6 +CRs-Fixed: 1092497 +Bug: 32402310 32402604 32871330 +Signed-off-by: Srinivas Girigowda +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 43 +++++++++++++++++++--- + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 89dba5d54b627..fd23a304b93bd 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1799,6 +1799,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; ++ uint32_t count; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { +@@ -1974,15 +1975,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } +- roam_params.num_bssid_favored = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); ++ if (count > MAX_BSSID_FAVORED) { ++ hddLog(LOGE, FL("Preferred BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_FAVORED); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of Preferred BSSID (%d)"), +- roam_params.num_bssid_favored); ++ FL("Num of Preferred BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Preferred BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2012,6 +2023,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_favored_factor[i]); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Preferred BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_favored = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; +@@ -2021,15 +2037,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } +- roam_params.num_bssid_avoid_list = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); ++ if (count > MAX_BSSID_AVOID_LIST) { ++ hddLog(LOGE, FL("Blacklist BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_AVOID_LIST); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of blacklist BSSID (%d)"), +- roam_params.num_bssid_avoid_list); ++ FL("Num of blacklist BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Blacklist BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2050,6 +2076,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_avoid_list[i])); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Blacklist BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_avoid_list = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; diff --git a/Patches/Linux_CVEs/CVE-2017-0443/0.patch b/Patches/Linux_CVEs/CVE-2017-0443/0.patch new file mode 100644 index 00000000..3e7bc3db --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0443/0.patch @@ -0,0 +1,128 @@ +From 1f0b036dc74ccb6e9f0a03a540efdb0876f5ca77 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Mon, 28 Nov 2016 09:19:02 -0800 +Subject: qcacld-2.0: Avoid overflow of roam subcmd params + +Currently when processing the QCA_NL80211_VENDOR_SUBCMD_ROAM vendor +command, for the following roam commands there are input validation +issues: + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID + +Both of these commands have a "number of BSSIDs" attribute as well as a +list of BSSIDs. However there is no validation that the number of +BSSIDs provided won't overflow the destination buffer. In addition +there is no validation that the number of BSSIDs actually provided +matches the number of BSSIDs expected. + +To address these issues, for the above mentioned commands: +* Verify that the expected number of BSSIDs doesn't exceed the maximum + allowed number of BSSIDs +* Verify that the actual number of BSSIDs supplied doesn't exceed the + expected number of BSSIDs +* Only process the actual number of supplied BSSIDs if it is less than + the expected number of BSSIDs. + +Change-Id: Ifa6121ee1b1441ec415198897ef815b40cb5aff6 +CRs-Fixed: 1092497 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 43 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index b3c265c..800d123 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1870,6 +1870,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; ++ uint32_t count; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { +@@ -2045,15 +2046,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } +- roam_params.num_bssid_favored = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); ++ if (count > MAX_BSSID_FAVORED) { ++ hddLog(LOGE, FL("Preferred BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_FAVORED); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of Preferred BSSID (%d)"), +- roam_params.num_bssid_favored); ++ FL("Num of Preferred BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Preferred BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2083,6 +2094,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_favored_factor[i]); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Preferred BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_favored = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; +@@ -2092,15 +2108,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } +- roam_params.num_bssid_avoid_list = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); ++ if (count > MAX_BSSID_AVOID_LIST) { ++ hddLog(LOGE, FL("Blacklist BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_AVOID_LIST); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of blacklist BSSID (%d)"), +- roam_params.num_bssid_avoid_list); ++ FL("Num of blacklist BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Blacklist BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2121,6 +2147,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_avoid_list[i])); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Blacklist BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_avoid_list = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0443/1.patch b/Patches/Linux_CVEs/CVE-2017-0443/1.patch new file mode 100644 index 00000000..acb3c306 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0443/1.patch @@ -0,0 +1,127 @@ +From 138c690bd39a3f1ba14450e308ebc56bbda1f5b2 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Mon, 28 Nov 2016 20:47:30 -0800 +Subject: [PATCH] qcacld-2.0: Avoid overflow of roam subcmd params + +Currently when processing the QCA_NL80211_VENDOR_SUBCMD_ROAM vendor +command, for the following roam commands there are input validation +issues: + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID + +Both of these commands have a "number of BSSIDs" attribute as well as a +list of BSSIDs. However there is no validation that the number of +BSSIDs provided won't overflow the destination buffer. In addition +there is no validation that the number of BSSIDs actually provided +matches the number of BSSIDs expected. + +To address these issues, for the above mentioned commands: +* Verify that the expected number of BSSIDs doesn't exceed the maximum + allowed number of BSSIDs +* Verify that the actual number of BSSIDs supplied doesn't exceed the + expected number of BSSIDs +* Only process the actual number of supplied BSSIDs if it is less than + the expected number of BSSIDs. + +Change-Id: Ifa6121ee1b1441ec415198897ef815b40cb5aff6 +CRs-Fixed: 1092497 +Bug: 32402310 32402604 32871330 +Signed-off-by: Srinivas Girigowda +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 43 +++++++++++++++++++--- + 1 file changed, 37 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 89dba5d54b627..fd23a304b93bd 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1799,6 +1799,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1]; + int rem, i; + uint32_t buf_len = 0; ++ uint32_t count; + int ret; + + if (VOS_FTM_MODE == hdd_get_conparam()) { +@@ -1974,15 +1975,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of preferred bssid failed")); + goto fail; + } +- roam_params.num_bssid_favored = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]); ++ if (count > MAX_BSSID_FAVORED) { ++ hddLog(LOGE, FL("Preferred BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_FAVORED); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of Preferred BSSID (%d)"), +- roam_params.num_bssid_favored); ++ FL("Num of Preferred BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Preferred BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2012,6 +2023,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_favored_factor[i]); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Preferred BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_favored = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_FAVORED_BSSID); + break; +@@ -2021,15 +2037,25 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + hddLog(LOGE, FL("attr num of blacklist bssid failed")); + goto fail; + } +- roam_params.num_bssid_avoid_list = nla_get_u32( ++ count = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]); ++ if (count > MAX_BSSID_AVOID_LIST) { ++ hddLog(LOGE, FL("Blacklist BSSID count %u exceeds max %u"), ++ count, MAX_BSSID_AVOID_LIST); ++ goto fail; ++ } + hddLog(VOS_TRACE_LEVEL_DEBUG, +- FL("Num of blacklist BSSID (%d)"), +- roam_params.num_bssid_avoid_list); ++ FL("Num of blacklist BSSID: %d"), count); + i = 0; + nla_for_each_nested(curr_attr, + tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS], + rem) { ++ ++ if (i == count) { ++ hddLog(LOGW, FL("Ignoring excess Blacklist BSSID")); ++ break; ++ } ++ + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +@@ -2050,6 +2076,11 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + roam_params.bssid_avoid_list[i])); + i++; + } ++ if (i < count) ++ hddLog(LOGW, ++ FL("Num Blacklist BSSID %u less than expected %u"), ++ i, count); ++ roam_params.num_bssid_avoid_list = i; + sme_update_roam_params(pHddCtx->hHal, session_id, + roam_params, REASON_ROAM_SET_BLACKLIST_BSSID); + break; diff --git a/Patches/Linux_CVEs/CVE-2017-0444/0.patch b/Patches/Linux_CVEs/CVE-2017-0444/0.patch new file mode 100644 index 00000000..699a7985 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0444/0.patch @@ -0,0 +1,60 @@ +From 230f280dd4046a227665ff07c9afaa7b9aa1e061 Mon Sep 17 00:00:00 2001 +From: Mark Salyzyn +Date: Thu, 17 Nov 2016 08:58:07 -0800 +Subject: rt5677: protect model_buf and model_len + +vad_lock is active for model_buf and model_len fields +except during RT_WRITE_CODEC_DSP_IOCTL transactions. + +Signed-off-by: Mark Salyzyn +Bug: 32705232 +Change-Id: I3493909019b18a902c577c0010b41087fecb5325 +--- + sound/soc/codecs/rt5677.h | 1 + + sound/soc/codecs/rt5677_ioctl.c | 10 ++++++++-- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/rt5677.h b/sound/soc/codecs/rt5677.h +index 5295cfd..2375769 100644 +--- a/sound/soc/codecs/rt5677.h ++++ b/sound/soc/codecs/rt5677.h +@@ -1468,6 +1468,7 @@ struct rt5677_priv { + */ + struct regmap *regmap; + struct mutex index_lock; ++ /* protects vad activities, including model_len and model_buf */ + struct mutex vad_lock; + struct workqueue_struct *check_mic_wq; + struct delayed_work check_hp_mic_work; +diff --git a/sound/soc/codecs/rt5677_ioctl.c b/sound/soc/codecs/rt5677_ioctl.c +index f5ee880..d3262f5 100644 +--- a/sound/soc/codecs/rt5677_ioctl.c ++++ b/sound/soc/codecs/rt5677_ioctl.c +@@ -151,16 +151,22 @@ int rt5677_ioctl_common(struct snd_hwdep *hw, struct file *file, + + case RT_WRITE_CODEC_DSP_IOCTL: + case RT_WRITE_CODEC_DSP_IOCTL_COMPAT: ++ mutex_lock(&rt5677->vad_lock); + if (!rt5677->model_buf || rt5677->model_len < size) { + vfree(rt5677->model_buf); + rt5677->model_len = 0; + rt5677->model_buf = vmalloc(size); +- if (!rt5677->model_buf) ++ if (!rt5677->model_buf) { ++ mutex_unlock(&rt5677->vad_lock); + return -ENOMEM; ++ } + } +- if (copy_from_user(rt5677->model_buf, rt_codec.buf, size)) ++ if (copy_from_user(rt5677->model_buf, rt_codec.buf, size)) { ++ mutex_unlock(&rt5677->vad_lock); + return -EFAULT; ++ } + rt5677->model_len = size; ++ mutex_unlock(&rt5677->vad_lock); + return 0; + + default: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0445/0.patch b/Patches/Linux_CVEs/CVE-2017-0445/0.patch new file mode 100644 index 00000000..0a9424c6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0445/0.patch @@ -0,0 +1,34 @@ +From 773179468893965c2b81aa7ffe3722b6868ef749 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Fri, 2 Dec 2016 21:56:40 -0800 +Subject: [PATCH] input: touchscreen: disable generic update i/f + +Disable the generic touchscreen firmware update hook. +The generic touchscreen firmware update driver has +security flaws and is not necessary for Marlin touchscreen +firmware updates. + +synaptics_dsx_htc_2.6 still attempts firmware updates +via request_firmware on boot with this disabled. + +BUG: 32917445 +BUG: 32919560 +BUG: 32769717 +Change-Id: I272a1d1aba16b53647f2dde9dc7ff8b306179b43 +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index b633d17ea8b18..1e7ce91810f41 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -1020,7 +1020,6 @@ config SECURE_TOUCH + + config TOUCHSCREEN_TOUCH_FW_UPDATE + tristate "Touchscreen firmware update" +- default y + help + Say Y here to support touch firmware update + diff --git a/Patches/Linux_CVEs/CVE-2017-0445/1.patch b/Patches/Linux_CVEs/CVE-2017-0445/1.patch new file mode 100644 index 00000000..4db4d28a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0445/1.patch @@ -0,0 +1,373 @@ +From 367e64520dba1652d8f6d0ac1ebda3cab0f9e374 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Tue, 6 Dec 2016 17:03:07 -0800 +Subject: [PATCH] input: synaptics_dsx: remove update sysfs entries + +Remove sysfs entrypoints to fw_update module. +Also fixes request_firmware firmware update path. + +BUG: 32769717 +Change-Id: Iab7ff456288a18be71636b84c8e3008390c0d872 +Signed-off-by: Andrew Chant +--- + .../touchscreen/synaptics_dsx_htc_2.6/Kconfig | 10 ++++ + .../synaptics_dsx_fw_update.c | 53 ++++++++++++++++++++-- + 2 files changed, 60 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/Kconfig b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/Kconfig +index 30c64910d7dd5..60f536c8ee150 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/Kconfig ++++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/Kconfig +@@ -59,6 +59,16 @@ config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_HTC_v26 + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_fw_update. + ++config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 ++ bool "Synaptics DSX firmware update sysfs attributes" ++ depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_HTC_v26 ++ help ++ Say Y here to enable support for sysfs attributes for ++ performing firmware update in a development environment. ++ This does not affect the core or other subsystem attributes. ++ ++ If unsure, say N. ++ + config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING_HTC_v26 + tristate "Synaptics DSX v2.6 test reporting module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE_HTC_v26 +diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c +index f7d5dbdd69b53..aff460c13f257 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c +@@ -140,6 +140,7 @@ static int fwu_do_reflash(void); + + static int fwu_recovery_check_status(void); + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); +@@ -192,6 +193,7 @@ static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + + static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); ++#endif + + enum f34_version { + F34_V0 = 0, +@@ -708,6 +710,7 @@ struct synaptics_rmi4_fwu_handle { + #endif + }; + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", +@@ -765,11 +768,15 @@ static struct device_attribute attrs[] = { + synaptics_rmi4_show_error, + fwu_sysfs_write_guest_code_store), + }; ++#endif + + static struct synaptics_rmi4_fwu_handle *fwu; + + DECLARE_COMPLETION(fwu_remove_complete); ++ ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + DEFINE_MUTEX(fwu_sysfs_mutex); ++#endif + + /* Check offset + size <= bound. true if in bounds, false otherwise. */ + static bool in_bounds(unsigned long offset, unsigned long size, +@@ -923,6 +930,7 @@ static int fwu_f51_force_data_init(void) + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_allocate_read_config_buf(unsigned int count) + { + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +@@ -942,6 +950,7 @@ static int fwu_allocate_read_config_buf(unsigned int count) + + return 0; + } ++#endif + + static void fwu_compare_partition_tables(void) + { +@@ -2471,6 +2480,7 @@ static int fwu_write_f34_blocks(unsigned char *block_ptr, + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_read_f34_v7_blocks(unsigned short block_cnt, + unsigned char command) + { +@@ -2624,6 +2634,7 @@ static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd) + + return retval; + } ++#endif + + static int fwu_get_image_firmware_id(unsigned int *fw_id) + { +@@ -2645,7 +2656,7 @@ static int fwu_get_image_firmware_id(unsigned int *fw_id) + } + + strptr += 2; +- firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN, GFP_KERNEL); ++ firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN + 1, GFP_KERNEL); + if (!firmware_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for firmware_id\n", +@@ -3032,6 +3043,7 @@ static int fwu_check_ui_configuration_size(void) + return 0; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_check_dp_configuration_size(void) + { + unsigned short block_count; +@@ -3065,6 +3077,7 @@ static int fwu_check_pm_configuration_size(void) + + return 0; + } ++#endif + + #ifndef SYNA_SIMPLE_UPDATE + static int fwu_check_bl_configuration_size(void) +@@ -3085,6 +3098,7 @@ static int fwu_check_bl_configuration_size(void) + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_check_guest_code_size(void) + { + unsigned short block_count; +@@ -3100,6 +3114,7 @@ static int fwu_check_guest_code_size(void) + + return 0; + } ++#endif + + static int fwu_erase_configuration(void) + { +@@ -3199,6 +3214,7 @@ static int fwu_erase_utility_parameter(void) + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_erase_guest_code(void) + { + int retval; +@@ -3222,6 +3238,7 @@ static int fwu_erase_guest_code(void) + + return 0; + } ++#endif + + static int fwu_erase_all(void) + { +@@ -3275,7 +3292,7 @@ static int fwu_erase_all(void) + + #ifndef SYNA_SIMPLE_UPDATE + if (fwu->flash_properties.has_disp_config && +- fwu->img.contains_disp_config) { ++ fwu->img.contains_disp_config) { + fwu->config_area = DP_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) +@@ -3424,6 +3441,7 @@ static int fwu_write_ui_configuration(void) + return fwu_write_configuration(); + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_write_dp_configuration(void) + { + fwu->config_area = DP_CONFIG_AREA; +@@ -3443,6 +3461,7 @@ static int fwu_write_pm_configuration(void) + + return fwu_write_configuration(); + } ++#endif + + #ifndef SYNA_SIMPLE_UPDATE + static int fwu_write_flash_configuration(void) +@@ -3476,6 +3495,7 @@ static int fwu_write_flash_configuration(void) + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_write_guest_code(void) + { + int retval; +@@ -3490,6 +3510,7 @@ static int fwu_write_guest_code(void) + + return 0; + } ++#endif + + static int fwu_write_lockdown(void) + { +@@ -3998,6 +4019,7 @@ static int fwu_do_reflash(void) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_do_read_config(void) + { + int retval; +@@ -4076,6 +4098,7 @@ static int fwu_do_read_config(void) + + return retval; + } ++#endif + + static int fwu_do_lockdown_v7(void) + { +@@ -4212,6 +4235,7 @@ static int fwu_do_restore_f51_cal_data(void) + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_start_write_guest_code(void) + { + int retval; +@@ -4417,6 +4441,7 @@ static int fwu_start_write_config(void) + + return retval; + } ++#endif + + static int fwu_start_reflash(void) + { +@@ -4472,6 +4497,7 @@ static int fwu_start_reflash(void) + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + fwu->image = fw_entry->data; ++ fwu->image_size = fw_entry->size; + } + + retval = fwu_parse_image_info(); +@@ -4691,6 +4717,7 @@ static int fwu_recovery_check_status(void) + return 0; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static int fwu_recovery_erase_completion(void) + { + int retval; +@@ -4965,6 +4992,7 @@ static int fwu_start_recovery(void) + + return retval; + } ++#endif + + #ifdef HTC_FEATURE + static int fwu_do_write_config(uint8_t *config_data) +@@ -5219,8 +5247,10 @@ static void fwu_startup_fw_update_work(struct work_struct *work) + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + /* Prevent sysfs operations during initial update. */ + mutex_lock(&fwu_sysfs_mutex); ++#endif + + #ifdef HTC_FEATURE + wake_lock(&fwu->fwu_wake_lock); +@@ -5236,11 +5266,14 @@ static void fwu_startup_fw_update_work(struct work_struct *work) + #else + synaptics_fw_updater(NULL); + #endif ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + mutex_unlock(&fwu_sysfs_mutex); ++#endif + return; + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +@@ -5674,6 +5707,7 @@ static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + mutex_unlock(&fwu_sysfs_mutex); + return retval; + } ++#endif + + static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +@@ -5690,7 +5724,9 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + { + int retval; ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + unsigned char attr_count; ++#endif + struct pdt_properties pdt_props; + + if (fwu) { +@@ -5758,6 +5794,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + fwu->do_lockdown = DO_LOCKDOWN; + fwu->initialized = true; + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, + &dev_attr_data); + if (retval < 0) { +@@ -5778,6 +5815,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + goto exit_remove_attrs; + } + } ++#endif + + #ifdef DO_STARTUP_FW_UPDATE + #ifdef HTC_FEATURE +@@ -5800,13 +5838,19 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + + return 0; + ++#if defined(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26) || \ ++ defined(F51_DISCRETE_FORCE) + exit_remove_attrs: ++#endif ++ ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); ++#endif + + exit_free_mem: + kfree(fwu->image_name); +@@ -5821,8 +5865,9 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + + static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) + { ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + unsigned char attr_count; +- ++#endif + if (!fwu) + goto exit; + +@@ -5835,12 +5880,14 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) + #endif + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_SYSFS_HTC_v26 + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); ++#endif + + #ifdef F51_DISCRETE_FORCE + kfree(fwu->cal_data); diff --git a/Patches/Linux_CVEs/CVE-2017-0445/2.patch b/Patches/Linux_CVEs/CVE-2017-0445/2.patch new file mode 100644 index 00000000..c2e986ef --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0445/2.patch @@ -0,0 +1,210 @@ +From 2615c5f302441568e6dd20007bc5246d72837e80 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Tue, 6 Dec 2016 19:19:26 -0800 +Subject: [PATCH] input: synaptics_dsx: remove update sysfs entries + +Remove sysfs entrypoints to fw_update module. + +BUG: 32769717 +Change-Id: I425761af84ed5c31cc5902b4f49c4981a49f3af0 +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/synaptics_dsx25/Kconfig | 10 ++++++++ + .../synaptics_dsx25/synaptics_dsx_fw_update.c | 27 ++++++++++++++++++++-- + 2 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx25/Kconfig b/drivers/input/touchscreen/synaptics_dsx25/Kconfig +index 36661fc9d6a2d..218a6c3c96467 100644 +--- a/drivers/input/touchscreen/synaptics_dsx25/Kconfig ++++ b/drivers/input/touchscreen/synaptics_dsx25/Kconfig +@@ -59,6 +59,16 @@ config TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_fw_update. + ++config TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS ++ bool "Synaptics DSX firmware update sysfs attributes" ++ depends on TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE ++ help ++ Say Y here to enable support for sysfs attributes for ++ performing firmware update in a development environment. ++ This does not affect the core or other subsystem attributes. ++ ++ If unsure, say N. ++ + config TOUCHSCREEN_SYNAPTICS_DSX25_ACTIVE_PEN + tristate "Synaptics DSX active pen module" + depends on TOUCHSCREEN_SYNAPTICS25_DSX_CORE +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 323f65891b458..8cad4d3b3a9d9 100755 +--- a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c +@@ -105,6 +105,7 @@ static int fwu_do_reflash(void); + + static int fwu_recovery_check_status(void); + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); +@@ -157,6 +158,7 @@ static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + + static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); ++#endif + + enum f34_version { + F34_V0 = 0, +@@ -595,6 +597,7 @@ struct synaptics_rmi4_fwu_handle { + struct work_struct fwu_work; + }; + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", +@@ -652,12 +655,14 @@ static struct device_attribute attrs[] = { + synaptics_rmi4_show_error, + fwu_sysfs_write_guest_code_store), + }; ++#endif + + static struct synaptics_rmi4_fwu_handle *fwu; + + DECLARE_COMPLETION(dsx_fwu_remove_complete); ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + DEFINE_MUTEX(fwu_sysfs_mutex); +- ++#endif + static bool tp_2k_panel = false; + /** + * early_param: Parse system early startup parameters. +@@ -3057,6 +3062,7 @@ static int fwu_do_reflash(void) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static int fwu_do_read_config(void) + { + int retval; +@@ -3136,6 +3142,7 @@ static int fwu_do_read_config(void) + + return retval; + } ++#endif + + static int fwu_do_lockdown(void) + { +@@ -3173,6 +3180,7 @@ static int fwu_do_lockdown(void) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static int fwu_start_write_guest_code(void) + { + int retval; +@@ -3348,6 +3356,7 @@ static int fwu_start_write_config(void) + + return retval; + } ++#endif + + static void synaptics_refresh_configid(void) + { +@@ -3584,6 +3593,7 @@ static int fwu_recovery_check_status(void) + return 0; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static int fwu_recovery_erase_all(void) + { + int retval; +@@ -3778,6 +3788,7 @@ static int fwu_start_recovery(void) + + return retval; + } ++#endif + + int synaptics_dsx25_fw_updater(const unsigned char *fw_data) + { +@@ -3838,6 +3849,7 @@ static void fwu_startup_fw_update_work(struct work_struct *work) + } + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +@@ -4236,6 +4248,7 @@ static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + mutex_unlock(&fwu_sysfs_mutex); + return retval; + } ++#endif + + static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +@@ -4252,7 +4265,9 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + { + int retval; ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + unsigned char attr_count; ++#endif + struct pdt_properties pdt_props; + + if (fwu) { +@@ -4319,6 +4334,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + &fwu->fwu_work); + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, + &dev_attr_data); + if (retval < 0) { +@@ -4339,9 +4355,11 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + goto exit_remove_attrs; + } + } ++#endif + + return 0; + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + exit_remove_attrs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, +@@ -4349,8 +4367,9 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); +- + exit_destroy_work: ++#endif ++ + #ifdef DO_STARTUP_FW_UPDATE + cancel_work_sync(&fwu->fwu_work); + flush_workqueue(fwu->fwu_workqueue); +@@ -4370,7 +4389,9 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + + static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) + { ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + unsigned char attr_count; ++#endif + + if (!fwu) + goto exit; +@@ -4381,12 +4402,14 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) + destroy_workqueue(fwu->fwu_workqueue); + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX25_FW_UPDATE_SYSFS + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); ++#endif + + kfree(fwu->read_config_buf); + kfree(fwu->image_name); diff --git a/Patches/Linux_CVEs/CVE-2017-0445/3.patch b/Patches/Linux_CVEs/CVE-2017-0445/3.patch new file mode 100644 index 00000000..ed4d450e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0445/3.patch @@ -0,0 +1,181 @@ +From fe160e51f02ee5db529c2e84ac8364c89cce005e Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Tue, 6 Dec 2016 20:59:01 -0800 +Subject: [PATCH] input: synaptics_dsx: remove some sysfs nodes. + +Remove most sysfs entrypoints to fw_update module. +Retains check_fw, which is triggered from an +init script. + +BUG: 32769717 +Change-Id: I710cb37a8b5382dce7aa6a1d8748be5853a18a7a +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/Kconfig | 10 ++++++++++ + drivers/input/touchscreen/synaptics_fw_update.c | 20 ++++++++++++++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index a42fea5862af2..64266998c2290 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -1019,6 +1019,16 @@ config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_fw_update. + ++config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS ++ bool "Synaptics DSX firmware update extra sysfs attributes" ++ depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE ++ help ++ Say Y here to enable support for extra sysfs attributes ++ supporting firmware update in a development environment. ++ This does not affect the core or other subsystem attributes. ++ ++ If unsure, say N. ++ + config SECURE_TOUCH + bool "Secure Touch" + depends on (TOUCHSCREEN_ATMEL_MXT || TOUCHSCREEN_SYNAPTICS_I2C_RMI4 || \ +diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c +index 8891f1c836684..360e455a5a51b 100644 +--- a/drivers/input/touchscreen/synaptics_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_fw_update.c +@@ -1331,6 +1331,7 @@ static int fwu_do_write_config(void) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static int fwu_start_write_config(void) + { + int retval; +@@ -1383,6 +1384,7 @@ static int fwu_start_write_config(void) + + return retval; + } ++#endif + + static int fwu_do_write_lockdown(bool reset) + { +@@ -1430,6 +1432,7 @@ static int fwu_do_write_lockdown(bool reset) + return retval; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static int fwu_start_write_lockdown(void) + { + if (parse_header()) +@@ -1533,6 +1536,7 @@ static int fwu_do_read_config(void) + exit: + return retval; + } ++#endif + + static int fwu_do_reflash(void) + { +@@ -1767,6 +1771,7 @@ int synaptics_fw_updater(void) + } + EXPORT_SYMBOL(synaptics_fw_updater); + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +@@ -2021,6 +2026,7 @@ static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev, + mutex_unlock(&fwu_sysfs_mutex); + return retval; + } ++#endif + + static ssize_t fwu_sysfs_check_fw_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +@@ -2044,6 +2050,7 @@ static ssize_t fwu_sysfs_check_fw_store(struct device *dev, + return count; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) + { +@@ -2265,6 +2272,7 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev, + (pkg_id[1] << 8) | pkg_id[0], + (pkg_id[3] << 8) | pkg_id[2]); + } ++#endif + + static int synaptics_rmi4_debug_dump_info(struct seq_file *m, void *v) + { +@@ -2298,6 +2306,7 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + return; + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", +@@ -2307,8 +2316,10 @@ static struct bin_attribute dev_attr_data = { + .read = fwu_sysfs_show_image, + .write = fwu_sysfs_store_image, + }; ++#endif + + static struct device_attribute attrs[] = { ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP, + fwu_sysfs_image_name_show, + fwu_sysfs_image_name_store), +@@ -2318,9 +2329,11 @@ static struct device_attribute attrs[] = { + __ATTR(update_fw, S_IWUSR | S_IWGRP, + NULL, + fwu_sysfs_do_reflash_store), ++#endif + __ATTR(check_fw, S_IWUSR | S_IWGRP, + NULL, + fwu_sysfs_check_fw_store), ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + __ATTR(writeconfig, S_IWUSR | S_IWGRP, + NULL, + fwu_sysfs_write_config_store), +@@ -2360,6 +2373,7 @@ static struct device_attribute attrs[] = { + __ATTR(package_id, S_IRUGO, + fwu_sysfs_package_id_show, + synaptics_rmi4_store_error), ++#endif + }; + + +@@ -2470,6 +2484,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work); + #endif + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj, + &dev_attr_data); + if (retval < 0) { +@@ -2478,6 +2493,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + __func__); + goto exit_free_mem; + } ++#endif + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj, +@@ -2511,7 +2527,9 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + &attrs[attr_count].attr); + } + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); ++#endif + + exit_free_mem: + kfree(fwu->fn_ptr); +@@ -2528,7 +2546,9 @@ static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) + { + unsigned char attr_count; + ++#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); ++#endif + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, diff --git a/Patches/Linux_CVEs/CVE-2017-0446/0.patch b/Patches/Linux_CVEs/CVE-2017-0446/0.patch new file mode 100644 index 00000000..0a9424c6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0446/0.patch @@ -0,0 +1,34 @@ +From 773179468893965c2b81aa7ffe3722b6868ef749 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Fri, 2 Dec 2016 21:56:40 -0800 +Subject: [PATCH] input: touchscreen: disable generic update i/f + +Disable the generic touchscreen firmware update hook. +The generic touchscreen firmware update driver has +security flaws and is not necessary for Marlin touchscreen +firmware updates. + +synaptics_dsx_htc_2.6 still attempts firmware updates +via request_firmware on boot with this disabled. + +BUG: 32917445 +BUG: 32919560 +BUG: 32769717 +Change-Id: I272a1d1aba16b53647f2dde9dc7ff8b306179b43 +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index b633d17ea8b18..1e7ce91810f41 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -1020,7 +1020,6 @@ config SECURE_TOUCH + + config TOUCHSCREEN_TOUCH_FW_UPDATE + tristate "Touchscreen firmware update" +- default y + help + Say Y here to support touch firmware update + diff --git a/Patches/Linux_CVEs/CVE-2017-0447/0.patch b/Patches/Linux_CVEs/CVE-2017-0447/0.patch new file mode 100644 index 00000000..0a9424c6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0447/0.patch @@ -0,0 +1,34 @@ +From 773179468893965c2b81aa7ffe3722b6868ef749 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Fri, 2 Dec 2016 21:56:40 -0800 +Subject: [PATCH] input: touchscreen: disable generic update i/f + +Disable the generic touchscreen firmware update hook. +The generic touchscreen firmware update driver has +security flaws and is not necessary for Marlin touchscreen +firmware updates. + +synaptics_dsx_htc_2.6 still attempts firmware updates +via request_firmware on boot with this disabled. + +BUG: 32917445 +BUG: 32919560 +BUG: 32769717 +Change-Id: I272a1d1aba16b53647f2dde9dc7ff8b306179b43 +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index b633d17ea8b18..1e7ce91810f41 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -1020,7 +1020,6 @@ config SECURE_TOUCH + + config TOUCHSCREEN_TOUCH_FW_UPDATE + tristate "Touchscreen firmware update" +- default y + help + Say Y here to support touch firmware update + diff --git a/Patches/Linux_CVEs/CVE-2017-0449/0.patch b/Patches/Linux_CVEs/CVE-2017-0449/0.patch new file mode 100644 index 00000000..7763f01f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0449/0.patch @@ -0,0 +1,124 @@ +From 323a28bf14c622bdd1b9ecf09a339b00af98c965 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Wed, 23 Nov 2016 08:29:33 -0800 +Subject: [PATCH] net: wireless: bcmdhd: remove PCIe debug IOVAR access + +delete PCIe debug IOVARs in production build. + +BUG: 31707909 + +Signed-off-by: Insun Song +Change-Id: Icd659169eeae3e587bec1f5587511a354d482a33 +--- + drivers/net/wireless/bcmdhd/dhd_pcie.c | 98 ---------------------------------- + 1 file changed, 98 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pcie.c b/drivers/net/wireless/bcmdhd/dhd_pcie.c +index 26201a6d2f39d..c56f789c4797f 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pcie.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pcie.c +@@ -2609,104 +2609,6 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons + bcmerror = dhdpcie_downloadvars(bus, arg, len); + break; + +- case IOV_SVAL(IOV_PCIEREG): +- si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configaddr), ~0, +- int_val); +- si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configdata), ~0, +- int_val2); +- break; +- +- case IOV_GVAL(IOV_PCIEREG): +- si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configaddr), ~0, +- int_val); +- int_val = si_corereg(bus->sih, bus->sih->buscoreidx, +- OFFSETOF(sbpcieregs_t, configdata), 0, 0); +- bcopy(&int_val, arg, sizeof(int_val)); +- break; +- +- case IOV_GVAL(IOV_BAR0_SECWIN_REG): +- { +- uint32 cur_base, base; +- uchar *bar0; +- volatile uint32 *offset; +- /* set the bar0 secondary window to this */ +- /* write the register value */ +- cur_base = dhdpcie_bus_cfg_read_dword(bus, PCIE2_BAR0_CORE2_WIN, sizeof(uint)); +- base = int_val & 0xFFFFF000; +- dhdpcie_bus_cfg_write_dword(bus, PCIE2_BAR0_CORE2_WIN, sizeof(uint32), base); +- bar0 = (uchar *)bus->regs; +- offset = (uint32 *)(bar0 + 0x4000 + (int_val & 0xFFF)); +- int_val = *offset; +- bcopy(&int_val, arg, sizeof(int_val)); +- dhdpcie_bus_cfg_write_dword(bus, PCIE2_BAR0_CORE2_WIN, sizeof(uint32), cur_base); +- } +- break; +- case IOV_SVAL(IOV_BAR0_SECWIN_REG): +- { +- uint32 cur_base, base; +- uchar *bar0; +- volatile uint32 *offset; +- /* set the bar0 secondary window to this */ +- /* write the register value */ +- cur_base = dhdpcie_bus_cfg_read_dword(bus, PCIE2_BAR0_CORE2_WIN, sizeof(uint)); +- base = int_val & 0xFFFFF000; +- dhdpcie_bus_cfg_write_dword(bus, PCIE2_BAR0_CORE2_WIN, sizeof(uint32), base); +- bar0 = (uchar *)bus->regs; +- offset = (uint32 *)(bar0 + 0x4000 + (int_val & 0xFFF)); +- *offset = int_val2; +- bcopy(&int_val2, arg, val_size); +- dhdpcie_bus_cfg_write_dword(bus, PCIE2_BAR0_CORE2_WIN, sizeof(uint32), cur_base); +- } +- break; +- +- case IOV_SVAL(IOV_PCIECOREREG): +- si_corereg(bus->sih, bus->sih->buscoreidx, int_val, ~0, int_val2); +- break; +- case IOV_GVAL(IOV_SBREG): +- { +- sdreg_t sdreg; +- uint32 addr, coreidx; +- +- bcopy(params, &sdreg, sizeof(sdreg)); +- +- addr = sdreg.offset; +- coreidx = (addr & 0xF000) >> 12; +- +- int_val = si_corereg(bus->sih, coreidx, (addr & 0xFFF), 0, 0); +- bcopy(&int_val, arg, sizeof(int32)); +- break; +- } +- +- case IOV_SVAL(IOV_SBREG): +- { +- sdreg_t sdreg; +- uint32 addr, coreidx; +- +- bcopy(params, &sdreg, sizeof(sdreg)); +- +- addr = sdreg.offset; +- coreidx = (addr & 0xF000) >> 12; +- +- si_corereg(bus->sih, coreidx, (addr & 0xFFF), ~0, sdreg.value); +- +- break; +- } +- +- +- case IOV_GVAL(IOV_PCIECOREREG): +- int_val = si_corereg(bus->sih, bus->sih->buscoreidx, int_val, 0, 0); +- bcopy(&int_val, arg, sizeof(int_val)); +- break; +- +- case IOV_SVAL(IOV_PCIECFGREG): +- OSL_PCI_WRITE_CONFIG(bus->osh, int_val, 4, int_val2); +- break; +- +- case IOV_GVAL(IOV_PCIECFGREG): +- int_val = OSL_PCI_READ_CONFIG(bus->osh, int_val, 4); +- bcopy(&int_val, arg, sizeof(int_val)); +- break; +- + case IOV_SVAL(IOV_PCIE_LPBK): + bcmerror = dhdpcie_bus_lpback_req(bus, int_val); + break; diff --git a/Patches/Linux_CVEs/CVE-2017-0451/0.patch b/Patches/Linux_CVEs/CVE-2017-0451/0.patch new file mode 100644 index 00000000..49e142d6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0451/0.patch @@ -0,0 +1,101 @@ +From 59f55cd40b5f44941afc78b78e5bf81ad3dd723e Mon Sep 17 00:00:00 2001 +From: Josh Kirsch +Date: Mon, 2 May 2016 14:55:04 -0700 +Subject: drivers: soc: Add buffer overflow check for svc send request + +Add buffer overflow check in voice_svc_send_req. + +CRs-fixed: 1010081 +Change-Id: I4ae703334b0cf04f327b392bc9cd6febd4ad32f2 +Signed-off-by: Josh Kirsch +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 46 +++++++++++++++++++++++++----------- + 1 file changed, 32 insertions(+), 14 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index 23b8292..67c58d1 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, The 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 +@@ -188,7 +188,8 @@ static int voice_svc_send_req(struct voice_svc_cmd_request *apr_request, + int ret = 0; + void *apr_handle = NULL; + struct apr_data *aprdata = NULL; +- uint32_t user_payload_size = 0; ++ uint32_t user_payload_size; ++ uint32_t payload_size; + + pr_debug("%s\n", __func__); + +@@ -200,15 +201,19 @@ static int voice_svc_send_req(struct voice_svc_cmd_request *apr_request, + } + + user_payload_size = apr_request->payload_size; ++ payload_size = sizeof(struct apr_data) + user_payload_size; + +- aprdata = kmalloc(sizeof(struct apr_data) + user_payload_size, +- GFP_KERNEL); +- +- if (aprdata == NULL) { +- pr_err("%s: aprdata kmalloc failed.\n", __func__); +- +- ret = -ENOMEM; ++ if (payload_size <= user_payload_size) { ++ pr_err("%s: invalid payload size ( 0x%x ).\n", ++ __func__, user_payload_size); ++ ret = -EINVAL; + goto done; ++ } else { ++ aprdata = kmalloc(payload_size, GFP_KERNEL); ++ if (aprdata == NULL) { ++ ret = -ENOMEM; ++ goto done; ++ } + } + + voice_svc_update_hdr(apr_request, aprdata); +@@ -388,18 +393,31 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + + switch (cmd) { + case MSG_REGISTER: +- ret = process_reg_cmd( ++ if (count >= ++ (sizeof(struct voice_svc_register) + ++ sizeof(*data))) { ++ ret = process_reg_cmd( + (struct voice_svc_register *)data->payload, prtd); +- if (!ret) +- ret = count; +- ++ if (!ret) ++ ret = count; ++ } else { ++ pr_err("%s: invalid payload size\n", __func__); ++ ret = -EINVAL; ++ goto done; ++ } + break; + case MSG_REQUEST: ++ if (count >= (sizeof(struct voice_svc_cmd_request) + ++ sizeof(*data))) { + ret = voice_svc_send_req( + (struct voice_svc_cmd_request *)data->payload, prtd); + if (!ret) + ret = count; +- ++ } else { ++ pr_err("%s: invalid payload size\n", __func__); ++ ret = -EINVAL; ++ goto done; ++ } + break; + default: + pr_debug("%s: Invalid command: %u\n", __func__, cmd); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0451/1.patch b/Patches/Linux_CVEs/CVE-2017-0451/1.patch new file mode 100644 index 00000000..f16c4d87 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0451/1.patch @@ -0,0 +1,106 @@ +From 35346beb2d8882115f698ab22a96803552b5c57e Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Tue, 4 Oct 2016 12:24:28 -0700 +Subject: drivers: soc: add size checks and update log messages + +Add size checks to validate minimum size is met. Update log messages +to include only relevant information to ensure logs are accurate and +useful. + +Change-Id: Idf76a7d964ec6989a0474d49895e54103f17938b +CRs-fixed: 1073129 +Signed-off-by: Siena Richard +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 41 ++++++++++++++++++++++++++---------- + 1 file changed, 30 insertions(+), 11 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index 67c58d1..50dd925 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -223,8 +223,8 @@ static int voice_svc_send_req(struct voice_svc_cmd_request *apr_request, + } else if (!strcmp(apr_request->svc_name, VOICE_SVC_MVM_STR)) { + apr_handle = prtd->apr_q6_mvm; + } else { +- pr_err("%s: Invalid service %s\n", __func__, +- apr_request->svc_name); ++ pr_err("%s: Invalid service %.*s\n", __func__, ++ MAX_APR_SERVICE_NAME_LEN, apr_request->svc_name); + + ret = -EINVAL; + goto done; +@@ -338,8 +338,8 @@ static int process_reg_cmd(struct voice_svc_register *apr_reg_svc, + svc = VOICE_SVC_CVS_STR; + handle = &prtd->apr_q6_cvs; + } else { +- pr_err("%s: Invalid Service: %s\n", __func__, +- apr_reg_svc->svc_name); ++ pr_err("%s: Invalid Service: %.*s\n", __func__, ++ MAX_APR_SERVICE_NAME_LEN, apr_reg_svc->svc_name); + ret = -EINVAL; + goto done; + } +@@ -365,7 +365,17 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + + pr_debug("%s\n", __func__); + +- data = kmalloc(count, GFP_KERNEL); ++ /* ++ * Check if enough memory is allocated to parse the message type. ++ * Will check there is enough to hold the payload later. ++ */ ++ if (count >= sizeof(struct voice_svc_write_msg)) { ++ data = kmalloc(count, GFP_KERNEL); ++ } else { ++ pr_debug("%s: invalid data size\n", __func__); ++ ret = -EINVAL; ++ goto done; ++ } + + if (data == NULL) { + pr_err("%s: data kmalloc failed.\n", __func__); +@@ -383,7 +393,7 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + } + + cmd = data->msg_type; +- prtd = (struct voice_svc_prvt *)file->private_data; ++ prtd = (struct voice_svc_prvt *) file->private_data; + if (prtd == NULL) { + pr_err("%s: prtd is NULL\n", __func__); + +@@ -393,9 +403,13 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + + switch (cmd) { + case MSG_REGISTER: +- if (count >= +- (sizeof(struct voice_svc_register) + +- sizeof(*data))) { ++ /* ++ * Check that count reflects the expected size to ensure ++ * sufficient memory was allocated. Since voice_svc_register ++ * has a static size, this should be exact. ++ */ ++ if (count == (sizeof(struct voice_svc_write_msg) + ++ sizeof(struct voice_svc_register))) { + ret = process_reg_cmd( + (struct voice_svc_register *)data->payload, prtd); + if (!ret) +@@ -407,8 +421,13 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + } + break; + case MSG_REQUEST: +- if (count >= (sizeof(struct voice_svc_cmd_request) + +- sizeof(*data))) { ++ /* ++ * Check that count reflects the expected size to ensure ++ * sufficient memory was allocated. Since voice_svc_cmd_request ++ * has a variable size, check the minimum value count must be. ++ */ ++ if (count >= (sizeof(struct voice_svc_write_msg) + ++ sizeof(struct voice_svc_cmd_request))) { + ret = voice_svc_send_req( + (struct voice_svc_cmd_request *)data->payload, prtd); + if (!ret) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0452/0.patch b/Patches/Linux_CVEs/CVE-2017-0452/0.patch new file mode 100644 index 00000000..8ad73f60 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0452/0.patch @@ -0,0 +1,55 @@ +From 4fa7499742c56c7f7064c9dc14c3a34f4be38851 Mon Sep 17 00:00:00 2001 +From: Ariel Yin +Date: Fri, 13 Jan 2017 13:58:56 -0800 +Subject: [PATCH] msm: vidc: WARN_ON() reveals fuction addresses + +There is a security vulnerability where function addresses are +printed in kernel message if WARN_ON() is invoked implicitly. +WARN_ON() call is made explicit to avoid this issue. + +Bug: 32873615 +CRs-Fixed: 1093693 +Change-Id: If75581803adf62cb9bda3784ad1d4f4088e0d797 +Signed-off-by: Sanjay Singh +Signed-off-by: Biswajit Paul +--- + drivers/media/platform/msm/vidc/msm_vidc.c | 3 ++- + drivers/media/platform/msm/vidc/venus_hfi.c | 4 ++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c +index 0f55f3254a43b..b90ebc11d527a 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc.c +@@ -1405,7 +1405,8 @@ static void cleanup_instance(struct msm_vidc_inst *inst) + debugfs_remove_recursive(inst->debugfs_root); + + mutex_lock(&inst->pending_getpropq.lock); +- WARN_ON(!list_empty(&inst->pending_getpropq.list)); ++ WARN_ON(!list_empty(&inst->pending_getpropq.list) ++ && (msm_vidc_debug & VIDC_INFO)); + mutex_unlock(&inst->pending_getpropq.lock); + } + } +diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c +index a7a391f9c8d30..6f6d79a1f6946 100644 +--- a/drivers/media/platform/msm/vidc/venus_hfi.c ++++ b/drivers/media/platform/msm/vidc/venus_hfi.c +@@ -261,7 +261,7 @@ static int venus_hfi_acquire_regulator(struct regulator_info *rinfo) + rinfo->name); + } + } +- WARN_ON(!regulator_is_enabled(rinfo->regulator)); ++ WARN_ON(!regulator_is_enabled(rinfo->regulator) && (msm_vidc_debug & VIDC_INFO)); + return rc; + } + +@@ -3954,7 +3954,7 @@ static int venus_hfi_disable_regulator(struct regulator_info *rinfo) + disable_regulator_failed: + + /* Bring attention to this issue */ +- WARN_ON(1); ++ WARN_ON(msm_vidc_debug & VIDC_INFO); + return rc; + } + diff --git a/Patches/Linux_CVEs/CVE-2017-0453/0.patch b/Patches/Linux_CVEs/CVE-2017-0453/0.patch new file mode 100644 index 00000000..9caa26bc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0453/0.patch @@ -0,0 +1,38 @@ +From 05af1f34723939f477cb7d25adb320d016d68513 Mon Sep 17 00:00:00 2001 +From: Manjeet Singh +Date: Tue, 27 Dec 2016 17:48:37 +0530 +Subject: qcacld-2.0: Add buf len check in wlan_hdd_cfg80211_testmode + +In __wlan_hdd_cfg80211_testmode API no checks are in place that +ensure that buflen is smaller or equal the size of the stack +variable hb_params. Hence, the vos_mem_copy() call can overflow +stack memory. + +Add buf len check to avoid stack overflow + +CRs-Fixed: 1105085 +Change-Id: I6af6a74cc38ebce3337120adcf7e9595f22d3d8c +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 1ad4ef2..54605a2 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -26336,6 +26336,12 @@ static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, + (hb_params_temp->params.lphbTcpParamReq.timePeriodSec == 0)) + return -EINVAL; + ++ if (buf_len > sizeof(*hb_params)) { ++ hddLog(LOGE, FL("buf_len=%d exceeded hb_params size limit"), ++ buf_len); ++ return -ERANGE; ++ } ++ + hb_params = (tSirLPHBReq *)vos_mem_malloc(sizeof(tSirLPHBReq)); + if (NULL == hb_params) { + hddLog(LOGE, FL("Request Buffer Alloc Fail")); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0453/1.patch b/Patches/Linux_CVEs/CVE-2017-0453/1.patch new file mode 100644 index 00000000..adf06bec --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0453/1.patch @@ -0,0 +1,38 @@ +From dd88a6eb22a0df94c6414d1fe815d61e9dfb0a34 Mon Sep 17 00:00:00 2001 +From: Manjeet Singh +Date: Fri, 10 Feb 2017 19:03:38 +0530 +Subject: wlan: Add buf len check in wlan_hdd_cfg80211_testmode + +In __wlan_hdd_cfg80211_testmode API no checks are in place that +ensure that buflen is smaller or equal the size of the stack +variable hb_params. Hence, the vos_mem_copy() call can overflow +stack memory. + +Add buf len check to avoid stack overflow. + +CRs-Fixed: 1105085 +Change-Id: I6af6a74cc38ebce3337120adcf7e9595f22d3d8c +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 35e33db..10d3da4 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -19275,6 +19275,12 @@ static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, void *data, int len + buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]); + buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]); + ++ if (buf_len > sizeof(*hb_params)) { ++ hddLog(LOGE, FL("buf_len=%d exceeded hb_params size limit"), ++ buf_len); ++ return -ERANGE; ++ } ++ + hb_params_temp =(tSirLPHBReq *)buf; + if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID) && + (hb_params_temp->params.lphbTcpParamReq.timePeriodSec == 0)) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0454/0.patch b/Patches/Linux_CVEs/CVE-2017-0454/0.patch new file mode 100644 index 00000000..af327397 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0454/0.patch @@ -0,0 +1,119 @@ +From cb0701a2f99fa19f01fbd4249bda9a8eadb0241f Mon Sep 17 00:00:00 2001 +From: kunleiz +Date: Thu, 22 Dec 2016 18:03:37 +0800 +Subject: ASoC: msm: qdspv2: add mutex lock when access output buffer length + +Add mutex protection to avoid access output_len in parallel. + +CRs-Fixed: 1104067 +Change-Id: I4e17258e2abee9cd68152f4b79520b00003aa80d +Signed-off-by: kunleiz +--- + drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +index 940fd08..9889d9c 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -29,6 +29,8 @@ struct q6audio_effects { + struct audio_client *ac; + struct msm_hwacc_effects_config config; + ++ struct mutex lock; ++ + atomic_t in_count; + atomic_t out_count; + +@@ -230,8 +232,11 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + uint32_t idx = 0; + uint32_t size = 0; + ++ mutex_lock(&effects->lock); ++ + if (!effects->started) { + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + +@@ -241,11 +246,13 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + if (!rc) { + pr_err("%s: write wait_event_timeout\n", __func__); + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + if (!atomic_read(&effects->out_count)) { + pr_err("%s: pcm stopped out_count 0\n", __func__); + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + +@@ -255,6 +262,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + copy_from_user(bufptr, (void *)arg, + effects->config.buf_cfg.output_len)) { + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + rc = q6asm_write(effects->ac, +@@ -262,6 +270,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + 0, 0, NO_TIMESTAMP); + if (rc < 0) { + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + atomic_dec(&effects->out_count); +@@ -269,6 +278,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + pr_err("%s: AUDIO_EFFECTS_WRITE: Buffer dropped\n", + __func__); + } ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_EFFECTS_READ: { +@@ -466,6 +476,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, + break; + } + case AUDIO_EFFECTS_SET_BUF_LEN: { ++ mutex_lock(&effects->lock); + if (copy_from_user(&effects->config.buf_cfg, (void *)arg, + sizeof(effects->config.buf_cfg))) { + pr_err("%s: copy from user for AUDIO_EFFECTS_SET_BUF_LEN failed\n", +@@ -475,6 +486,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, + pr_debug("%s: write buf len: %d, read buf len: %d\n", + __func__, effects->config.buf_cfg.output_len, + effects->config.buf_cfg.input_len); ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_EFFECTS_GET_BUF_AVAIL: { +@@ -719,6 +731,7 @@ static int audio_effects_release(struct inode *inode, struct file *file) + } + q6asm_audio_client_free(effects->ac); + ++ mutex_destroy(&effects->lock); + kfree(effects); + + pr_debug("%s: close session success\n", __func__); +@@ -749,6 +762,7 @@ static int audio_effects_open(struct inode *inode, struct file *file) + + init_waitqueue_head(&effects->read_wait); + init_waitqueue_head(&effects->write_wait); ++ mutex_init(&effects->lock); + + effects->opened = 0; + effects->started = 0; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0457/0.patch b/Patches/Linux_CVEs/CVE-2017-0457/0.patch new file mode 100644 index 00000000..886cd9c8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0457/0.patch @@ -0,0 +1,33 @@ +From c257f35acc3841f7b99730f01ba834c0575030de Mon Sep 17 00:00:00 2001 +From: Biswajit Paul +Date: Fri, 2 Dec 2016 12:54:53 -0800 +Subject: [PATCH] msm: ADSPRPC: Buffer length truncated while validation + +The buffer length that is being used to validate gets truncated +due to it being assigned to wrong type causing invalid memory +to be accessed when the actual buffer length is used to copy +user buffer contents. + +Bug: 31695439 +CRs-Fixed: 1086123 +Change-Id: If04dee27b8bae04eef7455773d9f4327fd008a21 +Signed-off-by: Sathish Ambley +Signed-off-by: Biswajit Paul +--- + drivers/char/adsprpc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c +index f99855c0cacf5..53396b7839497 100644 +--- a/drivers/char/adsprpc.c ++++ b/drivers/char/adsprpc.c +@@ -719,7 +719,8 @@ static int get_page_list(uint32_t kernel, struct smq_invoke_ctx *ctx) + pgstart->size = obuf->size; + for (i = 0; i < inbufs + outbufs; ++i) { + void *buf; +- int len, num; ++ int num; ++ ssize_t len; + + list[i].num = 0; + list[i].pgidx = 0; diff --git a/Patches/Linux_CVEs/CVE-2017-0457/1.patch b/Patches/Linux_CVEs/CVE-2017-0457/1.patch new file mode 100644 index 00000000..fe0e0e97 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0457/1.patch @@ -0,0 +1,68 @@ +From 6f6ce85df80c31048863cd31349e86277d89ff36 Mon Sep 17 00:00:00 2001 +From: Biswajit Paul +Date: Tue, 13 Dec 2016 15:27:30 -0800 +Subject: [PATCH] msm: ADSPRPC: Buffer length to be copied is truncated + +The buffer length that is being used to allocate gets truncated +due to it being assigned to wrong type causing a much smaller +buffer to be allocated than what is required for copying. + +Bug: 31695439 +CRs-Fixed: 1100695 +Change-Id: I30818acd42bd282837c7c7aa16d56d3b95d4dfe7 +Signed-off-by: Sathish Ambley +Signed-off-by: Biswajit Paul +--- + drivers/char/adsprpc.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c +index a9c537b543122..f99855c0cacf5 100644 +--- a/drivers/char/adsprpc.c ++++ b/drivers/char/adsprpc.c +@@ -833,9 +833,9 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx, + void *args; + remote_arg_t *pra = ctx->pra; + remote_arg_t *rpra = ctx->rpra; +- ssize_t rlen, used, size; ++ ssize_t rlen, used, size, copylen = 0; + uint32_t sc = ctx->sc, start; +- int i, inh, bufs = 0, err = 0, oix, copylen = 0; ++ int i, inh, bufs = 0, err = 0, oix; + int inbufs = REMOTE_SCALARS_INBUFS(sc); + int outbufs = REMOTE_SCALARS_OUTBUFS(sc); + int cid = ctx->fdata->cid; +@@ -884,13 +884,23 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx, + /* calculate len requreed for copying */ + for (oix = 0; oix < inbufs + outbufs; ++oix) { + int i = ctx->overps[oix]->raix; ++ uintptr_t mstart, mend; ++ + if (!pra[i].buf.len) + continue; + if (list[i].num) + continue; + if (ctx->overps[oix]->offset == 0) + copylen = ALIGN(copylen, BALIGN); +- copylen += ctx->overps[oix]->mend - ctx->overps[oix]->mstart; ++ mstart = ctx->overps[oix]->mstart; ++ mend = ctx->overps[oix]->mend; ++ VERIFY(err, (mend - mstart) <= LONG_MAX); ++ if (err) ++ goto bail; ++ copylen += mend - mstart; ++ VERIFY(err, copylen >= 0); ++ if (err) ++ goto bail; + } + + /* alocate new buffer */ +@@ -916,7 +926,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx, + /* copy non ion buffers */ + for (oix = 0; oix < inbufs + outbufs; ++oix) { + int i = ctx->overps[oix]->raix; +- int mlen = ctx->overps[oix]->mend - ctx->overps[oix]->mstart; ++ ssize_t mlen = ctx->overps[oix]->mend - ctx->overps[oix]->mstart; + if (!pra[i].buf.len) + continue; + if (list[i].num) diff --git a/Patches/Linux_CVEs/CVE-2017-0457/2.patch b/Patches/Linux_CVEs/CVE-2017-0457/2.patch new file mode 100644 index 00000000..b5f7562c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0457/2.patch @@ -0,0 +1,57 @@ +From f6e21d2a3778bcbbef7320ffbf31631d76679175 Mon Sep 17 00:00:00 2001 +From: Wei Wang +Date: Fri, 13 Jan 2017 20:00:07 -0800 +Subject: [PATCH] msm: ADSPRPC: Buffer length to be copied is truncated + +The buffer length that is being used to allocate gets truncated +due to it being assigned to wrong type causing a much smaller +buffer to be allocated than what is required for copying. + +Bug: 31695439 +CRs-Fixed: 1100695 +Change-Id: I30818acd42bd282837c7c7aa16d56d3b95d4dfe7 +Signed-off-by: Sathish Ambley +Signed-off-by: Biswajit Paul +Signed-off-by: Wei Wang +--- + drivers/char/adsprpc.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c +index 23e1e8b7d04a4..30a9bf32d0801 100644 +--- a/drivers/char/adsprpc.c ++++ b/drivers/char/adsprpc.c +@@ -972,6 +972,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) + /* calculate len requreed for copying */ + for (oix = 0; oix < inbufs + outbufs; ++oix) { + int i = ctx->overps[oix]->raix; ++ uintptr_t mstart, mend; + ssize_t len = lpra[i].buf.len; + if (!len) + continue; +@@ -979,7 +980,15 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) + continue; + if (ctx->overps[oix]->offset == 0) + copylen = ALIGN(copylen, BALIGN); +- copylen += ctx->overps[oix]->mend - ctx->overps[oix]->mstart; ++ mstart = ctx->overps[oix]->mstart; ++ mend = ctx->overps[oix]->mend; ++ VERIFY(err, (mend - mstart) <= LONG_MAX); ++ if (err) ++ goto bail; ++ copylen += mend - mstart; ++ VERIFY(err, copylen >= 0); ++ if (err) ++ goto bail; + } + ctx->used = copylen; + +@@ -1044,7 +1053,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) + for (oix = 0; oix < inbufs + outbufs; ++oix) { + int i = ctx->overps[oix]->raix; + struct fastrpc_mmap *map = ctx->maps[i]; +- int mlen = ctx->overps[oix]->mend - ctx->overps[oix]->mstart; ++ ssize_t mlen = ctx->overps[oix]->mend - ctx->overps[oix]->mstart; + uint64_t buf; + ssize_t len = lpra[i].buf.len; + if (!len) diff --git a/Patches/Linux_CVEs/CVE-2017-0458/0.patch b/Patches/Linux_CVEs/CVE-2017-0458/0.patch new file mode 100644 index 00000000..03b65c5d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0458/0.patch @@ -0,0 +1,62 @@ +From eba46cb98431ba1d7a6bd859f26f6ad03f1bf4d4 Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Tue, 15 Nov 2016 14:55:35 -0800 +Subject: msm: camera: eeprom: Validate the power setting size + +Validate the power setting size before copying. +If userspace sends a value which is greater than +MAX_POWER_CONFIG, then the driver accesses unintended memory. +This change will fix the issue. + +Crs-Fixed: 1089433 +Signed-off-by: Rajesh Bondugula +Change-Id: Iaaa6f5b3c1c2ac5b5b38b3ac407d6ae394bba780 +--- + .../msm/camera_v2/sensor/eeprom/msm_eeprom.c | 24 +++++++++------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +index 037e8b5..dd2f919 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +@@ -1409,6 +1409,16 @@ static int eeprom_init_config32(struct msm_eeprom_ctrl_t *e_ctrl, + + power_info = &(e_ctrl->eboard_info->power_info); + ++ if ((power_setting_array32->size > MAX_POWER_CONFIG) || ++ (power_setting_array32->size_down > MAX_POWER_CONFIG) || ++ (!power_setting_array32->size) || ++ (!power_setting_array32->size_down)) { ++ pr_err("%s:%d invalid power setting size=%d size_down=%d\n", ++ __func__, __LINE__, power_setting_array32->size, ++ power_setting_array32->size_down); ++ rc = -EINVAL; ++ goto free_mem; ++ } + msm_eeprom_copy_power_settings_compat( + power_setting_array, + power_setting_array32); +@@ -1423,20 +1433,6 @@ static int eeprom_init_config32(struct msm_eeprom_ctrl_t *e_ctrl, + power_info->power_down_setting_size = + power_setting_array->size_down; + +- if ((power_info->power_setting_size > +- MAX_POWER_CONFIG) || +- (power_info->power_down_setting_size > +- MAX_POWER_CONFIG) || +- (!power_info->power_down_setting_size) || +- (!power_info->power_setting_size)) { +- rc = -EINVAL; +- pr_err("%s:%d Invalid power setting size :%d, %d\n", +- __func__, __LINE__, +- power_info->power_setting_size, +- power_info->power_down_setting_size); +- goto free_mem; +- } +- + if (e_ctrl->i2c_client.cci_client) { + e_ctrl->i2c_client.cci_client->i2c_freq_mode = + cdata32->cfg.eeprom_info.i2c_freq_mode; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0459/0.patch b/Patches/Linux_CVEs/CVE-2017-0459/0.patch new file mode 100644 index 00000000..87ce8587 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0459/0.patch @@ -0,0 +1,84 @@ +From ffacf6e2dc41b6063c3564791ed7a2f903e7e3b7 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Wed, 30 Nov 2016 14:41:24 -0800 +Subject: msm: ipa: fix the potential heap overflow on wan-driver + +Add the check on rmnet_ipa3_set_tether_client_pipe API +to make sure not accessing move than QMI_IPA_MAX_PIPES_V01 +entries when user-space module compromised. + +Change-Id: I59d39c7e5743dfea17853b6c4709605d4ebae962 +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c | 19 ++++++++++++++++++- + drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 17 +++++++++++++++++ + 2 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +index f81d637..2c43fc52 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +@@ -2507,7 +2507,7 @@ int rmnet_ipa_set_data_quota(struct wan_ioctl_set_data_quota *data) + * + * Return codes: + * 0: Success +- * -EFAULT: Invalid interface name provided ++ * -EFAULT: Invalid src/dst pipes provided + * other: See ipa_qmi_set_data_quota + */ + int rmnet_ipa_set_tether_client_pipe( +@@ -2515,6 +2515,23 @@ int rmnet_ipa_set_tether_client_pipe( + { + int number, i; + ++ /* error checking if ul_src_pipe_len valid or not*/ ++ if (data->ul_src_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->ul_src_pipe_len < 0) { ++ IPAWANERR("UL src pipes %d exceeding max %d\n", ++ data->ul_src_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ /* error checking if dl_dst_pipe_len valid or not*/ ++ if (data->dl_dst_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->dl_dst_pipe_len < 0) { ++ IPAWANERR("DL dst pipes %d exceeding max %d\n", ++ data->dl_dst_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ + IPAWANDBG("client %d, UL %d, DL %d, reset %d\n", + data->ipa_client, + data->ul_src_pipe_len, +diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +index 4ed2728..78187c9 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +@@ -2607,6 +2607,23 @@ int rmnet_ipa3_set_tether_client_pipe( + { + int number, i; + ++ /* error checking if ul_src_pipe_len valid or not*/ ++ if (data->ul_src_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->ul_src_pipe_len < 0) { ++ IPAWANERR("UL src pipes %d exceeding max %d\n", ++ data->ul_src_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ /* error checking if dl_dst_pipe_len valid or not*/ ++ if (data->dl_dst_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->dl_dst_pipe_len < 0) { ++ IPAWANERR("DL dst pipes %d exceeding max %d\n", ++ data->dl_dst_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ + IPAWANDBG("client %d, UL %d, DL %d, reset %d\n", + data->ipa_client, + data->ul_src_pipe_len, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0459/1.patch b/Patches/Linux_CVEs/CVE-2017-0459/1.patch new file mode 100644 index 00000000..6196e87f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0459/1.patch @@ -0,0 +1,55 @@ +From b4e374926ddc325840cda704aea1eb0c49d7f0e3 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Wed, 30 Nov 2016 14:41:24 -0800 +Subject: msm: ipa: fix the potential heap overflow on wan-driver + +Add the check on rmnet_ipa3_set_tether_client_pipe API +to make sure not accessing move than QMI_IPA_MAX_PIPES_V01 +entries when user-space module compromised. + +Change-Id: I59d39c7e5743dfea17853b6c4709605d4ebae962 +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/rmnet_ipa.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/msm/ipa/rmnet_ipa.c b/drivers/platform/msm/ipa/rmnet_ipa.c +index ddae8c5..c274ee1 100644 +--- a/drivers/platform/msm/ipa/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/rmnet_ipa.c +@@ -2426,7 +2426,7 @@ int rmnet_ipa_set_data_quota(struct wan_ioctl_set_data_quota *data) + * + * Return codes: + * 0: Success +- * -EFAULT: Invalid interface name provided ++ * -EFAULT: Invalid src/dst pipes provided + * other: See ipa_qmi_set_data_quota + */ + int rmnet_ipa_set_tether_client_pipe( +@@ -2434,6 +2434,23 @@ int rmnet_ipa_set_tether_client_pipe( + { + int number, i; + ++ /* error checking if ul_src_pipe_len valid or not*/ ++ if (data->ul_src_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->ul_src_pipe_len < 0) { ++ IPAWANERR("UL src pipes %d exceeding max %d\n", ++ data->ul_src_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ /* error checking if dl_dst_pipe_len valid or not*/ ++ if (data->dl_dst_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->dl_dst_pipe_len < 0) { ++ IPAWANERR("DL dst pipes %d exceeding max %d\n", ++ data->dl_dst_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ + IPAWANDBG("client %d, UL %d, DL %d, reset %d\n", + data->ipa_client, + data->ul_src_pipe_len, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0460/0.patch b/Patches/Linux_CVEs/CVE-2017-0460/0.patch new file mode 100644 index 00000000..b74435bc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0460/0.patch @@ -0,0 +1,42 @@ +From 3d63c530096ccd118ab7078c7b9f93c040f803bd Mon Sep 17 00:00:00 2001 +From: Subash Abhinov Kasiviswanathan +Date: Thu, 12 Jan 2017 22:09:16 -0700 +Subject: [PATCH] net: rmnet_data: Fix incorrect netlink handling + +rmnet_data netlink handler currently does not check for the +incoming process pid and instead just loops back the pid. +A malicious root user could potentially send a message with +source pid 0 and this could cause rmnet_data to loop the message +back till an out of memory situation occurs. + +rmnet_data also does not check for the message length of the +incoming netlink messages and instead casts the netlink message +without checking for the boundary. + +Fix these two scenarios by adding the pid and message length checks +respectively. + +Bug: 31252965 +CRs-Fixed: 1098801 +Change-Id: I172c1a7112e67e82959b397af7ddfd963d819bdc +Signed-off-by: Subash Abhinov Kasiviswanathan +--- + net/rmnet_data/rmnet_data_config.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/rmnet_data/rmnet_data_config.c b/net/rmnet_data/rmnet_data_config.c +index f6653588c023d..d47389806161e 100644 +--- a/net/rmnet_data/rmnet_data_config.c ++++ b/net/rmnet_data/rmnet_data_config.c +@@ -529,6 +529,11 @@ void rmnet_config_netlink_msg_handler(struct sk_buff *skb) + nlmsg_header = (struct nlmsghdr *) skb->data; + rmnet_header = (struct rmnet_nl_msg_s *) nlmsg_data(nlmsg_header); + ++ if (!nlmsg_header->nlmsg_pid || ++ (nlmsg_header->nlmsg_len < sizeof(struct nlmsghdr) + ++ sizeof(struct rmnet_nl_msg_s))) ++ return; ++ + LOGL("Netlink message pid=%d, seq=%d, length=%d, rmnet_type=%d", + nlmsg_header->nlmsg_pid, + nlmsg_header->nlmsg_seq, diff --git a/Patches/Linux_CVEs/CVE-2017-0461/0.patch b/Patches/Linux_CVEs/CVE-2017-0461/0.patch new file mode 100644 index 00000000..7c84dc2c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0461/0.patch @@ -0,0 +1,53 @@ +From ce5d6f84420a2e6ca6aad6b866992970dd313a65 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Mon, 12 Dec 2016 18:45:32 -0800 +Subject: qcacld-2.0: Fix array out-of-bounds & integer underflow in + _iw_set_genie + +'wrqu->data.length' holds the total number of IE data buffer. +Add a check to make sure the number of remaining data to be read is +greater than or equal to IE length. + +Also, advance the buffer pointer to point to the next element only +if next element is present. + +Change-Id: Ic60f3e0650f365955dab4099eb8740e9789e00cc +CRs-Fixed: 1100132 +--- + CORE/HDD/src/wlan_hdd_wext.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c +index 0549c3c..574b1ef 100644 +--- a/CORE/HDD/src/wlan_hdd_wext.c ++++ b/CORE/HDD/src/wlan_hdd_wext.c +@@ -2755,6 +2755,13 @@ static int __iw_set_genie(struct net_device *dev, struct iw_request_info *info, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]", + __func__, elementId, eLen); + ++ if (remLen < eLen) { ++ hddLog(LOGE, "Remaining len: %u less than ie len: %u", ++ remLen, eLen); ++ ret = -EINVAL; ++ goto exit; ++ } ++ + switch ( elementId ) + { + case IE_EID_VENDOR: +@@ -2837,8 +2844,11 @@ static int __iw_set_genie(struct net_device *dev, struct iw_request_info *info, + hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, elementId); + goto exit; + } +- genie += eLen; + remLen -= eLen; ++ ++ /* Move genie only if next element is present */ ++ if (remLen >= 2) ++ genie += eLen; + } + exit: + EXIT(); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0461/1.patch b/Patches/Linux_CVEs/CVE-2017-0461/1.patch new file mode 100644 index 00000000..d893b235 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0461/1.patch @@ -0,0 +1,53 @@ +From 02bd3c61ccb5a68eee42e6cfc59fc8d7120167a2 Mon Sep 17 00:00:00 2001 +From: Pothula Hanumantha Reddy +Date: Wed, 28 Dec 2016 17:55:19 +0530 +Subject: prima: Fix array out-of-bounds & integer underflow in _iw_set_genie + +qcacld-2.0 to prima propagation + +'wrqu->data.length' holds the total number of IE data buffer. +Add a check to make sure the number of remaining data to be read is +greater than or equal to IE length. +Also, advance the buffer pointer to point to the next element only +if next element is present. + +Change-Id: Ic60f3e0650f365955dab4099eb8740e9789e00cc +CRs-Fixed: 1100132 +--- + CORE/HDD/src/wlan_hdd_wext.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c +index 07d2e6b..91bc35c 100644 +--- a/CORE/HDD/src/wlan_hdd_wext.c ++++ b/CORE/HDD/src/wlan_hdd_wext.c +@@ -2565,6 +2565,13 @@ static int __iw_set_genie(struct net_device *dev, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]", + __func__, elementId, eLen); + ++ if (remLen < eLen) { ++ hddLog(LOGE, "Remaining len: %u less than ie len: %u", ++ remLen, eLen); ++ ret = -EINVAL; ++ goto exit; ++ } ++ + switch ( elementId ) + { + case IE_EID_VENDOR: +@@ -2647,8 +2654,11 @@ static int __iw_set_genie(struct net_device *dev, + hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, elementId); + goto exit; + } +- genie += eLen; + remLen -= eLen; ++ ++ /* Move genie only if next element is present */ ++ if (remLen >= 2) ++ genie += eLen; + } + + exit: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0462/0.patch b/Patches/Linux_CVEs/CVE-2017-0462/0.patch new file mode 100644 index 00000000..af26ac15 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0462/0.patch @@ -0,0 +1,63 @@ +From eb7b1426279e751b1fc3e86f434dc349945c1ae7 Mon Sep 17 00:00:00 2001 +From: ahmedsh +Date: Wed, 4 Jan 2017 16:00:27 -0500 +Subject: seemp: use local stack mem when encoding params + +Avoid race condition in driver when encoding param by +reading contents from a local copy instead of msg buffer +itself which can be mapped to user space. + +Change-Id: I9f111c078baefca6e6f1fcda30af1044891a3356 +Signed-off-by: Ahmed Sheikh +--- + .../platform/msm/seemp_core/seemp_event_encoder.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/platform/msm/seemp_core/seemp_event_encoder.c b/drivers/platform/msm/seemp_core/seemp_event_encoder.c +index df56a84..36901f5 100644 +--- a/drivers/platform/msm/seemp_core/seemp_event_encoder.c ++++ b/drivers/platform/msm/seemp_core/seemp_event_encoder.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2015, 2017, The 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 +@@ -48,9 +48,15 @@ static void check_param_range(char *section_eq, bool param, + + void encode_seemp_params(struct seemp_logk_blk *blk) + { +- char *s = blk->payload.msg + 1; ++ struct seemp_logk_blk tmp; ++ char *s = 0; ++ char *msg_section_start = 0; ++ char *msg_section_eq = 0; ++ char *msg_s = 0; + +- blk->payload.msg[BLK_MAX_MSG_SZ - 1] = 0; /* zero-terminate */ ++ memcpy(tmp.payload.msg, blk->payload.msg, BLK_MAX_MSG_SZ); ++ s = tmp.payload.msg + 1; ++ tmp.payload.msg[BLK_MAX_MSG_SZ - 1] = 0; /* zero-terminate */ + + while (true) { + char *section_start = s; +@@ -105,8 +111,13 @@ void encode_seemp_params(struct seemp_logk_blk *blk) + } + } + +- encode_seemp_section(section_start, section_eq, s, param, +- numeric, id, numeric_value); ++ msg_section_start = blk->payload.msg + (section_start - ++ tmp.payload.msg); ++ msg_section_eq = blk->payload.msg + (section_eq - ++ tmp.payload.msg); ++ msg_s = blk->payload.msg + (s - tmp.payload.msg); ++ encode_seemp_section(msg_section_start, msg_section_eq, ++ msg_s, param, numeric, id, numeric_value); + + if (*s == 0) + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0463/0.patch b/Patches/Linux_CVEs/CVE-2017-0463/0.patch new file mode 100644 index 00000000..4de1757c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0463/0.patch @@ -0,0 +1,35 @@ +From 955bd7e7ac097bdffbadafab90e5378038fefeb2 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Ramasubramanian +Date: Thu, 15 Dec 2016 08:13:20 -0700 +Subject: net: ipc_router: Register services only on client port + +Allowing services to be registered on a non-client port will cause either +an existing service or a control port to be over-written. This will cause +undefined functional behavior. + +Allow the services to be registered only on client ports. + +CRs-Fixed: 1101792 +Change-Id: If6cfc75e9314204b7b44957f1598a8a2e1a45325 +Signed-off-by: Karthikeyan Ramasubramanian +--- + net/ipc_router/ipc_router_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c +index ee4a873..9c784e8 100644 +--- a/net/ipc_router/ipc_router_core.c ++++ b/net/ipc_router/ipc_router_core.c +@@ -2799,6 +2799,9 @@ int msm_ipc_router_register_server(struct msm_ipc_port *port_ptr, + if (!port_ptr || !name) + return -EINVAL; + ++ if (port_ptr->type != CLIENT_PORT) ++ return -EINVAL; ++ + if (name->addrtype != MSM_IPC_ADDR_NAME) + return -EINVAL; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0464/0.patch b/Patches/Linux_CVEs/CVE-2017-0464/0.patch new file mode 100644 index 00000000..f3f224eb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0464/0.patch @@ -0,0 +1,1101 @@ +From 051597a4fe19fd1292fb7ea2e627d12d1fd2934f Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Fri, 16 Dec 2016 18:32:10 -0800 +Subject: qcacld-2.0: Remove obsolete set/reset ssid hotlist + +Remove obsolete set/reset ssid hotlist. + +Change-Id: Ie6c4a9847f2daa9ba2aebd17f386d584201b86d6 +CRs-Fixed: 1102593 +--- + CORE/HDD/inc/wlan_hdd_cfg80211.h | 20 +- + CORE/HDD/src/wlan_hdd_cfg80211.c | 560 ------------------------------- + CORE/MAC/inc/sirApi.h | 33 -- + CORE/MAC/src/include/sirParams.h | 2 +- + CORE/SERVICES/WMA/wma.c | 219 ------------ + CORE/SME/inc/sme_Api.h | 4 - + CORE/SME/src/sme_common/sme_Api.c | 46 --- + CORE/SYS/legacy/src/utils/src/macTrace.c | 1 - + 8 files changed, 7 insertions(+), 878 deletions(-) + +diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h +index 3e46b3e..9a943af 100644 +--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h ++++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h +@@ -219,10 +219,12 @@ enum qca_nl80211_vendor_subcmds { + /* Start Wifi Memory Dump */ + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP = 63, + QCA_NL80211_VENDOR_SUBCMD_ROAM = 64, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST = 65, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST = 66, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND = 67, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST = 68, ++ ++ /* ++ * APIs corresponding to the sub commands 65-68 are deprecated. ++ * These sub commands are reserved and not supposed to be used ++ * for any other purpose ++ */ + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST = 69, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST = 70, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST = 71, +@@ -333,12 +335,6 @@ enum qca_nl80211_vendor_subcmds_index { + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX, + #endif /* FEATURE_WLAN_EXTSCAN */ + +-#ifdef FEATURE_WLAN_EXTSCAN +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX, +-#endif + /* OCB events */ + QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX, + #ifdef WLAN_FEATURE_MEMDUMP +@@ -802,10 +798,6 @@ enum qca_wlan_vendor_attr_extscan_results + /* Unsigned 32bit value; a EXTSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID, + +- /* EXTSCAN attributes for +- * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND sub-command & +- * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST sub-command +- */ + /* Use attr QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE + * to indicate number of results. + */ +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 532ec5a..4e3e7d4 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1223,14 +1223,6 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE + }, +- [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = { +- .vendor_id = QCA_NL80211_VENDOR_ID, +- .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND +- }, +- [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = { +- .vendor_id = QCA_NL80211_VENDOR_ID, +- .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST +- }, + #endif /* FEATURE_WLAN_EXTSCAN */ + + #ifdef WLAN_FEATURE_LINK_LAYER_STATS +@@ -1307,14 +1299,6 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND + }, +- [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = { +- .vendor_id = QCA_NL80211_VENDOR_ID, +- .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST +- }, +- [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = { +- .vendor_id = QCA_NL80211_VENDOR_ID, +- .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST +- }, + [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = { + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST +@@ -3033,253 +3017,6 @@ static int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + } + + +-/* +- * define short names for the global vendor params +- * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist() +- */ +-#define PARAM_MAX \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +-#define PARAM_REQUEST_ID \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID +-#define PARAMS_LOST_SSID_SAMPLE_SIZE \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE +-#define PARAMS_NUM_SSID \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID +-#define THRESHOLD_PARAM \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM +-#define PARAM_SSID \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID +-#define PARAM_BAND \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND +-#define PARAM_RSSI_LOW \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW +-#define PARAM_RSSI_HIGH \ +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH +- +-/** +- * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list +- * @wiphy: Pointer to wireless phy +- * @wdev: Pointer to wireless device +- * @data: Pointer to data +- * @data_len: Data length +- * +- * Return: 0 on success, negative errno on failure +- */ +-static int +-__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- const void *data, +- int data_len) +-{ +- struct sir_set_ssid_hotlist_request *request; +- struct net_device *dev = wdev->netdev; +- hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); +- hdd_context_t *hdd_ctx = wiphy_priv(wiphy); +- struct nlattr *tb[PARAM_MAX + 1]; +- struct nlattr *tb2[PARAM_MAX + 1]; +- struct nlattr *ssids; +- struct hdd_ext_scan_context *context; +- uint32_t request_id; +- char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1]; +- int ssid_len, ssid_length; +- eHalStatus status; +- int i, rem, retval; +- unsigned long rc; +- +- ENTER(); +- +- if (VOS_FTM_MODE == hdd_get_conparam()) { +- hddLog(LOGE, FL("Command not allowed in FTM mode")); +- return -EINVAL; +- } +- +- retval = wlan_hdd_validate_context(hdd_ctx); +- if (0 != retval) +- return -EINVAL; +- +- if (nla_parse(tb, PARAM_MAX, +- data, data_len, +- wlan_hdd_extscan_config_policy)) { +- hddLog(LOGE, FL("Invalid ATTR")); +- return -EINVAL; +- } +- +- request = vos_mem_malloc(sizeof(*request)); +- if (!request) { +- hddLog(LOGE, FL("vos_mem_malloc failed")); +- return -ENOMEM; +- } +- +- /* Parse and fetch request Id */ +- if (!tb[PARAM_REQUEST_ID]) { +- hddLog(LOGE, FL("attr request id failed")); +- goto fail; +- } +- +- request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]); +- hddLog(LOG1, FL("Request Id %d"), request->request_id); +- +- /* Parse and fetch lost SSID sample size */ +- if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) { +- hddLog(LOGE, FL("attr number of Ssid failed")); +- goto fail; +- } +- request->lost_ssid_sample_size = +- nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]); +- hddLog(LOG1, FL("Lost SSID Sample Size %d"), +- request->lost_ssid_sample_size); +- +- /* Parse and fetch number of hotlist SSID */ +- if (!tb[PARAMS_NUM_SSID]) { +- hddLog(LOGE, FL("attr number of Ssid failed")); +- goto fail; +- } +- request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]); +- hddLog(LOG1, FL("Number of SSID %d"), request->ssid_count); +- +- request->session_id = adapter->sessionId; +- hddLog(LOG1, FL("Session Id (%d)"), request->session_id); +- +- i = 0; +- nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) { +- if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) { +- hddLog(LOGE, +- FL("Too Many SSIDs, %d exceeds %d"), +- i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS); +- break; +- } +- if (nla_parse(tb2, PARAM_MAX, +- nla_data(ssids), nla_len(ssids), +- wlan_hdd_extscan_config_policy)) { +- hddLog(LOGE, FL("nla_parse failed")); +- goto fail; +- } +- +- /* Parse and fetch SSID */ +- if (!tb2[PARAM_SSID]) { +- hddLog(LOGE, FL("attr ssid failed")); +- goto fail; +- } +- ssid_length = nla_strlcpy(ssid_string, +- tb2[PARAM_SSID], +- sizeof(ssid_string)); +- +- /* nla_parse will detect overflow but not underflow */ +- if (0 == ssid_length) { +- hddLog(LOGE, FL("zero ssid length")); +- goto fail; +- } +- hddLog(LOG1, FL("SSID %s"), ssid_string); +- ssid_len = strlen(ssid_string); +- if (ssid_length > SIR_MAC_MAX_SSID_LENGTH) { +- hddLog(LOGE, FL("Invalid ssid length")); +- goto fail; +- } +- memcpy(request->ssids[i].ssid.ssId, ssid_string, ssid_len); +- request->ssids[i].ssid.length = ssid_len; +- +- /* Parse and fetch low RSSI */ +- if (!tb2[PARAM_BAND]) { +- hddLog(LOGE, FL("attr band failed")); +- goto fail; +- } +- request->ssids[i].band = nla_get_u8(tb2[PARAM_BAND]); +- hddLog(LOG1, FL("band %d"), request->ssids[i].band); +- +- /* Parse and fetch low RSSI */ +- if (!tb2[PARAM_RSSI_LOW]) { +- hddLog(LOGE, FL("attr low RSSI failed")); +- goto fail; +- } +- request->ssids[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]); +- hddLog(LOG1, FL("RSSI low %d"), request->ssids[i].rssi_low); +- +- /* Parse and fetch high RSSI */ +- if (!tb2[PARAM_RSSI_HIGH]) { +- hddLog(LOGE, FL("attr high RSSI failed")); +- goto fail; +- } +- request->ssids[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]); +- hddLog(LOG1, FL("RSSI high %d"), request->ssids[i].rssi_high); +- i++; +- } +- +- context = &hdd_ctx->ext_scan_context; +- spin_lock(&hdd_context_lock); +- INIT_COMPLETION(context->response_event); +- context->request_id = request_id = request->request_id; +- spin_unlock(&hdd_context_lock); +- +- status = sme_set_ssid_hotlist(hdd_ctx->hHal, request); +- if (!HAL_STATUS_SUCCESS(status)) { +- hddLog(LOGE, +- FL("sme_set_ssid_hotlist failed(err=%d)"), status); +- goto fail; +- } +- +- vos_mem_free(request); +- +- /* request was sent -- wait for the response */ +- rc = wait_for_completion_timeout(&context->response_event, +- msecs_to_jiffies +- (WLAN_WAIT_TIME_EXTSCAN)); +- if (!rc) { +- hddLog(LOGE, FL("sme_set_ssid_hotlist timed out")); +- retval = -ETIMEDOUT; +- } else { +- spin_lock(&hdd_context_lock); +- if (context->request_id == request_id) +- retval = context->response_status; +- else +- retval = -EINVAL; +- spin_unlock(&hdd_context_lock); +- } +- +- return retval; +- +-fail: +- vos_mem_free(request); +- return -EINVAL; +-} +- +-/* +- * done with short names for the global vendor params +- * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist() +- */ +-#undef PARAM_MAX +-#undef PARAM_REQUEST_ID +-#undef PARAMS_NUM_SSID +-#undef THRESHOLD_PARAM +-#undef PARAM_SSID +-#undef PARAM_BAND +-#undef PARAM_RSSI_LOW +-#undef PARAM_RSSI_HIGH +- +-/** +- * wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list +- * @wiphy: Pointer to wireless phy +- * @wdev: Pointer to wireless device +- * @data: Pointer to data +- * @data_len: Data length +- * +- * Return: 0 on success, negative errno on failure +- */ +-static int +-wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- const void *data, +- int data_len) +-{ +- int ret; +- +- vos_ssr_protect(__func__); +- ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data, +- data_len); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} +- + static int __wlan_hdd_cfg80211_extscan_set_significant_change( + struct wiphy *wiphy, + struct wireless_dev *wdev, +@@ -4632,136 +4369,6 @@ static int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy, + return ret; + } + +-/** +- * __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list +- * @wiphy: Pointer to wireless phy +- * @wdev: Pointer to wireless device +- * @data: Pointer to data +- * @data_len: Data length +- * +- * Return: 0 on success, negative errno on failure +- */ +-static int +-__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- const void *data, +- int data_len) +-{ +- struct sir_set_ssid_hotlist_request *request; +- struct net_device *dev = wdev->netdev; +- hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); +- hdd_context_t *hdd_ctx = wiphy_priv(wiphy); +- struct nlattr *tb[PARAM_MAX + 1]; +- struct hdd_ext_scan_context *context; +- uint32_t request_id; +- eHalStatus status; +- int retval; +- unsigned long rc; +- +- ENTER(); +- +- if (VOS_FTM_MODE == hdd_get_conparam()) { +- hddLog(LOGE, FL("Command not allowed in FTM mode")); +- return -EINVAL; +- } +- +- retval = wlan_hdd_validate_context(hdd_ctx); +- if (0 != retval) +- return -EINVAL; +- +- if (!hdd_ctx->cfg_ini->extscan_enabled) { +- hddLog(LOGE, FL("extscan not supported")); +- return -ENOTSUPP; +- } +- if (nla_parse(tb, PARAM_MAX, +- data, data_len, +- wlan_hdd_extscan_config_policy)) { +- hddLog(LOGE, FL("Invalid ATTR")); +- return -EINVAL; +- } +- +- request = vos_mem_malloc(sizeof(*request)); +- if (!request) { +- hddLog(LOGE, FL("vos_mem_malloc failed")); +- return -ENOMEM; +- } +- +- /* Parse and fetch request Id */ +- if (!tb[PARAM_REQUEST_ID]) { +- hddLog(LOGE, FL("attr request id failed")); +- goto fail; +- } +- +- request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]); +- request->session_id = adapter->sessionId; +- hddLog(LOG1, FL("Request Id %d Session Id %d"), request->request_id, +- request->session_id); +- +- request->lost_ssid_sample_size = 0; +- request->ssid_count = 0; +- +- context = &hdd_ctx->ext_scan_context; +- spin_lock(&hdd_context_lock); +- INIT_COMPLETION(context->response_event); +- context->request_id = request_id = request->request_id; +- spin_unlock(&hdd_context_lock); +- +- status = sme_set_ssid_hotlist(hdd_ctx->hHal, request); +- if (!HAL_STATUS_SUCCESS(status)) { +- hddLog(LOGE, +- FL("sme_reset_ssid_hotlist failed(err=%d)"), status); +- goto fail; +- } +- +- vos_mem_free(request); +- +- /* request was sent -- wait for the response */ +- rc = wait_for_completion_timeout(&context->response_event, +- msecs_to_jiffies +- (WLAN_WAIT_TIME_EXTSCAN)); +- if (!rc) { +- hddLog(LOGE, FL("sme_reset_ssid_hotlist timed out")); +- retval = -ETIMEDOUT; +- } else { +- spin_lock(&hdd_context_lock); +- if (context->request_id == request_id) +- retval = context->response_status; +- else +- retval = -EINVAL; +- spin_unlock(&hdd_context_lock); +- } +- +- return retval; +- +-fail: +- vos_mem_free(request); +- return -EINVAL; +-} +- +-/** +- * wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list +- * @wiphy: Pointer to wireless phy +- * @wdev: Pointer to wireless device +- * @data: Pointer to data +- * @data_len: Data length +- * +- * Return: 0 on success, negative errno on failure +- */ +-static int +-wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- const void *data, +- int data_len) +-{ +- int ret; +- +- vos_ssr_protect(__func__); +- ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev, +- data, data_len); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} + /* + * done with short names for the global vendor params + * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() +@@ -13572,22 +13179,6 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_reset_passpoint_list + }, +- { +- .info.vendor_id = QCA_NL80211_VENDOR_ID, +- .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST, +- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | +- WIPHY_VENDOR_CMD_NEED_NETDEV | +- WIPHY_VENDOR_CMD_NEED_RUNNING, +- .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist +- }, +- { +- .info.vendor_id = QCA_NL80211_VENDOR_ID, +- .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST, +- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | +- WIPHY_VENDOR_CMD_NEED_NETDEV | +- WIPHY_VENDOR_CMD_NEED_RUNNING, +- .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist +- }, + #endif /* FEATURE_WLAN_EXTSCAN */ + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, +@@ -27596,152 +27187,6 @@ wlan_hdd_cfg80211_extscan_generic_rsp + } + + /** +- * wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind() - +- * Handle an SSID hotlist match event +- * @ctx: HDD context registered with SME +- * @event: The SSID hotlist match event +- * +- * This function will take an SSID match event that was generated by +- * firmware and will convert it into a cfg80211 vendor event which is +- * sent to userspace. +- * This callback execute in atomic context and must not invoke any +- * blocking calls. +- * +- * Return: none +- */ +-static void +-wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx, +- tpSirWifiScanResultEvent event) +-{ +- hdd_context_t *hdd_ctx = ctx; +- struct sk_buff *skb; +- unsigned i; +- unsigned index; +- int flags = vos_get_gfp_flags(); +- +- ENTER(); +- +- if (wlan_hdd_validate_context(hdd_ctx)) +- return; +- +- if (!event) { +- hddLog(LOGE, +- FL("event is null")); +- return; +- } +- if (event->ap_found) { +- index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX; +- hddLog(LOG1, "SSID hotlist found"); +- } else { +- index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX; +- hddLog(LOG1, "SSID hotlist lost"); +- } +- +- skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, +- NULL, +- EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, +- index, flags); +- +- if (!skb) { +- hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); +- return; +- } +- hddLog(LOG1, "Req Id %u, Num results %u, More Data (%u)", +- event->requestId, event->numOfAps, event->moreData); +- +- for (i = 0; i < event->numOfAps; i++) { +- hddLog(LOG1, "[i=%d] Timestamp %llu " +- "Ssid: %s " +- "Bssid (" MAC_ADDRESS_STR ") " +- "Channel %u " +- "Rssi %d " +- "RTT %u " +- "RTT_SD %u", +- i, +- event->ap[i].ts, +- event->ap[i].ssid, +- MAC_ADDR_ARRAY(event->ap[i].bssid), +- event->ap[i].channel, +- event->ap[i].rssi, +- event->ap[i].rtt, +- event->ap[i].rtt_sd); +- } +- +- if (nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, +- event->requestId) || +- nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE, +- event->numOfAps)) { +- hddLog(LOGE, FL("put fail")); +- goto fail; +- } +- +- if (event->numOfAps) { +- struct nlattr *aps; +- aps = nla_nest_start(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST); +- if (!aps) { +- hddLog(LOGE, FL("nest fail")); +- goto fail; +- } +- +- for (i = 0; i < event->numOfAps; i++) { +- struct nlattr *ap; +- +- ap = nla_nest_start(skb, i); +- if (!ap) { +- hddLog(LOGE, FL("nest fail")); +- goto fail; +- } +- +- if (nla_put_u64(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, +- event->ap[i].ts) || +- nla_put(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID, +- sizeof(event->ap[i].ssid), +- event->ap[i].ssid) || +- nla_put(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID, +- sizeof(event->ap[i].bssid), +- event->ap[i].bssid) || +- nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL, +- event->ap[i].channel) || +- nla_put_s32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI, +- event->ap[i].rssi) || +- nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT, +- event->ap[i].rtt) || +- nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD, +- event->ap[i].rtt_sd)) { +- hddLog(LOGE, FL("put fail")); +- goto fail; +- } +- nla_nest_end(skb, ap); +- } +- nla_nest_end(skb, aps); +- +- if (nla_put_u8(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, +- event->moreData)) { +- hddLog(LOGE, FL("put fail")); +- goto fail; +- } +- } +- +- cfg80211_vendor_event(skb, flags); +- return; +- +-fail: +- kfree_skb(skb); +- return; +-} +- +-/** + * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() - results callback + * @hddctx: HDD context + * @data: event data +@@ -28462,11 +27907,6 @@ void wlan_hdd_cfg80211_extscan_callback(void *ctx, const tANI_U16 evType, + wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg); + break; + +- case eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND: +- wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx, +- (tpSirWifiScanResultEvent)pMsg); +- break; +- + default: + hddLog(LOGE, FL("Unknown event type %u"), evType); + break; +diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h +index 605e9c6..a2ac0b3 100644 +--- a/CORE/MAC/inc/sirApi.h ++++ b/CORE/MAC/inc/sirApi.h +@@ -99,7 +99,6 @@ typedef tANI_U8 tSirVersionString[SIR_VERSION_STRING_LEN]; + #define WLAN_EXTSCAN_MAX_BUCKETS 16 + #define WLAN_EXTSCAN_MAX_HOTLIST_APS 128 + #define WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS 64 +-#define WLAN_EXTSCAN_MAX_HOTLIST_SSIDS 8 + + #define NUM_CHAINS_MAX 2 + +@@ -133,7 +132,6 @@ typedef enum + eSIR_PASSPOINT_NETWORK_FOUND_IND, + eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP, + eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP, +- eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND, + + /* Keep this last */ + eSIR_EXTSCAN_CALLBACK_TYPE_MAX, +@@ -5639,37 +5637,6 @@ typedef struct + } tSirExtScanResetBssidHotlistReqParams, + *tpSirExtScanResetBssidHotlistReqParams; + +-/** +- * struct sir_ssid_hotlist_param - param for SSID Hotlist +- * @ssid: SSID which is being hotlisted +- * @band: Band in which the given SSID should be scanned +- * @rssi_low: Low bound on RSSI +- * @rssi_high: High bound on RSSI +- */ +-struct sir_ssid_hotlist_param { +- tSirMacSSid ssid; +- uint8_t band; +- int32_t rssi_low; +- int32_t rssi_high; +-}; +- +-/** +- * struct sir_set_ssid_hotlist_request - set SSID hotlist request struct +- * @request_id: ID of the request +- * @session_id: ID of the session +- * @lost_ssid_sample_size: Number of consecutive scans in which the SSID +- * must not be seen in order to consider the SSID "lost" +- * @ssid_count: Number of valid entries in the @ssids array +- * @ssids: Array that defines the SSIDs that are in the hotlist +- */ +-struct sir_set_ssid_hotlist_request { +- uint32_t request_id; +- uint8_t session_id; +- uint32_t lost_ssid_sample_size; +- uint32_t ssid_count; +- struct sir_ssid_hotlist_param ssids[WLAN_EXTSCAN_MAX_HOTLIST_SSIDS]; +-}; +- + typedef struct + { + tANI_U32 requestId; +diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h +index c6c8648..fbaad99 100644 +--- a/CORE/MAC/src/include/sirParams.h ++++ b/CORE/MAC/src/include/sirParams.h +@@ -725,7 +725,7 @@ typedef struct sSirMbMsgP2p + #define SIR_HAL_CONFIG_GUARD_TIME (SIR_HAL_ITC_MSG_TYPES_BEGIN + 315) + #define SIR_HAL_SET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 316) + #define SIR_HAL_RESET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 317) +-#define SIR_HAL_EXTSCAN_SET_SSID_HOTLIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 318) ++/* 318 unused */ + + #define SIR_HAL_OCB_SET_CONFIG_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 319) + #define SIR_HAL_OCB_SET_UTC_TIME_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 320) +diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c +index 4acc943..df2ae90 100644 +--- a/CORE/SERVICES/WMA/wma.c ++++ b/CORE/SERVICES/WMA/wma.c +@@ -4438,102 +4438,6 @@ static int wma_passpoint_match_event_handler(void *handle, + return 0; + } + +-/** +- * wma_extscan_hotlist_ssid_match_event_handler() - +- * Handler for SSID hotlist match event from firmware +- * @handle: WMA handle +- * @cmd_param_info: WMI command buffer +- * @len: length of @cmd_param_info +- * +- * Return: 0 on success, non-zero on failure +- */ +-static int +-wma_extscan_hotlist_ssid_match_event_handler(void *handle, +- uint8_t *cmd_param_info, +- uint32_t len) +-{ +- tp_wma_handle wma = (tp_wma_handle) handle; +- WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID_param_tlvs *param_buf; +- wmi_extscan_hotlist_ssid_match_event_fixed_param *event; +- tSirWifiScanResultEvent *dest_hotlist; +- tSirWifiScanResult *dest_ap; +- wmi_extscan_wlan_descriptor *src_hotlist; +- int numap, j; +- bool ssid_found = false; +- tpAniSirGlobal mac = +- vos_get_context(VOS_MODULE_ID_PE, wma->vos_context); +- +- if (!mac) { +- WMA_LOGE("%s: Invalid mac", __func__); +- return -EINVAL; +- } +- +- if (!mac->sme.pExtScanIndCb) { +- WMA_LOGE("%s: Callback not registered", __func__); +- return -EINVAL; +- } +- +- param_buf = (WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID_param_tlvs *) +- cmd_param_info; +- if (!param_buf) { +- WMA_LOGE("%s: Invalid hotlist match event", __func__); +- return -EINVAL; +- } +- +- event = param_buf->fixed_param; +- src_hotlist = param_buf->hotlist_ssid_match; +- numap = event->total_entries; +- if (!src_hotlist || !numap) { +- WMA_LOGE("%s: Hotlist AP's list invalid", __func__); +- return -EINVAL; +- } +- +- dest_hotlist = vos_mem_malloc(sizeof(*dest_hotlist) + +- sizeof(*dest_ap) * numap); +- if (!dest_hotlist) { +- WMA_LOGE("%s: Allocation failed for hotlist buffer", __func__); +- return -EINVAL; +- } +- +- dest_ap = &dest_hotlist->ap[0]; +- dest_hotlist->numOfAps = event->total_entries; +- dest_hotlist->requestId = event->config_request_id; +- +- if (event->first_entry_index + +- event->num_entries_in_page < event->total_entries) +- dest_hotlist->moreData = 1; +- else +- dest_hotlist->moreData = 0; +- +- WMA_LOGD("%s: Hotlist match: requestId: %u, numOfAps: %d", __func__, +- dest_hotlist->requestId, dest_hotlist->numOfAps); +- +- for (j = 0; j < numap; j++) { +- dest_ap->channel = src_hotlist->channel; +- dest_ap->ts = src_hotlist->tstamp; +- ssid_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE; +- dest_ap->rtt = src_hotlist->rtt; +- dest_ap->rtt_sd = src_hotlist->rtt_sd; +- dest_ap->beaconPeriod = src_hotlist->beacon_interval; +- dest_ap->capability = src_hotlist->capabilities; +- dest_ap->ieLength = src_hotlist-> ie_length; +- WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid, +- dest_ap->bssid); +- vos_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid, +- src_hotlist->ssid.ssid_len); +- dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0'; +- dest_ap++; +- src_hotlist++; +- } +- +- dest_hotlist->ap_found = ssid_found; +- mac->sme.pExtScanIndCb(mac->hHdd, +- eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND, +- dest_hotlist); +- WMA_LOGD("%s: sending hotlist ssid match event", __func__); +- vos_mem_free(dest_hotlist); +- return 0; +-} + #endif + + #ifdef WLAN_FEATURE_LINK_LAYER_STATS +@@ -8079,10 +7983,6 @@ wma_register_extscan_event_handler(tp_wma_handle wma_handle) + WMI_PASSPOINT_MATCH_EVENTID, + wma_passpoint_match_event_handler); + +- wmi_unified_register_event_handler(wma_handle->wmi_handle, +- WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID, +- wma_extscan_hotlist_ssid_match_event_handler); +- + return; + + } +@@ -21915,10 +21815,6 @@ static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag) + event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID; + break; + +- case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param: +- event_id = WMI_EXTSCAN_HOTLIST_SSID_MATCH_EVENTID; +- break; +- + default: + event_id = 0; + WMA_LOGE("%s: Unknown tag: %d", __func__, tag); +@@ -22003,11 +21899,6 @@ static void wma_extscan_wow_event_callback(void *handle, void *event, + wmi_cmd_struct_ptr, len); + break; + +- case WMITLV_TAG_STRUC_wmi_extscan_hotlist_ssid_match_event_fixed_param: +- wma_extscan_hotlist_ssid_match_event_handler(handle, +- wmi_cmd_struct_ptr, len); +- break; +- + default: + WMA_LOGE("%s: Unknown tag: %d", __func__, tag); + break; +@@ -28903,111 +28794,6 @@ VOS_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma, + return VOS_STATUS_SUCCESS; + } + +-/** +- * wma_set_ssid_hotlist() - Handle an SSID hotlist set request +- * @wma: WMA handle +- * @request: SSID hotlist set request from SME +- * +- * Return: VOS_STATUS +- */ +-static VOS_STATUS +-wma_set_ssid_hotlist(tp_wma_handle wma, +- struct sir_set_ssid_hotlist_request *request) +-{ +- wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param *cmd; +- wmi_buf_t wmi_buf; +- uint32_t len; +- uint32_t array_size; +- uint8_t *buf_ptr; +- +- if (!wma || !wma->wmi_handle) { +- WMA_LOGE("%s: WMA is closed, can not issue hotlist cmd", +- __func__); +- return VOS_STATUS_E_INVAL; +- } +- if (!request) { +- WMA_LOGE("%s: Invalid request buffer", +- __func__); +- return VOS_STATUS_E_INVAL; +- } +- if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, +- WMI_SERVICE_EXTSCAN)) { +- WMA_LOGE("%s: extscan not enabled", +- __func__); +- return VOS_STATUS_E_FAILURE; +- } +- +- /* length of fixed portion */ +- len = sizeof(*cmd); +- +- /* length of variable portion */ +- array_size = +- request->ssid_count * sizeof(wmi_extscan_hotlist_ssid_entry); +- len += WMI_TLV_HDR_SIZE + array_size; +- +- wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); +- if (!wmi_buf) { +- WMA_LOGE("%s: wmi_buf_alloc failed", __func__); +- return VOS_STATUS_E_NOMEM; +- } +- +- buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf); +- cmd = (wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param *) +- buf_ptr; +- WMITLV_SET_HDR +- (&cmd->tlv_header, +- WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param, +- WMITLV_GET_STRUCT_TLVLEN +- (wmi_extscan_configure_hotlist_ssid_monitor_cmd_fixed_param)); +- +- cmd->request_id = request->request_id; +- cmd->requestor_id = 0; +- cmd->vdev_id = request->session_id; +- cmd->table_id = 0; +- cmd->lost_ap_scan_count = request->lost_ssid_sample_size; +- cmd->total_entries = request->ssid_count; +- cmd->num_entries_in_page = request->ssid_count; +- cmd->first_entry_index = 0; +- +- buf_ptr += sizeof(*cmd); +- WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, array_size); +- +- if (request->ssid_count) { +- wmi_extscan_hotlist_ssid_entry *entry; +- int i; +- +- buf_ptr += WMI_TLV_HDR_SIZE; +- entry = (wmi_extscan_hotlist_ssid_entry *)buf_ptr; +- for (i = 0; i < request->ssid_count; i++) { +- WMITLV_SET_HDR +- (entry, +- WMITLV_TAG_ARRAY_STRUC, +- WMITLV_GET_STRUCT_TLVLEN +- (wmi_extscan_hotlist_ssid_entry)); +- entry->ssid.ssid_len = request->ssids[i].ssid.length; +- vos_mem_copy(entry->ssid.ssid, +- request->ssids[i].ssid.ssId, +- request->ssids[i].ssid.length); +- entry->band = request->ssids[i].band; +- entry->min_rssi = request->ssids[i].rssi_low; +- entry->max_rssi = request->ssids[i].rssi_high; +- entry++; +- } +- cmd->mode = WMI_EXTSCAN_MODE_START; +- } else { +- cmd->mode = WMI_EXTSCAN_MODE_STOP; +- } +- +- if (wmi_unified_cmd_send +- (wma->wmi_handle, wmi_buf, len, +- WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID)) { +- WMA_LOGE("%s: failed to send command", __func__); +- wmi_buf_free(wmi_buf); +- return VOS_STATUS_E_FAILURE; +- } +- return VOS_STATUS_SUCCESS; +-} +- + VOS_STATUS wma_get_buf_extscan_change_monitor_cmd(tp_wma_handle wma_handle, + tSirExtScanSetSigChangeReqParams *psigchange, + wmi_buf_t *buf, int *buf_len) +@@ -32598,11 +32384,6 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg) + (tSirExtScanResetBssidHotlistReqParams *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; +- case WDA_EXTSCAN_SET_SSID_HOTLIST_REQ: +- wma_set_ssid_hotlist(wma_handle, +- (struct sir_set_ssid_hotlist_request *)msg->bodyptr); +- vos_mem_free(msg->bodyptr); +- break; + case WDA_EXTSCAN_SET_SIGNF_CHANGE_REQ: + wma_extscan_start_change_monitor(wma_handle, + (tSirExtScanSetSigChangeReqParams *)msg->bodyptr); +diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h +index 3a08cb5..0834e5b 100644 +--- a/CORE/SME/inc/sme_Api.h ++++ b/CORE/SME/inc/sme_Api.h +@@ -4137,10 +4137,6 @@ eHalStatus sme_SetBssHotlist (tHalHandle hHal, + eHalStatus sme_ResetBssHotlist (tHalHandle hHal, + tSirExtScanResetBssidHotlistReqParams *pResetReq); + +-eHalStatus +-sme_set_ssid_hotlist(tHalHandle hal, +- struct sir_set_ssid_hotlist_request *request); +- + /* --------------------------------------------------------------------------- + \fn sme_SetSignificantChange + \brief SME API to set significant change +diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c +index 4db2b3f..cb1a588 100644 +--- a/CORE/SME/src/sme_common/sme_Api.c ++++ b/CORE/SME/src/sme_common/sme_Api.c +@@ -15966,52 +15966,6 @@ eHalStatus sme_ResetBssHotlist (tHalHandle hHal, + return status; + } + +-/** +- * sme_set_ssid_hotlist() - Set the SSID hotlist +- * @hal: SME handle +- * @request: set ssid hotlist request +- * +- * Return: eHalStatus +- */ +-eHalStatus +-sme_set_ssid_hotlist(tHalHandle hal, +- struct sir_set_ssid_hotlist_request *request) +-{ +- eHalStatus status; +- VOS_STATUS vstatus; +- tpAniSirGlobal mac = PMAC_STRUCT(hal); +- vos_msg_t vos_message; +- struct sir_set_ssid_hotlist_request *set_req; +- +- set_req = vos_mem_malloc(sizeof(*set_req)); +- if (!set_req) { +- VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, +- "%s: Not able to allocate memory for WDA_EXTSCAN_SET_SSID_HOTLIST_REQ", +- __func__); +- return eHAL_STATUS_FAILURE; +- } +- +- *set_req = *request; +- status = sme_AcquireGlobalLock(&mac->sme); +- if (eHAL_STATUS_SUCCESS == status) { +- /* Serialize the req through MC thread */ +- vos_message.bodyptr = set_req; +- vos_message.type = WDA_EXTSCAN_SET_SSID_HOTLIST_REQ; +- vstatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); +- sme_ReleaseGlobalLock(&mac->sme); +- if (!VOS_IS_STATUS_SUCCESS(vstatus)) { +- vos_mem_free(set_req); +- status = eHAL_STATUS_FAILURE; +- } +- } else { +- VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, +- "%s: sme_AcquireGlobalLock error", __func__); +- vos_mem_free(set_req); +- status = eHAL_STATUS_FAILURE; +- } +- return status; +-} +- + /* --------------------------------------------------------------------------- + \fn sme_SetSignificantChange + \brief SME API to set significant change +diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c +index 8a27363..110376f 100644 +--- a/CORE/SYS/legacy/src/utils/src/macTrace.c ++++ b/CORE/SYS/legacy/src/utils/src/macTrace.c +@@ -952,7 +952,6 @@ tANI_U8* macTraceGetWdaMsgString(tANI_U16 wdaMsg) + CASE_RETURN_STRING(WDA_EXTSCAN_STOP_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_SET_BSSID_HOTLIST_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_RESET_BSSID_HOTLIST_REQ); +- CASE_RETURN_STRING(WDA_EXTSCAN_SET_SSID_HOTLIST_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_SET_SIGNF_CHANGE_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_RESET_SIGNF_CHANGE_REQ); + CASE_RETURN_STRING(WDA_EXTSCAN_GET_CACHED_RESULTS_REQ); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0464/1.patch b/Patches/Linux_CVEs/CVE-2017-0464/1.patch new file mode 100644 index 00000000..c61af867 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0464/1.patch @@ -0,0 +1,2021 @@ +From c593cd332c42b2a813f0ab72e2e33980430fb47b Mon Sep 17 00:00:00 2001 +From: Hanumanth Reddy Pothula +Date: Fri, 21 Aug 2015 19:58:01 +0530 +Subject: wlan: Remove obsolete set/reset ssid hotlist + +Remove obsolete set/reset ssid hotlist. + +Change-Id: Ie6c4a9847f2daa9ba2aebd17f386d584201b86d6 +CRs-Fixed: 2049138 +--- + CORE/HDD/inc/wlan_hdd_cfg80211.h | 19 +- + CORE/HDD/src/wlan_hdd_cfg80211.c | 612 -------------------------------------- + CORE/MAC/inc/sirApi.h | 60 ---- + CORE/SME/inc/sme_Api.h | 21 -- + CORE/SME/src/sme_common/sme_Api.c | 111 ------- + CORE/WDA/src/wlan_qct_wda.c | 265 ----------------- + CORE/WDI/CP/inc/wlan_qct_wdi.h | 65 +--- + CORE/WDI/CP/inc/wlan_qct_wdi_i.h | 41 --- + CORE/WDI/CP/src/wlan_qct_wdi.c | 462 +--------------------------- + 9 files changed, 13 insertions(+), 1643 deletions(-) + +diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h +index d1ca157..6307b18 100644 +--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h ++++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h +@@ -179,10 +179,12 @@ enum qca_nl80211_vendor_subcmds { + QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO = 61, + /* Start Wifi Memory Dump */ + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP = 63, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST = 65, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST = 66, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND = 67, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST = 68, ++ ++ /* ++ * APIs corresponding to the sub commands 65-68 are deprecated. ++ * These sub commands are reserved and not supposed to be used ++ * for any other purpose ++ */ + + /* Wi-Fi Configuration subcommands */ + QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74, +@@ -230,11 +232,6 @@ enum qca_nl80211_vendor_subcmds_index { + QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX, + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX, + +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX, +- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX, +- + QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX, + QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX, + QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX, +@@ -1046,10 +1043,6 @@ enum qca_wlan_vendor_attr_extscan_results + /* Unsigned 32bit value; a EXTSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID, + +- /* EXTSCAN attributes for +- * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND sub-command & +- * QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST sub-command +- */ + /* Use attr QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE + * to indicate number of results. + */ +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 719a56c..2caef5e 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -2533,70 +2533,6 @@ static void wlan_hdd_cfg80211_extscan_reset_bss_hotlist_rsp(void *ctx, + return; + } + +-static void wlan_hdd_cfg80211_extscan_set_ssid_hotlist_rsp(void *ctx, +- void *pMsg) +-{ +- hdd_context_t *pHddCtx = (hdd_context_t *)ctx; +- tpSirEXTScanSetSsidHotListRspParams pData = +- (tpSirEXTScanSetSsidHotListRspParams) pMsg; +- struct hdd_ext_scan_context *context; +- +- if (wlan_hdd_validate_context(pHddCtx)){ +- return; +- } +- +- if (!pMsg) +- { +- hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null")); +- return; +- } +- +- hddLog(VOS_TRACE_LEVEL_INFO, "Req Id %u Status %u", pData->requestId, +- pData->status); +- +- context = &pHddCtx->ext_scan_context; +- spin_lock(&hdd_context_lock); +- if (context->request_id == pData->requestId) { +- context->response_status = pData->status ? -EINVAL : 0; +- complete(&context->response_event); +- } +- spin_unlock(&hdd_context_lock); +- +- return; +-} +- +-static void wlan_hdd_cfg80211_extscan_reset_ssid_hotlist_rsp(void *ctx, +- void *pMsg) +-{ +- hdd_context_t *pHddCtx = (hdd_context_t *)ctx; +- tpSirEXTScanResetSsidHotlistRspParams pData = +- (tpSirEXTScanResetSsidHotlistRspParams) pMsg; +- struct hdd_ext_scan_context *context; +- +- if (wlan_hdd_validate_context(pHddCtx)) { +- return; +- } +- if (!pMsg) +- { +- hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null")); +- return; +- } +- +- hddLog(VOS_TRACE_LEVEL_INFO, "Req Id %u Status %u", pData->requestId, +- pData->status); +- +- context = &pHddCtx->ext_scan_context; +- spin_lock(&hdd_context_lock); +- if (context->request_id == pData->requestId) { +- context->response_status = pData->status ? -EINVAL : 0; +- complete(&context->response_event); +- } +- spin_unlock(&hdd_context_lock); +- +- return; +-} +- +- + static void wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx, + void *pMsg) + { +@@ -3004,156 +2940,6 @@ fail: + + } + +-/** +- * wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind() - +- * Handle an SSID hotlist match event +- * @ctx: HDD context registered with SME +- * @event: The SSID hotlist match event +- * +- * This function will take an SSID match event that was generated by +- * firmware and will convert it into a cfg80211 vendor event which is +- * sent to userspace. +- * +- * Return: none +- */ +-static void +-wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx, +- void *pMsg) +-{ +- hdd_context_t *hdd_ctx = ctx; +- struct sk_buff *skb; +- tANI_U32 i, index; +- tpSirEXTScanSsidHotlistMatch pData = (tpSirEXTScanSsidHotlistMatch) pMsg; +- +- ENTER(); +- +- if (wlan_hdd_validate_context(hdd_ctx)) { +- hddLog(LOGE, +- FL("HDD context is not valid or response")); +- return; +- } +- if (!pMsg) +- { +- hddLog(VOS_TRACE_LEVEL_ERROR, FL("pMsg is null")); +- return; +- } +- +- if (pData->ssid_found) { +- index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX; +- hddLog(LOG1, "SSID hotlist found"); +- } else { +- index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX; +- hddLog(LOG1, "SSID hotlist lost"); +- } +- +- skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) +- NULL, +-#endif +- EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN, +- index, GFP_KERNEL); +- +- if (!skb) { +- hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed")); +- return; +- } +- hddLog(LOG1, "Req Id %u, Num of SSIDs %u, More Data (%u)", +- pData->requestId, pData->numHotlistSsid, pData->moreData); +- +- for (i = 0; i < pData->numHotlistSsid; i++) { +- hddLog(LOG1, "[i=%d] Timestamp %llu " +- "Ssid: %s " +- "Bssid (" MAC_ADDRESS_STR ") " +- "Channel %u " +- "Rssi %d " +- "RTT %u " +- "RTT_SD %u", +- i, +- pData->ssidHotlist[i].ts, +- pData->ssidHotlist[i].ssid, +- MAC_ADDR_ARRAY(pData->ssidHotlist[i].bssid), +- pData->ssidHotlist[i].channel, +- pData->ssidHotlist[i].rssi, +- pData->ssidHotlist[i].rtt, +- pData->ssidHotlist[i].rtt_sd); +- } +- +- if (nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID, +- pData->requestId) || +- nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE, +- pData->numHotlistSsid)) { +- hddLog(LOGE, FL("put fail")); +- goto fail; +- } +- +- if (pData->numHotlistSsid) { +- struct nlattr *aps; +- aps = nla_nest_start(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST); +- if (!aps) { +- hddLog(LOGE, FL("nest fail")); +- goto fail; +- } +- +- for (i = 0; i < pData->numHotlistSsid; i++) { +- struct nlattr *ap; +- +- ap = nla_nest_start(skb, i); +- if (!ap) { +- hddLog(LOGE, FL("nest fail")); +- goto fail; +- } +- +- if (nla_put_u64(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP, +- pData->ssidHotlist[i].ts) || +- nla_put(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID, +- sizeof(pData->ssidHotlist[i].ssid), +- pData->ssidHotlist[i].ssid) || +- nla_put(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID, +- sizeof(pData->ssidHotlist[i].bssid), +- pData->ssidHotlist[i].bssid) || +- nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL, +- pData->ssidHotlist[i].channel) || +- nla_put_s32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI, +- pData->ssidHotlist[i].rssi) || +- nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT, +- pData->ssidHotlist[i].rtt) || +- nla_put_u32(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD, +- pData->ssidHotlist[i].rtt_sd)) { +- hddLog(LOGE, FL("put fail")); +- goto fail; +- } +- nla_nest_end(skb, ap); +- } +- nla_nest_end(skb, aps); +- +- if (nla_put_u8(skb, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA, +- pData->moreData)) { +- hddLog(LOGE, FL("put fail")); +- goto fail; +- } +- } +- +- cfg80211_vendor_event(skb, GFP_KERNEL); +- return; +- +-fail: +- kfree_skb(skb); +- return; +- +-} +- +- + static void wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, + void *pMsg) + { +@@ -3429,14 +3215,6 @@ void wlan_hdd_cfg80211_extscan_callback(void *ctx, const tANI_U16 evType, + wlan_hdd_cfg80211_extscan_reset_bss_hotlist_rsp(ctx, pMsg); + break; + +- case SIR_HAL_EXTSCAN_SET_SSID_HOTLIST_RSP: +- wlan_hdd_cfg80211_extscan_set_ssid_hotlist_rsp(ctx, pMsg); +- break; +- +- case SIR_HAL_EXTSCAN_RESET_SSID_HOTLIST_RSP: +- wlan_hdd_cfg80211_extscan_reset_ssid_hotlist_rsp(ctx, pMsg); +- break; +- + case SIR_HAL_EXTSCAN_GET_CAPABILITIES_RSP: + wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx, pMsg); + break; +@@ -3452,9 +3230,6 @@ void wlan_hdd_cfg80211_extscan_callback(void *ctx, const tANI_U16 evType, + case SIR_HAL_EXTSCAN_HOTLIST_MATCH_IND: + wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg); + break; +- case SIR_HAL_EXTSCAN_SSID_HOTLIST_MATCH_IND: +- wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx, pMsg); +- break; + case SIR_HAL_EXTSCAN_FULL_SCAN_RESULT_IND: + wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx, pMsg); + break; +@@ -3875,361 +3650,6 @@ static int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy, + return ret; + } + +-/* +- * define short names for the global vendor params +- * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist() +- */ +-#define PARAM_MAX \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +-#define PARAM_REQUEST_ID \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID +-#define PARAMS_LOST_SSID_SAMPLE_SIZE \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE +-#define PARAMS_NUM_SSID \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID +-#define THRESHOLD_PARAM \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM +-#define PARAM_SSID \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID +-#define PARAM_BAND \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND +-#define PARAM_RSSI_LOW \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW +-#define PARAM_RSSI_HIGH \ +-QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH +- +-/** +- * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list +- * @wiphy: Pointer to wireless phy +- * @wdev: Pointer to wireless device +- * @data: Pointer to data +- * @data_len: Data length +- * +- * Return: 0 on success, negative errno on failure +- */ +-static int +-__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- const void *data, +- int data_len) +-{ +- tSirEXTScanSetSsidHotListReqParams *request; +- struct net_device *dev = wdev->netdev; +- hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); +- hdd_context_t *hdd_ctx = wiphy_priv(wiphy); +- struct nlattr *tb[PARAM_MAX + 1]; +- struct nlattr *tb2[PARAM_MAX + 1]; +- struct nlattr *ssids; +- struct hdd_ext_scan_context *context; +- uint32_t request_id; +- char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1] = {'\0'}; +- int ssid_len; +- int ssid_length; +- eHalStatus status; +- int i, rem, retval; +- unsigned long rc; +- +- ENTER(); +- +- if (VOS_FTM_MODE == hdd_get_conparam()) { +- hddLog(LOGE, FL("Command not allowed in FTM mode")); +- return -EINVAL; +- } +- +- retval = wlan_hdd_validate_context(hdd_ctx); +- if (0 != retval) { +- hddLog(LOGE, FL("HDD context is not valid")); +- return -EINVAL; +- } +- +- /* check the EXTScan Capability */ +- if ( (TRUE != hdd_ctx->cfg_ini->fEnableEXTScan) || +- (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)) || +- (TRUE != sme_IsFeatureSupportedByFW(EXT_SCAN_ENHANCED))) +- { +- hddLog(VOS_TRACE_LEVEL_ERROR, +- FL("EXTScan not enabled/supported by Firmware")); +- return -EINVAL; +- } +- +- if (nla_parse(tb, PARAM_MAX, +- data, data_len, +- wlan_hdd_extscan_config_policy)) { +- hddLog(LOGE, FL("Invalid ATTR")); +- return -EINVAL; +- } +- +- request = vos_mem_malloc(sizeof(*request)); +- if (!request) { +- hddLog(LOGE, FL("vos_mem_malloc failed")); +- return -ENOMEM; +- } +- +- /* Parse and fetch request Id */ +- if (!tb[PARAM_REQUEST_ID]) { +- hddLog(LOGE, FL("attr request id failed")); +- goto fail; +- } +- +- request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]); +- hddLog(LOG1, FL("Request Id %d"), request->request_id); +- +- /* Parse and fetch lost SSID sample size */ +- if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) { +- hddLog(LOGE, FL("attr number of Ssid failed")); +- goto fail; +- } +- request->lost_ssid_sample_size = +- nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]); +- hddLog(LOG1, FL("Lost SSID Sample Size %d"), +- request->lost_ssid_sample_size); +- +- /* Parse and fetch number of hotlist SSID */ +- if (!tb[PARAMS_NUM_SSID]) { +- hddLog(LOGE, FL("attr number of Ssid failed")); +- goto fail; +- } +- request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]); +- hddLog(LOG1, FL("Number of SSID %d"), request->ssid_count); +- +- request->session_id = adapter->sessionId; +- hddLog(LOG1, FL("Session Id (%d)"), request->session_id); +- +- i = 0; +- nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) { +- if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) { +- hddLog(LOGE, +- FL("Too Many SSIDs, %d exceeds %d"), +- i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS); +- break; +- } +- if (nla_parse(tb2, PARAM_MAX, +- nla_data(ssids), nla_len(ssids), +- wlan_hdd_extscan_config_policy)) { +- hddLog(LOGE, FL("nla_parse failed")); +- goto fail; +- } +- +- /* Parse and fetch SSID */ +- if (!tb2[PARAM_SSID]) { +- hddLog(LOGE, FL("attr ssid failed")); +- goto fail; +- } +- ssid_length = nla_strlcpy(ssid_string, tb2[PARAM_SSID], +- sizeof(ssid_string)); +- hddLog(LOG1, FL("SSID %s"), +- ssid_string); +- ssid_len = strlen(ssid_string); +- if (ssid_length >= SIR_MAC_MAX_SSID_LENGTH) { +- hddLog(LOGE, FL("Invalid ssid length")); +- goto fail; +- } +- memcpy(request->ssid[i].ssid.ssId, ssid_string, ssid_len); +- request->ssid[i].ssid.length = ssid_len; +- request->ssid[i].ssid.ssId[ssid_len] = '\0'; +- hddLog(LOG1, FL("After copying SSID %s"), +- request->ssid[i].ssid.ssId); +- hddLog(LOG1, FL("After copying length: %d"), +- ssid_len); +- +- /* Parse and fetch low RSSI */ +- if (!tb2[PARAM_BAND]) { +- hddLog(LOGE, FL("attr band failed")); +- goto fail; +- } +- request->ssid[i].band = nla_get_u8(tb2[PARAM_BAND]); +- hddLog(LOG1, FL("band %d"), request->ssid[i].band); +- +- /* Parse and fetch low RSSI */ +- if (!tb2[PARAM_RSSI_LOW]) { +- hddLog(LOGE, FL("attr low RSSI failed")); +- goto fail; +- } +- request->ssid[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]); +- hddLog(LOG1, FL("RSSI low %d"), request->ssid[i].rssi_low); +- +- /* Parse and fetch high RSSI */ +- if (!tb2[PARAM_RSSI_HIGH]) { +- hddLog(LOGE, FL("attr high RSSI failed")); +- goto fail; +- } +- request->ssid[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]); +- hddLog(LOG1, FL("RSSI high %d"), request->ssid[i].rssi_high); +- i++; +- } +- +- context = &hdd_ctx->ext_scan_context; +- spin_lock(&hdd_context_lock); +- INIT_COMPLETION(context->response_event); +- context->request_id = request_id = request->request_id; +- spin_unlock(&hdd_context_lock); +- +- status = sme_set_ssid_hotlist(hdd_ctx->hHal, request); +- if (!HAL_STATUS_SUCCESS(status)) { +- hddLog(LOGE, +- FL("sme_set_ssid_hotlist failed(err=%d)"), status); +- goto fail; +- } +- +- vos_mem_free(request); +- +- /* request was sent -- wait for the response */ +- rc = wait_for_completion_timeout(&context->response_event, +- msecs_to_jiffies +- (WLAN_WAIT_TIME_EXTSCAN)); +- if (!rc) { +- hddLog(LOGE, FL("sme_set_ssid_hotlist timed out")); +- retval = -ETIMEDOUT; +- } else { +- spin_lock(&hdd_context_lock); +- if (context->request_id == request_id) +- retval = context->response_status; +- else +- retval = -EINVAL; +- spin_unlock(&hdd_context_lock); +- } +- +- return retval; +- +-fail: +- vos_mem_free(request); +- return -EINVAL; +-} +- +-/* +- * done with short names for the global vendor params +- * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist() +- */ +-#undef PARAM_MAX +-#undef PARAM_REQUEST_ID +-#undef PARAMS_NUM_SSID +-#undef THRESHOLD_PARAM +-#undef PARAM_SSID +-#undef PARAM_BAND +-#undef PARAM_RSSI_LOW +-#undef PARAM_RSSI_HIGH +- +-static int wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- const void *data, int dataLen) +-{ +- int ret = 0; +- +- vos_ssr_protect(__func__); +- ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data, +- dataLen); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} +- +-static int +-__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- const void *data, +- int data_len) +-{ +- tSirEXTScanResetSsidHotlistReqParams request; +- struct net_device *dev = wdev->netdev; +- hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); +- hdd_context_t *hdd_ctx = wiphy_priv(wiphy); +- struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1]; +- struct hdd_ext_scan_context *context; +- uint32_t request_id; +- eHalStatus status; +- int retval; +- unsigned long rc; +- +- ENTER(); +- +- if (VOS_FTM_MODE == hdd_get_conparam()) { +- hddLog(LOGE, FL("Command not allowed in FTM mode")); +- return -EINVAL; +- } +- +- retval = wlan_hdd_validate_context(hdd_ctx); +- if (0 != retval) { +- hddLog(LOGE, FL("HDD context is not valid")); +- return -EINVAL; +- } +- +- /* check the EXTScan Capability */ +- if ( (TRUE != hdd_ctx->cfg_ini->fEnableEXTScan) || +- (TRUE != sme_IsFeatureSupportedByFW(EXTENDED_SCAN)) || +- (TRUE != sme_IsFeatureSupportedByFW(EXT_SCAN_ENHANCED))) +- { +- hddLog(LOGE, +- FL("EXTScan not enabled/supported by Firmware")); +- return -EINVAL; +- } +- +- if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, +- data, data_len, +- wlan_hdd_extscan_config_policy)) { +- hddLog(LOGE, FL("Invalid ATTR")); +- return -EINVAL; +- } +- +- /* Parse and fetch request Id */ +- if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { +- hddLog(LOGE, FL("attr request id failed")); +- return -EINVAL; +- } +- +- request.requestId = nla_get_u32( +- tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); +- request.sessionId = adapter->sessionId; +- hddLog(LOG1, FL("Request Id %d Session Id %d"), request.requestId, +- request.sessionId); +- +- context = &hdd_ctx->ext_scan_context; +- spin_lock(&hdd_context_lock); +- INIT_COMPLETION(context->response_event); +- context->request_id = request_id = request.requestId; +- spin_unlock(&hdd_context_lock); +- +- status = sme_reset_ssid_hotlist(hdd_ctx->hHal, &request); +- if (!HAL_STATUS_SUCCESS(status)) { +- hddLog(LOGE, +- FL("sme_reset_ssid_hotlist failed(err=%d)"), status); +- return -EINVAL; +- } +- +- /* request was sent -- wait for the response */ +- rc = wait_for_completion_timeout(&context->response_event, +- msecs_to_jiffies +- (WLAN_WAIT_TIME_EXTSCAN)); +- if (!rc) { +- hddLog(LOGE, FL("sme_reset_ssid_hotlist timed out")); +- retval = -ETIMEDOUT; +- } else { +- spin_lock(&hdd_context_lock); +- if (context->request_id == request_id) +- retval = context->response_status; +- else +- retval = -EINVAL; +- spin_unlock(&hdd_context_lock); +- } +- +- return retval; +-} +- +-static int +-wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy, +- struct wireless_dev *wdev, +- const void *data, +- int data_len) +-{ +- int ret; +- +- vos_ssr_protect(__func__); +- ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev, +- data, data_len); +- vos_ssr_unprotect(__func__); +- +- return ret; +-} +- + static int __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int dataLen) +@@ -8017,22 +7437,6 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist + }, +- { +- .info.vendor_id = QCA_NL80211_VENDOR_ID, +- .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST, +- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | +- WIPHY_VENDOR_CMD_NEED_NETDEV | +- WIPHY_VENDOR_CMD_NEED_RUNNING, +- .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist +- }, +- { +- .info.vendor_id = QCA_NL80211_VENDOR_ID, +- .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST, +- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | +- WIPHY_VENDOR_CMD_NEED_NETDEV | +- WIPHY_VENDOR_CMD_NEED_RUNNING, +- .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist +- }, + #endif /* WLAN_FEATURE_EXTSCAN */ + /*EXT TDLS*/ + { +@@ -8260,22 +7664,6 @@ struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = + .vendor_id = QCA_NL80211_VENDOR_ID, + .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST + }, +- { +- .vendor_id = QCA_NL80211_VENDOR_ID, +- .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST +- }, +- { +- .vendor_id = QCA_NL80211_VENDOR_ID, +- .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST +- }, +- [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = { +- .vendor_id = QCA_NL80211_VENDOR_ID, +- .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND +- }, +- [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = { +- .vendor_id = QCA_NL80211_VENDOR_ID, +- .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST +- }, + #endif /* WLAN_FEATURE_EXTSCAN */ + /*EXT TDLS*/ + { +diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h +index bf39d4b..f1d59c4 100644 +--- a/CORE/MAC/inc/sirApi.h ++++ b/CORE/MAC/inc/sirApi.h +@@ -143,7 +143,6 @@ typedef tANI_U8 tSirVersionString[SIR_VERSION_STRING_LEN]; + #define WLAN_EXTSCAN_MAX_BUCKETS 16 + #define WLAN_EXTSCAN_MAX_HOTLIST_APS 128 + #define WLAN_EXTSCAN_MAX_RSSI_SAMPLE_SIZE 8 +-#define WLAN_EXTSCAN_MAX_HOTLIST_SSIDS 8 + #endif /* WLAN_FEATURE_EXTSCAN */ + + #define WLAN_DISA_MAX_PAYLOAD_SIZE 1600 +@@ -5630,22 +5629,6 @@ typedef PACKED_PRE struct PACKED_POST + tANI_U8 result[1]; + } tSirWifiScanResultEvent, *tpSirWifiScanResultEvent; + +-/* WLAN_HAL_SSID_HOTLIST_RESULT_IND */ +- +-typedef PACKED_PRE struct PACKED_POST +-{ +- tANI_U32 requestId; +- tANI_BOOLEAN ssid_found; +- tANI_U32 numHotlistSsid; // numbers of SSIDs +- +- /* +- * 0 for last fragment +- * 1 still more fragment(s) coming +- */ +- tANI_BOOLEAN moreData; +- tSirWifiScanResult ssidHotlist[1]; +-} tSirEXTScanSsidHotlistMatch, *tpSirEXTScanSsidHotlistMatch; +- + typedef PACKED_PRE struct PACKED_POST + { + tANI_U8 elemId; // Element Identifier +@@ -5775,49 +5758,6 @@ typedef PACKED_PRE struct PACKED_POST + tANI_U32 status; + } tSirEXTScanResetBssidHotlistRspParams, *tpSirEXTScanResetBssidHotlistRspParams; + +-typedef struct +-{ +- tANI_U32 requestId; +- tANI_U8 sessionId; +-} tSirEXTScanResetSsidHotlistReqParams, *tpSirEXTScanResetSsidHotlistReqParams; +- +-typedef PACKED_PRE struct PACKED_POST +-{ +- tANI_U32 requestId; +- tANI_U32 status; +-} tSirEXTScanResetSsidHotlistRspParams, *tpSirEXTScanResetSsidHotlistRspParams; +- +- +-/** +- * struct sir_ssid_hotlist_param - param for SSID Hotlist +- * @ssid: SSID which is being hotlisted +- * @band: Band in which the given SSID should be scanned +- * @rssi_low: Low bound on RSSI +- * @rssi_high: High bound on RSSI +- */ +-typedef struct +-{ +- tSirMacSSid ssid; +- tANI_U8 band; +- tANI_S32 rssi_low; +- tANI_S32 rssi_high; +-}tSirSsidThresholdParam, *tpSirSsidThresholdParam; +- +-typedef struct +-{ +- tANI_U32 request_id; +- tANI_U8 session_id; +- tANI_U32 lost_ssid_sample_size; +- tANI_U32 ssid_count; +- tSirSsidThresholdParam ssid[WLAN_EXTSCAN_MAX_HOTLIST_SSIDS]; +-}tSirEXTScanSetSsidHotListReqParams, *tpSirEXTScanSetSsidHotListReqParams; +- +-typedef PACKED_PRE struct PACKED_POST +-{ +- tANI_U32 requestId; +- tANI_U32 status; +-} tSirEXTScanSetSsidHotListRspParams, *tpSirEXTScanSetSsidHotListRspParams; +- + /*--------------------------------------------------------------------------- + * * WLAN_HAL_EXTSCAN_RESULT_AVAILABLE_IND + * *-------------------------------------------------------------------------*/ +diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h +index cf65a45..7039efc 100644 +--- a/CORE/SME/inc/sme_Api.h ++++ b/CORE/SME/inc/sme_Api.h +@@ -293,27 +293,6 @@ eHalStatus sme_SetBssHotlist (tHalHandle hHal, + eHalStatus sme_ResetBssHotlist (tHalHandle hHal, + tSirEXTScanResetBssidHotlistReqParams *pResetReq); + +-/** +- * sme_set_ssid_hotlist() - Set the SSID hotlist +- * @hal: SME handle +- * @request: set ssid hotlist request +- * +- * Return: eHalStatus +- */ +-eHalStatus sme_set_ssid_hotlist(tHalHandle hal, +- tSirEXTScanSetSsidHotListReqParams *request); +- +-/* --------------------------------------------------------------------------- +- \fn sme_ResetBssHotlist +- \brief SME API to reset BSSID hotlist +- \param hHal +- \param pSetHotListReq: Extented Scan set hotlist structure +- \- return eHalStatus +- -------------------------------------------------------------------------*/ +-eHalStatus sme_reset_ssid_hotlist (tHalHandle hHal, +- tSirEXTScanResetSsidHotlistReqParams *pResetReq); +- +- + /* --------------------------------------------------------------------------- + \fn sme_getCachedResults + \brief SME API to get cached results +diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c +index 2caf735..05d20d2 100644 +--- a/CORE/SME/src/sme_common/sme_Api.c ++++ b/CORE/SME/src/sme_common/sme_Api.c +@@ -13416,117 +13416,6 @@ eHalStatus sme_ResetBssHotlist (tHalHandle hHal, + return(status); + } + +-/** +- * sme_set_ssid_hotlist() - Set the SSID hotlist +- * @hal: SME handle +- * @request: set ssid hotlist request +- * +- * Return: eHalStatus +- */ +-eHalStatus +-sme_set_ssid_hotlist(tHalHandle hal, +- tSirEXTScanSetSsidHotListReqParams *request) +-{ +- eHalStatus status; +- VOS_STATUS vstatus; +- tpAniSirGlobal mac = PMAC_STRUCT(hal); +- vos_msg_t vos_message; +- tSirEXTScanSetSsidHotListReqParams *set_req; +- int i; +- +- set_req = vos_mem_malloc(sizeof(*set_req)); +- if (!set_req) { +- VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, +- "%s: Not able to allocate memory for WDA_EXTSCAN_SET_SSID_HOTLIST_REQ", +- __func__); +- return eHAL_STATUS_FAILURE; +- } +- +- *set_req = *request; +- +- +- +- for( i = 0; i < set_req->ssid_count; i++){ +- +- VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, +- "%s: SSID %s \n length: %d", +- __func__, set_req->ssid[i].ssid.ssId, set_req->ssid[i].ssid.length); +- } +- +- MTRACE(vos_trace(VOS_MODULE_ID_SME, +- TRACE_CODE_SME_RX_HDD_EXTSCAN_SET_SSID_HOTLIST, NO_SESSION, 0)); +- +- status = sme_AcquireGlobalLock(&mac->sme); +- if (eHAL_STATUS_SUCCESS == status) { +- /* Serialize the req through MC thread */ +- vos_message.bodyptr = set_req; +- vos_message.type = WDA_EXTSCAN_SET_SSID_HOTLIST_REQ; +- vstatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); +- sme_ReleaseGlobalLock(&mac->sme); +- if (!VOS_IS_STATUS_SUCCESS(vstatus)) { +- vos_mem_free(set_req); +- status = eHAL_STATUS_FAILURE; +- } +- } else { +- VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, +- "%s: sme_AcquireGlobalLock error", __func__); +- vos_mem_free(set_req); +- status = eHAL_STATUS_FAILURE; +- } +- return status; +-} +- +-/** +- * sme_reset_ssid_hotlist() - Set the SSID hotlist +- * @hal: SME handle +- * @request: reset ssid hotlist request +- * +- * Return: eHalStatus +- */ +-eHalStatus +-sme_reset_ssid_hotlist(tHalHandle hal, +- tSirEXTScanResetSsidHotlistReqParams *request) +-{ +- eHalStatus status; +- VOS_STATUS vstatus; +- tpAniSirGlobal mac = PMAC_STRUCT(hal); +- vos_msg_t vos_message; +- tSirEXTScanResetSsidHotlistReqParams *set_req; +- +- set_req = vos_mem_malloc(sizeof(*set_req)); +- if (!set_req) { +- VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, +- "%s: Not able to allocate memory for WDA_EXTSCAN_SET_SSID_HOTLIST_REQ", +- __func__); +- return eHAL_STATUS_FAILURE; +- } +- +- *set_req = *request; +- +- MTRACE(vos_trace(VOS_MODULE_ID_SME, +- TRACE_CODE_SME_RX_HDD_EXTSCAN_RESET_SSID_HOTLIST, NO_SESSION, 0)); +- +- status = sme_AcquireGlobalLock(&mac->sme); +- if (eHAL_STATUS_SUCCESS == status) { +- /* Serialize the req through MC thread */ +- vos_message.bodyptr = set_req; +- vos_message.type = WDA_EXTSCAN_RESET_SSID_HOTLIST_REQ; +- vstatus = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message); +- sme_ReleaseGlobalLock(&mac->sme); +- if (!VOS_IS_STATUS_SUCCESS(vstatus)) { +- vos_mem_free(set_req); +- status = eHAL_STATUS_FAILURE; +- } +- } else { +- VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, +- "%s: sme_AcquireGlobalLock error", __func__); +- vos_mem_free(set_req); +- status = eHAL_STATUS_FAILURE; +- } +- return status; +-} +- +- + /* --------------------------------------------------------------------------- + \fn sme_getCachedResults + \brief SME API to get cached results +diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c +index 5d58542..83a5229 100644 +--- a/CORE/WDA/src/wlan_qct_wda.c ++++ b/CORE/WDA/src/wlan_qct_wda.c +@@ -259,10 +259,6 @@ VOS_STATUS WDA_ProcessEXTScanSetBSSIDHotlistReq(tWDA_CbContext *pWDA, + tSirEXTScanSetBssidHotListReqParams *wdaRequest); + VOS_STATUS WDA_ProcessEXTScanResetBSSIDHotlistReq(tWDA_CbContext *pWDA, + tSirEXTScanResetBssidHotlistReqParams *wdaRequest); +-VOS_STATUS WDA_ProcessEXTScanSetSSIDHotlistReq(tWDA_CbContext *pWDA, +- tSirEXTScanSetSsidHotListReqParams *wdaRequest); +-VOS_STATUS WDA_ProcessEXTScanResetSSIDHotlistReq(tWDA_CbContext *pWDA, +- tSirEXTScanResetSsidHotlistReqParams *wdaRequest); + VOS_STATUS WDA_ProcessHighPriorityDataInfoInd(tWDA_CbContext *pWDA, + tSirHighPriorityDataInfoInd *wdaRequest); + #endif /* WLAN_FEATURE_EXTSCAN */ +@@ -16144,18 +16140,6 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) + (tSirEXTScanResetBssidHotlistReqParams *)pMsg->bodyptr); + break; + } +- case WDA_EXTSCAN_SET_SSID_HOTLIST_REQ: +- { +- WDA_ProcessEXTScanSetSSIDHotlistReq(pWDA, +- (tSirEXTScanSetSsidHotListReqParams *)pMsg->bodyptr); +- break; +- } +- case WDA_EXTSCAN_RESET_SSID_HOTLIST_REQ: +- { +- WDA_ProcessEXTScanResetSSIDHotlistReq(pWDA, +- (tSirEXTScanResetSsidHotlistReqParams *)pMsg->bodyptr); +- break; +- } + case WDA_HIGH_PRIORITY_DATA_INFO_IND: + { + WDA_ProcessHighPriorityDataInfoInd(pWDA, +@@ -17384,7 +17368,6 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, + case WDI_EXTSCAN_SCAN_AVAILABLE_IND: + case WDI_EXTSCAN_SCAN_RESULT_IND: + case WDI_EXTSCAN_BSSID_HOTLIST_RESULT_IND: +- case WDI_EXTSCAN_SSID_HOTLIST_RESULT_IND: + { + void *pEXTScanData; + void *pCallbackContext; +@@ -17431,14 +17414,6 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, + VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "WDI_EXTSCAN Indication is WDI_EXTSCAN_BSSID_HOTLIST_RESULT_IND"); + } +- if (wdiLowLevelInd->wdiIndicationType == +- WDI_EXTSCAN_SSID_HOTLIST_RESULT_IND) +- { +- indType = WDA_EXTSCAN_SSID_HOTLIST_RESULT_IND; +- +- VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, +- "WDI_EXTSCAN Indication is WDI_EXTSCAN_SSID_HOTLIST_RESULT_IND"); +- } + + pEXTScanData = + (void *)wdiLowLevelInd->wdiIndicationData.pEXTScanIndData; +@@ -21017,160 +20992,6 @@ error: + } + + /*========================================================================== +- FUNCTION WDA_EXTScanSetSSIDHotlistRspCallback +- +- DESCRIPTION +- API to send EXTScan Set SSID Hotlist Response to HDD +- +- PARAMETERS +- pEventData: Response from FW +- pUserData: +-===========================================================================*/ +-void WDA_EXTScanSetSSIDHotlistRspCallback(void *pEventData, void* pUserData) +-{ +- tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; +- tWDA_CbContext *pWDA = NULL; +- void *pCallbackContext; +- tpAniSirGlobal pMac; +- +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, +- "%s: ", __func__); +- if (NULL == pWdaParams) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s: pWdaParams received NULL", __func__); +- VOS_ASSERT(0) ; +- return; +- } +- +- pWDA = (tWDA_CbContext *) pWdaParams->pWdaContext; +- +- if (NULL == pWDA) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s: pWDA received NULL", __func__); +- VOS_ASSERT(0); +- goto error; +- } +- +- pMac = (tpAniSirGlobal )VOS_GET_MAC_CTXT(pWDA->pVosContext); +- if (NULL == pMac) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s:pMac is NULL", __func__); +- VOS_ASSERT(0); +- goto error; +- } +- +- pCallbackContext = pMac->sme.pEXTScanCallbackContext; +- +- if (pMac->sme.pEXTScanIndCb) +- { +- pMac->sme.pEXTScanIndCb(pCallbackContext, +- WDA_EXTSCAN_SET_SSID_HOTLIST_RSP, +- pEventData); +- } +- else +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s:HDD callback is null", __func__); +- VOS_ASSERT(0); +- } +- +- +-error: +- +- if (pWdaParams->wdaWdiApiMsgParam != NULL) +- { +- vos_mem_free(pWdaParams->wdaWdiApiMsgParam); +- } +- if (pWdaParams->wdaMsgParam != NULL) +- { +- vos_mem_free(pWdaParams->wdaMsgParam); +- } +- vos_mem_free(pWdaParams) ; +- +- return; +-} +- +-/*========================================================================== +- FUNCTION WDA_EXTScanResetSSIDHotlistRspCallback +- +- DESCRIPTION +- API to send EXTScan ReSet SSID Hotlist Response to HDD +- +- PARAMETERS +- pEventData: Response from FW +- pUserData: +-===========================================================================*/ +-void WDA_EXTScanResetSSIDHotlistRspCallback(void *pEventData, void* pUserData) +-{ +- tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; +- tWDA_CbContext *pWDA = NULL; +- void *pCallbackContext; +- tpAniSirGlobal pMac; +- +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, +- "%s:", __func__); +- if (NULL == pWdaParams) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s: pWdaParams received NULL", __func__); +- VOS_ASSERT(0) ; +- return; +- } +- +- pWDA = (tWDA_CbContext *) pWdaParams->pWdaContext; +- +- if (NULL == pWDA) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s: pWDA received NULL", __func__); +- VOS_ASSERT(0); +- goto error; +- } +- +- pMac = (tpAniSirGlobal )VOS_GET_MAC_CTXT(pWDA->pVosContext); +- if (NULL == pMac) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s:pMac is NULL", __func__); +- VOS_ASSERT(0); +- goto error; +- } +- +- pCallbackContext = pMac->sme.pEXTScanCallbackContext; +- +- if (pMac->sme.pEXTScanIndCb) +- { +- pMac->sme.pEXTScanIndCb(pCallbackContext, +- WDA_EXTSCAN_RESET_SSID_HOTLIST_RSP, +- pEventData); +- } +- else +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s:HDD callback is null", __func__); +- VOS_ASSERT(0); +- } +- +- +-error: +- +- if (pWdaParams->wdaWdiApiMsgParam != NULL) +- { +- vos_mem_free(pWdaParams->wdaWdiApiMsgParam); +- } +- if (pWdaParams->wdaMsgParam != NULL) +- { +- vos_mem_free(pWdaParams->wdaMsgParam); +- } +- vos_mem_free(pWdaParams) ; +- +- return; +-} +- +-/*========================================================================== + FUNCTION WDA_ProcessEXTScanStartReq + + DESCRIPTION +@@ -21429,92 +21250,6 @@ VOS_STATUS WDA_ProcessEXTScanResetBSSIDHotlistReq(tWDA_CbContext *pWDA, + } + + /*========================================================================== +- FUNCTION WDA_ProcessEXTScanSetSSIDHotlistReq +- +- DESCRIPTION +- API to send Set SSID Hotlist Request to WDI +- +- PARAMETERS +- pWDA: Pointer to WDA context +- wdaRequest: Pointer to EXTScan req parameters +-===========================================================================*/ +-VOS_STATUS WDA_ProcessEXTScanSetSSIDHotlistReq(tWDA_CbContext *pWDA, +- tSirEXTScanSetSsidHotListReqParams *wdaRequest) +-{ +- WDI_Status status = WDI_STATUS_SUCCESS; +- tWDA_ReqParams *pWdaParams; +- +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, +- "%s: ", __func__); +- pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)); +- if (NULL == pWdaParams) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s: VOS MEM Alloc Failure", __func__); +- VOS_ASSERT(0); +- return VOS_STATUS_E_NOMEM; +- } +- pWdaParams->pWdaContext = pWDA; +- pWdaParams->wdaMsgParam = wdaRequest; +- pWdaParams->wdaWdiApiMsgParam = NULL; +- +- status = WDI_EXTScanSetSSIDHotlistReq((void *)wdaRequest, +- (WDI_EXTScanSetSSIDHotlistRspCb)WDA_EXTScanSetSSIDHotlistRspCallback, +- (void *)pWdaParams); +- if (IS_WDI_STATUS_FAILURE(status)) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "Failure to request. Free all the memory " ); +- vos_mem_free(pWdaParams->wdaMsgParam); +- vos_mem_free(pWdaParams); +- } +- return CONVERT_WDI2VOS_STATUS(status); +-} +- +-/*========================================================================== +- FUNCTION WDA_ProcessEXTScanReSetSSIDHotlistReq +- +- DESCRIPTION +- API to send Reset SSID Hotlist Request to WDI +- +- PARAMETERS +- pWDA: Pointer to WDA context +- wdaRequest: Pointer to EXTScan req parameters +-===========================================================================*/ +-VOS_STATUS WDA_ProcessEXTScanResetSSIDHotlistReq(tWDA_CbContext *pWDA, +- tSirEXTScanResetSsidHotlistReqParams *wdaRequest) +-{ +- WDI_Status status = WDI_STATUS_SUCCESS; +- tWDA_ReqParams *pWdaParams; +- +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, +- "%s:", __func__); +- pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)); +- if (NULL == pWdaParams) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "%s: VOS MEM Alloc Failure", __func__); +- VOS_ASSERT(0); +- return VOS_STATUS_E_NOMEM; +- } +- pWdaParams->pWdaContext = pWDA; +- pWdaParams->wdaMsgParam = wdaRequest; +- pWdaParams->wdaWdiApiMsgParam = NULL; +- +- status = WDI_EXTScanResetSSIDHotlistReq((void *)wdaRequest, +- (WDI_EXTScanResetSSIDHotlistRspCb)WDA_EXTScanResetSSIDHotlistRspCallback, +- (void *)pWdaParams); +- if (IS_WDI_STATUS_FAILURE(status)) +- { +- VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, +- "Failure to request. Free all the memory " ); +- vos_mem_free(pWdaParams->wdaMsgParam); +- vos_mem_free(pWdaParams); +- } +- return CONVERT_WDI2VOS_STATUS(status); +-} +- +-/*========================================================================== + FUNCTION WDA_ProcessHighPriorityDataInfoInd + + DESCRIPTION +diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h +index 595dec2..65461f7 100644 +--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h ++++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h +@@ -421,7 +421,6 @@ typedef enum + WDI_EXTSCAN_SCAN_RESULT_IND, + WDI_EXTSCAN_GET_CAPABILITIES_IND, + WDI_EXTSCAN_BSSID_HOTLIST_RESULT_IND, +- WDI_EXTSCAN_SSID_HOTLIST_RESULT_IND, + #endif + /*Delete BA Ind*/ + WDI_DEL_BA_IND, +@@ -6126,7 +6125,6 @@ typedef struct + #define WDI_WLAN_EXTSCAN_MAX_CHANNELS 16 + #define WDI_WLAN_EXTSCAN_MAX_BUCKETS 16 + #define WDI_WLAN_EXTSCAN_MAX_HOTLIST_APS 128 +-#define WDI_WLAN_EXTSCAN_MAX_HOTLIST_SSID 8 + + typedef enum + { +@@ -6234,14 +6232,6 @@ typedef struct + + typedef struct + { +- WDI_MacSSid ssid; /* SSID */ +- wpt_uint8 band; /* band */ +- wpt_int32 lowRssiThreshold; /* low threshold */ +- wpt_int32 highRssiThreshold; /* high threshold */ +-} WDI_SSIDThresholdParam; +- +-typedef struct +-{ + wpt_int32 requestId; + wpt_int8 sessionId; // session Id mapped to vdev_id + wpt_uint32 lostBssidSampleSize; +@@ -6261,21 +6251,6 @@ typedef struct + wpt_uint32 reserved; + } WDI_HighPriorityDataInfoIndParams; + +-typedef struct +-{ +- wpt_int32 requestId; +- wpt_int8 sessionId; // session Id mapped to vdev_id +- wpt_uint32 lostSsidSampleSize; +- wpt_uint32 numSsid; // number of hotlist APs +- WDI_SSIDThresholdParam ssid[WDI_WLAN_EXTSCAN_MAX_HOTLIST_SSID]; // hotlist SSIDs +-} WDI_EXTScanSetSSIDHotlistReqParams; +- +-typedef struct +-{ +- wpt_uint32 requestId; +- wpt_uint8 sessionId; +-} WDI_EXTScanResetSSIDHotlistReqParams; +- + #endif /* WLAN_FEATURE_EXTSCAN */ + + #ifdef WLAN_FEATURE_LINK_LAYER_STATS +@@ -8409,10 +8384,8 @@ typedef void (*WDI_EXTScanSetBSSIDHotlistRspCb)(void *pEventData, + void *pUserData); + typedef void (*WDI_EXTScanResetBSSIDHotlistRspCb)(void *pEventData, + void *pUserData); +-typedef void (*WDI_EXTScanSetSSIDHotlistRspCb)(void *pEventData, +- void *pUserData); +-typedef void (*WDI_EXTScanResetSSIDHotlistRspCb)(void *pEventData, +- void *pUserData); ++ ++ + #endif /* WLAN_FEATURE_EXTSCAN */ + + #ifdef WLAN_FEATURE_LINK_LAYER_STATS +@@ -11865,40 +11838,6 @@ WDI_Status WDI_EXTScanResetBSSIDHotlistReq + ); + + /** +- @brief WDI_EXTScanSetSSIDHotlistReq +- This API is called to send Set SSID Hotlist Request FW +- +- @param pwdiEXTScanSetBssidHotlistReqParams : pointer to the request params. +- wdiEXTScanSetBSSIDHotlistRspCb : callback on getting the response. +- usrData : Client context +- @see +- @return SUCCESS or FAIL +-*/ +-WDI_Status WDI_EXTScanSetSSIDHotlistReq +-( +- WDI_EXTScanSetSSIDHotlistReqParams* pwdiEXTScanSetSSIDHotlistReqParams, +- WDI_EXTScanSetSSIDHotlistRspCb wdiEXTScanSetSSIDHotlistRspCb, +- void* pUserData +-); +- +-/** +- @brief WDI_EXTScanResetSSIDHotlistReq +- This API is called to send Reset SSID Hotlist Request FW +- +- @param pwdiEXTScanResetSsidHotlistReqParams : pointer to the request params. +- wdiEXTScanGetCachedResultsRspCb : callback on getting the response. +- usrData : Client context +- @see +- @return SUCCESS or FAIL +-*/ +-WDI_Status WDI_EXTScanResetSSIDHotlistReq +-( +- WDI_EXTScanResetSSIDHotlistReqParams* pwdiEXTScanResetSSIDHotlistReqParams, +- WDI_EXTScanResetSSIDHotlistRspCb wdiEXTScanResetSSIDHotlistRspCb, +- void* pUserData +-); +- +-/** + @brief WDI_HighPriorityDataInfoInd + + @param pHighPriorityDataInfoIndParams: Req parameter for the FW +diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h +index 4b74e41..d0faaf0 100644 +--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h ++++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h +@@ -465,8 +465,6 @@ typedef enum + WDI_EXTSCAN_GET_CAPABILITIES_REQ = 98, + WDI_EXTSCAN_SET_BSSID_HOTLIST_REQ = 99, + WDI_EXTSCAN_RESET_BSSID_HOTLIST_REQ = 100, +- WDI_EXTSCAN_SET_SSID_HOTLIST_REQ = 101, +- WDI_EXTSCAN_RESET_SSID_HOTLIST_REQ = 102, + #endif + + WDI_SPOOF_MAC_ADDR_REQ = 103, +@@ -847,8 +845,6 @@ typedef enum + WDI_EXTSCAN_GET_CAPABILITIES_RSP = 98, + WDI_EXTSCAN_SET_HOTLIST_BSSID_RSP = 99, + WDI_EXTSCAN_RESET_HOTLIST_BSSID_RSP = 100, +- WDI_EXTSCAN_SET_HOTLIST_SSID_RSP = 101, +- WDI_EXTSCAN_RESET_HOTLIST_SSID_RSP = 102, + #endif + WDI_SPOOF_MAC_ADDR_RSP = 103, + WDI_GET_FW_STATS_RSP = 104, +@@ -958,7 +954,6 @@ typedef enum + WDI_HAL_EXTSCAN_SCAN_AVAILABLE_IND = WDI_HAL_IND_MIN + 24, + WDI_HAL_EXTSCAN_RESULT_IND = WDI_HAL_IND_MIN + 25, + WDI_HAL_EXTSCAN_BSSID_HOTLIST_RESULT_IND = WDI_HAL_IND_MIN + 26, +- WDI_HAL_EXTSCAN_SSID_HOTLIST_RESULT_IND = WDI_HAL_IND_MIN + 27, + #endif + WDI_TDLS_CHAN_SWITCH_REQ_RESP = WDI_HAL_IND_MIN + 28, + WDI_HAL_DEL_BA_IND = WDI_HAL_IND_MIN + 29, +@@ -6197,34 +6192,6 @@ WDI_ProcessEXTScanResetHotlistBSSIDRsp + ); + + WDI_Status +-WDI_ProcessEXTScanSetSSIDHotlistReq +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-); +- +-WDI_Status +-WDI_ProcessEXTScanSetHotlistSSIDRsp +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-); +- +-WDI_Status +-WDI_ProcessEXTScanResetSSIDHotlistReq +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-); +- +-WDI_Status +-WDI_ProcessEXTScanResetHotlistSSIDRsp +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-); +- +-WDI_Status + WDI_ProcessHighPriorityDataInfoInd + ( + WDI_ControlBlockType* pWDICtx, +@@ -6252,14 +6219,6 @@ WDI_ProcessEXTScanBssidHotListResultInd + WDI_EventInfoType* pEventData + ); + +-WDI_Status +-WDI_ProcessEXTScanSsidHotListResultInd +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-); +- +- + #endif /* WLAN_FEATURE_EXTSCAN */ + + #ifdef WLAN_FEATURE_LINK_LAYER_STATS +diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c +index ec83707..4dd8722 100644 +--- a/CORE/WDI/CP/src/wlan_qct_wdi.c ++++ b/CORE/WDI/CP/src/wlan_qct_wdi.c +@@ -485,8 +485,8 @@ WDI_ReqProcFuncType pfnReqProcTbl[WDI_MAX_UMAC_IND] = + WDI_ProcessEXTScanGetCapabilitiesReq, /* WDI_EXTSCAN_GET_CAPABILITIES_REQ */ + WDI_ProcessEXTScanSetBSSIDHotlistReq, /* WDI_EXTSCAN_SET_BSSID_HOTLIST_REQ */ + WDI_ProcessEXTScanResetBSSIDHotlistReq, /* WDI_EXTSCAN_RESET_BSSID_HOTLIST_REQ */ +- WDI_ProcessEXTScanSetSSIDHotlistReq, /* WDI_EXTSCAN_SET_SSID_HOTLIST_REQ */ +- WDI_ProcessEXTScanResetSSIDHotlistReq, /* WDI_EXTSCAN_RESET_SSID_HOTLIST_REQ */ ++ NULL, /* maintain synchronization though SSID_HOTLIST is deprecated */ ++ NULL, + #else + NULL, + NULL, +@@ -812,8 +812,8 @@ WDI_RspProcFuncType pfnRspProcTbl[WDI_MAX_RESP] = + WDI_ProcessEXTScanGetCapabilitiesRsp, /* WDI_EXTSCAN_GET_CAPABILITIES_RSP */ + WDI_ProcessEXTScanSetHotlistBSSIDRsp, /* WDI_EXTSCAN_SET_HOTLIST_BSSID_RSP */ + WDI_ProcessEXTScanResetHotlistBSSIDRsp, /* WDI_EXTSCAN_RESET_HOTLIST_BSSID_RSP */ +- WDI_ProcessEXTScanSetHotlistSSIDRsp, /* WDI_EXTSCAN_SET_HOTLIST_SSID_RSP */ +- WDI_ProcessEXTScanResetHotlistSSIDRsp, /* WDI_EXTSCAN_RESET_HOTLIST_SSID_RSP */ ++ NULL, /* maintain synchronization though SSID_HOTLIST is deprecated */ ++ NULL, + #else + NULL, + NULL, +@@ -934,7 +934,7 @@ WDI_RspProcFuncType pfnRspProcTbl[WDI_MAX_RESP] = + WDI_ProcessEXTScanScanAvailableInd, /* WDI_HAL_EXTSCAN_SCAN_AVAILABLE_IND */ + WDI_ProcessEXTScanResultInd, /* WDI_HAL_EXTSCAN_RESULT_IND */ + WDI_ProcessEXTScanBssidHotListResultInd, /* WDI_HAL_EXTSCAN_BSSID_HOTLIST_RESULT_IND */ +- WDI_ProcessEXTScanSsidHotListResultInd, /* WDI_HAL_EXTSCAN_SSID_HOTLIST_RESULT_IND */ ++ NULL, /* maintain synchronization though SSID_HOTLIST is deprecated */ + #else + NULL, + NULL, +@@ -1290,8 +1290,6 @@ static char *WDI_getReqMsgString(wpt_uint16 wdiReqMsgId) + CASE_RETURN_STRING( WDI_EXTSCAN_GET_CAPABILITIES_REQ); + CASE_RETURN_STRING( WDI_EXTSCAN_SET_BSSID_HOTLIST_REQ); + CASE_RETURN_STRING( WDI_EXTSCAN_RESET_BSSID_HOTLIST_REQ); +- CASE_RETURN_STRING( WDI_EXTSCAN_SET_SSID_HOTLIST_REQ); +- CASE_RETURN_STRING( WDI_EXTSCAN_RESET_SSID_HOTLIST_REQ); + CASE_RETURN_STRING( WDI_HIGH_PRIORITY_DATA_INFO_IND); + #endif /* WLAN_FEATURE_EXTSCAN */ + CASE_RETURN_STRING( WDI_SPOOF_MAC_ADDR_REQ); +@@ -1523,13 +1521,10 @@ static char *WDI_getRespMsgString(wpt_uint16 wdiRespMsgId) + CASE_RETURN_STRING( WDI_EXTSCAN_GET_CAPABILITIES_RSP); + CASE_RETURN_STRING( WDI_EXTSCAN_SET_HOTLIST_BSSID_RSP); + CASE_RETURN_STRING( WDI_EXTSCAN_RESET_HOTLIST_BSSID_RSP); +- CASE_RETURN_STRING( WDI_EXTSCAN_SET_HOTLIST_SSID_RSP); +- CASE_RETURN_STRING( WDI_EXTSCAN_RESET_HOTLIST_SSID_RSP); + CASE_RETURN_STRING( WDI_HAL_EXTSCAN_PROGRESS_IND); + CASE_RETURN_STRING( WDI_HAL_EXTSCAN_SCAN_AVAILABLE_IND); + CASE_RETURN_STRING( WDI_HAL_EXTSCAN_RESULT_IND); + CASE_RETURN_STRING( WDI_HAL_EXTSCAN_BSSID_HOTLIST_RESULT_IND); +- CASE_RETURN_STRING( WDI_HAL_EXTSCAN_SSID_HOTLIST_RESULT_IND); + #endif /* WLAN_FEATURE_EXTSCAN */ + CASE_RETURN_STRING( WDI_GET_FW_STATS_RSP); + CASE_RETURN_STRING( WDI_ENCRYPT_MSG_RSP); +@@ -24849,10 +24844,6 @@ WDI_2_HAL_REQ_TYPE + return WLAN_HAL_BSSID_HOTLIST_SET_REQ; + case WDI_EXTSCAN_RESET_BSSID_HOTLIST_REQ: + return WLAN_HAL_BSSID_HOTLIST_RESET_REQ; +- case WDI_EXTSCAN_SET_SSID_HOTLIST_REQ: +- return WLAN_HAL_SSID_HOTLIST_SET_REQ; +- case WDI_EXTSCAN_RESET_SSID_HOTLIST_REQ: +- return WLAN_HAL_SSID_HOTLIST_RESET_REQ; + case WDI_HIGH_PRIORITY_DATA_INFO_IND: + return WLAN_HAL_HIGH_PRIORITY_DATA_INFO_REQ; + #endif /* WLAN_FEATURE_EXTSCAN */ +@@ -25216,10 +25207,6 @@ case WLAN_HAL_DEL_STA_SELF_RSP: + return WDI_EXTSCAN_SET_HOTLIST_BSSID_RSP; + case WLAN_HAL_BSSID_HOTLIST_RESET_RSP: + return WDI_EXTSCAN_RESET_HOTLIST_BSSID_RSP; +- case WLAN_HAL_SSID_HOTLIST_SET_RSP: +- return WDI_EXTSCAN_SET_HOTLIST_SSID_RSP; +- case WLAN_HAL_SSID_HOTLIST_RESET_RSP: +- return WDI_EXTSCAN_RESET_HOTLIST_SSID_RSP; + case WLAN_HAL_EXT_SCAN_PROGRESS_IND: + return WDI_HAL_EXTSCAN_PROGRESS_IND; + case WLAN_HAL_EXT_SCAN_RESULT_AVAILABLE_IND: +@@ -25228,8 +25215,6 @@ case WLAN_HAL_DEL_STA_SELF_RSP: + return WDI_HAL_EXTSCAN_RESULT_IND; + case WLAN_HAL_BSSID_HOTLIST_RESULT_IND: + return WDI_HAL_EXTSCAN_BSSID_HOTLIST_RESULT_IND; +- case WLAN_HAL_SSID_HOTLIST_RESULT_IND: +- return WDI_HAL_EXTSCAN_SSID_HOTLIST_RESULT_IND; + #endif /* WLAN_FEATURE_EXTSCAN */ + case WLAN_HAL_MAC_SPOOFED_SCAN_RSP: + return WDI_SPOOF_MAC_ADDR_RSP; +@@ -34293,60 +34278,6 @@ WDI_ProcessEXTScanBssidHotListResultInd + } /* End of WDI_ProcessEXTScanBssidHotListResultInd */ + + /** +- @brief Process EXTScan SSID Hotlist Result Indication indication from FW +- +- @param pWDICtx: pointer to the WLAN DAL context +- pEventData: pointer to the event information structure +- +- @see +- @return Result of the function call +-*/ +-WDI_Status +-WDI_ProcessEXTScanSsidHotListResultInd +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-) +-{ +- WDI_LowLevelIndType wdiInd; +- /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s: ", __func__); +- +- /* sanity check */ +- if (( NULL == pWDICtx ) || ( NULL == pEventData ) || +- ( NULL == pEventData->pEventData)) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, +- "%s: Invalid parameters", __func__); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- +- /* Fill in the indication parameters */ +- wdiInd.wdiIndicationType = WDI_EXTSCAN_SSID_HOTLIST_RESULT_IND; +- +- /* extract response and send it to UMAC */ +- wdiInd.wdiIndicationData.pEXTScanIndData = (void *)pEventData->pEventData; +- +- /* Notify UMAC */ +- if (pWDICtx->wdiLowLevelIndCB) +- { +- pWDICtx->wdiLowLevelIndCB( &wdiInd, pWDICtx->pIndUserData ); +- } +- else +- { +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s: WDILowLevelIndCb is null", __func__); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- return WDI_STATUS_SUCCESS; +-} /* End of WDI_ProcessEXTScanSsidHotListResultInd */ +- +- +-/** + @brief WDI_EXTScanGetCapabilitiesReq + + @param WDI_EXTScanGetCapabilitiesReqParams: Req parameter for the FW +@@ -35199,286 +35130,6 @@ WDI_ProcessEXTScanResetBSSIDHotlistReq + WDI_EXTSCAN_RESET_HOTLIST_BSSID_RSP); + } + +- +-/** +- @brief WDI_EXTScanSetSSIDHotlistReq +- +- @param WDI_EXTScanSetSSIDHotlistReqParams: Req parameter for the FW +- WDI_EXTScanSetSSIDHotlistRspCb: callback for passing back the response +- of the Req operation received from the device +- pUserData: user data will be passed back with the callback +- +- @return SUCCESS or FAIL +-*/ +-WDI_Status +-WDI_EXTScanSetSSIDHotlistReq( +- WDI_EXTScanSetSSIDHotlistReqParams* pwdiEXTScanSetSSIDHotlistReqParams, +- WDI_EXTScanSetSSIDHotlistRspCb wdiEXTScanSetSSIDHotlistRspCb, +- void* pUserData) +-{ +- WDI_EventInfoType wdiEventData; +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s: %d Enter ",__func__, __LINE__); +- /*------------------------------------------------------------------------ +- Sanity Check +- ------------------------------------------------------------------------*/ +- if ( eWLAN_PAL_FALSE == gWDIInitialized ) +- { +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR, +- "WDI API call before module is initialized - Fail request"); +- +- return WDI_STATUS_E_NOT_ALLOWED; +- } +- +- wdiEventData.wdiRequest = WDI_EXTSCAN_SET_SSID_HOTLIST_REQ; +- wdiEventData.pEventData = pwdiEXTScanSetSSIDHotlistReqParams; +- wdiEventData.uEventDataSize = sizeof(*pwdiEXTScanSetSSIDHotlistReqParams); +- wdiEventData.pCBfnc = wdiEXTScanSetSSIDHotlistRspCb; +- wdiEventData.pUserData = pUserData; +- +- return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +-} +- +-/** +- @brief WDI_ProcessEXTScanSetSSIDHotlistReq - +- Extended Scan Set SSSID Hotlist Request to FW +- +- @param pWDICtx : wdi context +- pEventData : indication data +- +- @see +- @return none +-*/ +-WDI_Status +-WDI_ProcessEXTScanSetSSIDHotlistReq +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-) +-{ +- WDI_EXTScanSetSSIDHotlistReqParams* pwdiEXTScanSetSSIDHotlistReqParams; +- WDI_EXTScanSetSSIDHotlistRspCb wdiEXTScanSetSSIDHotlistRspCb; +- wpt_uint8* pSendBuffer = NULL; +- wpt_uint16 usSendSize = 0; +- wpt_uint16 usDataOffset = 0; +- tpHalSsidHotlistSetReq pHalSsidHotlistSetReqParams; +- int i; +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s: %d Enter",__func__, __LINE__); +- +- if (( NULL == pEventData ) || ( NULL == pEventData->pEventData ) || +- ( NULL == pEventData->pCBfnc )) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, +- "%s: Invalid parameters", __func__); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- +- pwdiEXTScanSetSSIDHotlistReqParams = +- (WDI_EXTScanSetSSIDHotlistReqParams *)pEventData->pEventData; +- wdiEXTScanSetSSIDHotlistRspCb = +- (WDI_EXTScanSetSSIDHotlistRspCb)pEventData->pCBfnc; +- +- /*----------------------------------------------------------------------- +- Get message buffer +- ! TO DO : proper conversion into the HAL Message Request Format +- -----------------------------------------------------------------------*/ +- if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( +- pWDICtx, +- WDI_EXTSCAN_SET_SSID_HOTLIST_REQ, +- sizeof(tHalSsidHotlistSetReq), +- &pSendBuffer, &usDataOffset, +- &usSendSize))|| +- ( usSendSize < (usDataOffset + sizeof(tHalSsidHotlistSetReq) ))) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, +- "Unable to get send buffer in %s %p %p %p", __func__, +- pEventData, pwdiEXTScanSetSSIDHotlistReqParams, +- wdiEXTScanSetSSIDHotlistRspCb); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- pHalSsidHotlistSetReqParams = +- (tpHalSsidHotlistSetReq) (pSendBuffer + usDataOffset); +- +- pHalSsidHotlistSetReqParams->requestId = +- pwdiEXTScanSetSSIDHotlistReqParams->requestId; +- +- pHalSsidHotlistSetReqParams->sessionId = +- pwdiEXTScanSetSSIDHotlistReqParams->sessionId; +- +- pHalSsidHotlistSetReqParams->lostSsidSampleSize = +- pwdiEXTScanSetSSIDHotlistReqParams->lostSsidSampleSize;; +- +- pHalSsidHotlistSetReqParams->numSsid = +- pwdiEXTScanSetSSIDHotlistReqParams->numSsid; +- +- for( i = 0; i < pHalSsidHotlistSetReqParams->numSsid; i++){ +- +- wpalMemoryZero(pHalSsidHotlistSetReqParams->ssid[i].ssid, 33); +- wpalMemoryCopy(pHalSsidHotlistSetReqParams->ssid[i].ssid, +- pwdiEXTScanSetSSIDHotlistReqParams->ssid[i].ssid.sSSID, +- pwdiEXTScanSetSSIDHotlistReqParams->ssid[i].ssid.ucLength); +- +- pHalSsidHotlistSetReqParams->ssid[i].lowRssiThreshold = +- pwdiEXTScanSetSSIDHotlistReqParams->ssid[i].lowRssiThreshold; +- +- pHalSsidHotlistSetReqParams->ssid[i].highRssiThreshold = +- pwdiEXTScanSetSSIDHotlistReqParams->ssid[i].highRssiThreshold; +- +- pHalSsidHotlistSetReqParams->ssid[i].band = +- pwdiEXTScanSetSSIDHotlistReqParams->ssid[i].band; +- } +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "ReqID %u sessionId %u numSsid %u lost_ssid_sample_size: %u", +- pHalSsidHotlistSetReqParams->requestId, +- pHalSsidHotlistSetReqParams->sessionId, +- pHalSsidHotlistSetReqParams->numSsid, +- pHalSsidHotlistSetReqParams->lostSsidSampleSize); +- +- for( i = 0; i < pHalSsidHotlistSetReqParams->numSsid; i++){ +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s %d %d) SSID = %s lowRssiThreshold %d highRssiThreshold %d band: %d", +- __func__, __LINE__, i, +- pHalSsidHotlistSetReqParams->ssid[i].ssid, +- pHalSsidHotlistSetReqParams->ssid[i].lowRssiThreshold, +- pHalSsidHotlistSetReqParams->ssid[i].highRssiThreshold, +- pHalSsidHotlistSetReqParams->ssid[i].band); +- } +- +- pWDICtx->pReqStatusUserData = pEventData->pUserData; +- +- +- /*------------------------------------------------------------------------- +- Send EXTScan Stop Request to HAL +- -------------------------------------------------------------------------*/ +- return WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize, +- wdiEXTScanSetSSIDHotlistRspCb, pEventData->pUserData, +- WDI_EXTSCAN_SET_HOTLIST_SSID_RSP); +-} +- +-/** +- @brief WDI_EXTScanResetSSIDHotlistReq +- +- @param WDI_EXTScanResetSSIDHotlistReqParams: Req parameter for the FW +- WDI_EXTScanResetSSIDHotlistRspCb: callback for passing back the response +- of the Req operation received from the device +- pUserData: user data will be passed back with the callback +- +- @return SUCCESS or FAIL +-*/ +-WDI_Status +-WDI_EXTScanResetSSIDHotlistReq( +- WDI_EXTScanResetSSIDHotlistReqParams* pwdiEXTScanResetSSIDHotlistReqParams, +- WDI_EXTScanResetSSIDHotlistRspCb wdiEXTScanResetSSIDHotlistRspCb, +- void* pUserData) +-{ +- WDI_EventInfoType wdiEventData; +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s: %d",__func__, __LINE__); +- /*------------------------------------------------------------------------ +- Sanity Check +- ------------------------------------------------------------------------*/ +- if ( eWLAN_PAL_FALSE == gWDIInitialized ) +- { +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR, +- "WDI API call before module is initialized - Fail request"); +- +- return WDI_STATUS_E_NOT_ALLOWED; +- } +- +- wdiEventData.wdiRequest = WDI_EXTSCAN_RESET_SSID_HOTLIST_REQ; +- wdiEventData.pEventData = pwdiEXTScanResetSSIDHotlistReqParams; +- wdiEventData.uEventDataSize = sizeof(*pwdiEXTScanResetSSIDHotlistReqParams); +- wdiEventData.pCBfnc = wdiEXTScanResetSSIDHotlistRspCb; +- wdiEventData.pUserData = pUserData; +- +- return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +-} +- +-/** +- @brief WDI_ProcessEXTScanResetSSIDHotlistReq - +- Extended Scan reset SSID hotlist Request to FW +- +- @param pWDICtx : wdi context +- pEventData : indication data +- +- @see +- @return none +-*/ +-WDI_Status +-WDI_ProcessEXTScanResetSSIDHotlistReq +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-) +-{ +- WDI_EXTScanResetSSIDHotlistReqParams* pwdiEXTScanResetSSIDHotlistReqParams; +- WDI_EXTScanResetSSIDHotlistRspCb wdiEXTScanResetSSIDHotlistRspCb; +- wpt_uint8* pSendBuffer = NULL; +- wpt_uint16 usSendSize = 0; +- wpt_uint16 usDataOffset = 0; +- tpHalSsidHotlistResetReq pHalSsidHotlistResetReqParams; +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s: %d",__func__, __LINE__); +- +- if (( NULL == pEventData ) || ( NULL == pEventData->pEventData ) || +- ( NULL == pEventData->pCBfnc )) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, +- "%s: Invalid parameters", __func__); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- +- pwdiEXTScanResetSSIDHotlistReqParams = +- (WDI_EXTScanResetSSIDHotlistReqParams *)pEventData->pEventData; +- wdiEXTScanResetSSIDHotlistRspCb = +- (WDI_EXTScanResetSSIDHotlistRspCb)pEventData->pCBfnc; +- +- /*----------------------------------------------------------------------- +- Get message buffer +- ! TO DO : proper conversion into the HAL Message Request Format +- -----------------------------------------------------------------------*/ +- if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( +- pWDICtx, +- WDI_EXTSCAN_RESET_SSID_HOTLIST_REQ, +- sizeof(tHalSsidHotlistResetReq), +- &pSendBuffer, &usDataOffset, +- &usSendSize))|| +- ( usSendSize < (usDataOffset + sizeof(tHalSsidHotlistResetReq) ))) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, +- "Unable to get send buffer in %s %p %p %p", __func__, +- pEventData, pwdiEXTScanResetSSIDHotlistReqParams, +- wdiEXTScanResetSSIDHotlistRspCb); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- pHalSsidHotlistResetReqParams = +- (tpHalSsidHotlistResetReq) (pSendBuffer+usDataOffset); +- +- pHalSsidHotlistResetReqParams->requestId = +- pwdiEXTScanResetSSIDHotlistReqParams->requestId; +- +- pWDICtx->pReqStatusUserData = pEventData->pUserData; +- +- /*------------------------------------------------------------------------- +- Send RESET_HOTLIST_SSID Request to HAL +- -------------------------------------------------------------------------*/ +- return WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize, +- wdiEXTScanResetSSIDHotlistRspCb, pEventData->pUserData, +- WDI_EXTSCAN_RESET_HOTLIST_SSID_RSP); +-} +- +- + /** + @brief WDI_HighPriorityDataInfoInd + +@@ -35887,109 +35538,6 @@ WDI_ProcessEXTScanResetHotlistBSSIDRsp + + return WDI_STATUS_SUCCESS; + } +- +-/** +- @brief Process Extended Scan Set hotlist SSID Rsp function (called when a +- response is being received over the bus from HAL) +- +- @param pWDICtx: pointer to the WLAN DAL context +- pEventData: pointer to the event information structure +- +- @see +- @return Result of the function call +-*/ +-WDI_Status +-WDI_ProcessEXTScanSetHotlistSSIDRsp +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-) +-{ +- WDI_EXTScanSetSSIDHotlistRspCb wdiEXTScanSetSSIDHotlistRspCb; +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s: %d ",__func__, __LINE__); +- +- +- /*------------------------------------------------------------------------- +- Sanity check +- -------------------------------------------------------------------------*/ +- if (( NULL == pWDICtx ) || ( NULL == pEventData ) || +- ( NULL == pEventData->pEventData)) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, +- "%s: Invalid parameters", __func__); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- +- wdiEXTScanSetSSIDHotlistRspCb = +- (WDI_EXTScanSetSSIDHotlistRspCb)pWDICtx->pfncRspCB; +- if ( NULL == wdiEXTScanSetSSIDHotlistRspCb) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, +- "%s: Callback function Invalid", __func__); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- +- wdiEXTScanSetSSIDHotlistRspCb( +- (void *) pEventData->pEventData, pWDICtx->pRspCBUserData); +- +- return WDI_STATUS_SUCCESS; +-} +- +- +-/** +- @brief Process Extended Scan Reset Hotlist BSSID Rsp function (called +- when a response is being received over the bus from HAL) +- +- @param pWDICtx: pointer to the WLAN DAL context +- pEventData: pointer to the event information structure +- +- @see +- @return Result of the function call +-*/ +-WDI_Status +-WDI_ProcessEXTScanResetHotlistSSIDRsp +-( +- WDI_ControlBlockType* pWDICtx, +- WDI_EventInfoType* pEventData +-) +-{ +- WDI_EXTScanResetSSIDHotlistRspCb wdiEXTScanResetSSIDHotlistRspCb; +- +- VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO, +- "%s: %d ",__func__, __LINE__); +- +- +- /*------------------------------------------------------------------------- +- Sanity check +- -------------------------------------------------------------------------*/ +- if (( NULL == pWDICtx ) || ( NULL == pEventData ) || +- ( NULL == pEventData->pEventData)) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, +- "%s: Invalid parameters", __func__); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- +- wdiEXTScanResetSSIDHotlistRspCb = +- (WDI_EXTScanResetSSIDHotlistRspCb)pWDICtx->pfncRspCB; +- if ( NULL == wdiEXTScanResetSSIDHotlistRspCb) +- { +- WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, +- "%s: Callback function Invalid", __func__); +- WDI_ASSERT(0); +- return WDI_STATUS_E_FAILURE; +- } +- +- wdiEXTScanResetSSIDHotlistRspCb( +- (void *) pEventData->pEventData, pWDICtx->pRspCBUserData); +- +- return WDI_STATUS_SUCCESS; +-} + #endif /* WLAN_FEATURE_EXTSCAN */ + + /** +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0465/0.patch b/Patches/Linux_CVEs/CVE-2017-0465/0.patch new file mode 100644 index 00000000..cd94e134 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0465/0.patch @@ -0,0 +1,68 @@ +From 3823f0f8d0bbbbd675a42a54691f4051b3c7e544 Mon Sep 17 00:00:00 2001 +From: Sathish Ambley +Date: Wed, 25 Jan 2017 10:51:55 -0800 +Subject: msm: ADSPRPC: Check for buffer overflow condition + +The buffer length that is being passed could result in overflow +condition causing invalid memory to be accessed. + +Change-Id: I3e23f31b8cb61f8e77d09a39fab4a2d4c222cf25 +Signed-off-by: Sathish Ambley +--- + drivers/char/adsprpc.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c +index 95dca75..b8be20c 100644 +--- a/drivers/char/adsprpc.c ++++ b/drivers/char/adsprpc.c +@@ -805,9 +805,9 @@ static int overlap_ptr_cmp(const void *a, const void *b) + return st == 0 ? ed : st; + } + +-static void context_build_overlap(struct smq_invoke_ctx *ctx) ++static int context_build_overlap(struct smq_invoke_ctx *ctx) + { +- int i; ++ int i, err = 0; + remote_arg_t *lpra = ctx->lpra; + int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); + int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); +@@ -816,6 +816,11 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) + for (i = 0; i < nbufs; ++i) { + ctx->overs[i].start = (uintptr_t)lpra[i].buf.pv; + ctx->overs[i].end = ctx->overs[i].start + lpra[i].buf.len; ++ if (lpra[i].buf.len) { ++ VERIFY(err, ctx->overs[i].end > ctx->overs[i].start); ++ if (err) ++ goto bail; ++ } + ctx->overs[i].raix = i; + ctx->overps[i] = &ctx->overs[i]; + } +@@ -841,6 +846,8 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) + max = *ctx->overps[i]; + } + } ++bail: ++ return err; + } + + #define K_COPY_FROM_USER(err, kernel, dst, src, size) \ +@@ -913,8 +920,11 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, + } + + ctx->sc = invoke->sc; +- if (bufs) +- context_build_overlap(ctx); ++ if (bufs) { ++ VERIFY(err, 0 == context_build_overlap(ctx)); ++ if (err) ++ goto bail; ++ } + ctx->retval = -1; + ctx->pid = current->pid; + ctx->tgid = current->tgid; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0507/0.patch b/Patches/Linux_CVEs/CVE-2017-0507/0.patch new file mode 100644 index 00000000..3c43eb3c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0507/0.patch @@ -0,0 +1,67 @@ +From 03c26a1d8c8687131da151c2e4bd5a04d08e0dec Mon Sep 17 00:00:00 2001 +From: Ariel Yin +Date: Fri, 13 Jan 2017 15:05:54 -0800 +Subject: [PATCH] ANDROID: ion: check for kref overflow + +Userspace can cause the kref to handles to increment +arbitrarily high. Ensure it does not overflow. + +Signed-off-by: Daniel Rosenberg + +Bug: 31992382 +Test: See bug for poc +Change-Id: I6bff1df385742b1d836d43180dc87fadcea80782 +--- + drivers/staging/android/ion/ion.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c +index cc1b3bff392ac..48b6b86a61945 100644 +--- a/drivers/staging/android/ion/ion.c ++++ b/drivers/staging/android/ion/ion.c +@@ -16,6 +16,8 @@ + * + */ + ++#include ++#include + #include + #include + #include +@@ -400,6 +402,15 @@ static void ion_handle_get(struct ion_handle *handle) + kref_get(&handle->ref); + } + ++/* Must hold the client lock */ ++static struct ion_handle* ion_handle_get_check_overflow(struct ion_handle *handle) ++{ ++ if (atomic_read(&handle->ref.refcount) + 1 == 0) ++ return ERR_PTR(-EOVERFLOW); ++ ion_handle_get(handle); ++ return handle; ++} ++ + int ion_handle_put_nolock(struct ion_handle *handle) + { + int ret; +@@ -445,9 +456,9 @@ struct ion_handle *ion_handle_get_by_id_nolock(struct ion_client *client, + + handle = idr_find(&client->idr, id); + if (handle) +- ion_handle_get(handle); ++ return ion_handle_get_check_overflow(handle); + +- return handle ? handle : ERR_PTR(-EINVAL); ++ return ERR_PTR(-EINVAL); + } + + struct ion_handle *ion_handle_get_by_id(struct ion_client *client, +@@ -1339,7 +1350,7 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) + /* if a handle exists for this buffer just take a reference to it */ + handle = ion_handle_lookup(client, buffer); + if (!IS_ERR(handle)) { +- ion_handle_get(handle); ++ handle = ion_handle_get_check_overflow(handle); + mutex_unlock(&client->lock); + goto end; + } diff --git a/Patches/Linux_CVEs/CVE-2017-0509/0.patch b/Patches/Linux_CVEs/CVE-2017-0509/0.patch new file mode 100644 index 00000000..a14fce76 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0509/0.patch @@ -0,0 +1,4341 @@ +From 9c5e11d70f209553d023ea2b79efe7b2bf85fd5e Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Tue, 3 Jan 2017 16:21:01 -0800 +Subject: [PATCH] net: wireless: bcmdhd: remove unsed WEXT file. + +WEXT API was already obsoleted and should be removed. + +Bug: 34199963 +Change-Id: Iffb1c81afb9874120c64008c1072eebb8695c65f +Signed-off-by: Insun Song +Bug: 32124445 +--- + drivers/net/wireless/bcmdhd/Kconfig | 8 - + drivers/net/wireless/bcmdhd/dhd_common.c | 203 -- + drivers/net/wireless/bcmdhd/dhd_custom_gpio.c | 7 +- + drivers/net/wireless/bcmdhd/dhd_linux.c | 90 - + drivers/net/wireless/bcmdhd/dhd_linux.h | 5 +- + drivers/net/wireless/bcmdhd/wl_iw.c | 3696 ------------------------- + drivers/net/wireless/bcmdhd/wl_iw.h | 161 -- + 7 files changed, 7 insertions(+), 4163 deletions(-) + delete mode 100644 drivers/net/wireless/bcmdhd/wl_iw.c + delete mode 100644 drivers/net/wireless/bcmdhd/wl_iw.h + +diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig +index b19c557c8e61b..1ec72f8af16a3 100644 +--- a/drivers/net/wireless/bcmdhd/Kconfig ++++ b/drivers/net/wireless/bcmdhd/Kconfig +@@ -43,14 +43,6 @@ config BCMDHD_NVRAM_PATH + ---help--- + Path to the calibration file. + +-config BCMDHD_WEXT +- bool "Enable WEXT support" +- depends on BCMDHD && CFG80211 = n +- select WIRELESS_EXT +- select WEXT_PRIV +- help +- Enables WEXT support +- + config DHD_USE_STATIC_BUF + bool "Enable memory preallocation" + depends on BCMDHD +diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c +index 0b2ab8e8ac78f..1f457fae6b178 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_common.c ++++ b/drivers/net/wireless/bcmdhd/dhd_common.c +@@ -84,9 +84,6 @@ extern void htsf_update(struct dhd_info *dhd, void *data); + #endif + int dhd_msg_level = DHD_ERROR_VAL; + +- +-#include +- + #ifdef SOFTAP + char fw_path2[MOD_PARAM_PATHLEN]; + extern bool softap_enabled; +@@ -2732,203 +2729,3 @@ wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, + return 1; + } + +-/* +- * channel list parsing from cscan tlv list +-*/ +-int +-wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, +- int channel_num, int *bytes_left) +-{ +- char* str; +- int idx = 0; +- +- if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { +- DHD_ERROR(("%s error paramters\n", __FUNCTION__)); +- return -1; +- } +- str = *list_str; +- +- while (*bytes_left > 0) { +- +- if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) { +- *list_str = str; +- DHD_TRACE(("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0])); +- return idx; +- } +- /* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */ +- *bytes_left -= 1; +- str += 1; +- +- if (str[0] == 0) { +- /* All channels */ +- channel_list[idx] = 0x0; +- } +- else { +- channel_list[idx] = (uint16)str[0]; +- DHD_TRACE(("%s channel=%d \n", __FUNCTION__, channel_list[idx])); +- } +- *bytes_left -= 1; +- str += 1; +- +- if (idx++ > 255) { +- DHD_ERROR(("%s Too many channels \n", __FUNCTION__)); +- return -1; +- } +- } +- +- *list_str = str; +- return idx; +-} +- +-/* +- * SSIDs list parsing from cscan tlv list +- */ +-int +-wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_ext_t* ssid, int max, int *bytes_left) +-{ +- char* str; +- int idx = 0; +- +- if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) { +- DHD_ERROR(("%s error paramters\n", __FUNCTION__)); +- return -1; +- } +- str = *list_str; +- while (*bytes_left > 0) { +- +- if (str[0] != CSCAN_TLV_TYPE_SSID_IE) { +- *list_str = str; +- DHD_TRACE(("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0])); +- return idx; +- } +- +- /* Get proper CSCAN_TLV_TYPE_SSID_IE */ +- *bytes_left -= 1; +- str += 1; +- ssid[idx].rssi_thresh = 0; +- if (str[0] == 0) { +- /* Broadcast SSID */ +- ssid[idx].SSID_len = 0; +- memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN); +- *bytes_left -= 1; +- str += 1; +- +- DHD_TRACE(("BROADCAST SCAN left=%d\n", *bytes_left)); +- } +- else if (str[0] <= DOT11_MAX_SSID_LEN) { +- /* Get proper SSID size */ +- ssid[idx].SSID_len = str[0]; +- *bytes_left -= 1; +- str += 1; +- +- /* Get SSID */ +- if (ssid[idx].SSID_len > *bytes_left) { +- DHD_ERROR(("%s out of memory range len=%d but left=%d\n", +- __FUNCTION__, ssid[idx].SSID_len, *bytes_left)); +- return -1; +- } +- +- memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len); +- +- *bytes_left -= ssid[idx].SSID_len; +- str += ssid[idx].SSID_len; +- ssid[idx].hidden = TRUE; +- +- DHD_TRACE(("%s :size=%d left=%d\n", +- (char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left)); +- } +- else { +- DHD_ERROR(("### SSID size more that %d\n", str[0])); +- return -1; +- } +- +- if (idx++ > max) { +- DHD_ERROR(("%s number of SSIDs more that %d\n", __FUNCTION__, idx)); +- return -1; +- } +- } +- +- *list_str = str; +- return idx; +-} +- +-/* Parse a comma-separated list from list_str into ssid array, starting +- * at index idx. Max specifies size of the ssid array. Parses ssids +- * and returns updated idx; if idx >= max not all fit, the excess have +- * not been copied. Returns -1 on empty string, or on ssid too long. +- */ +-int +-wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max) +-{ +- char* str, *ptr; +- +- if ((list_str == NULL) || (*list_str == NULL)) +- return -1; +- +- for (str = *list_str; str != NULL; str = ptr) { +- +- /* check for next TAG */ +- if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) { +- *list_str = str + strlen(GET_CHANNEL); +- return idx; +- } +- +- if ((ptr = strchr(str, ',')) != NULL) { +- *ptr++ = '\0'; +- } +- +- if (strlen(str) > DOT11_MAX_SSID_LEN) { +- DHD_ERROR(("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN)); +- return -1; +- } +- +- if (strlen(str) == 0) +- ssid[idx].SSID_len = 0; +- +- if (idx < max) { +- bzero(ssid[idx].SSID, sizeof(ssid[idx].SSID)); +- strncpy((char*)ssid[idx].SSID, str, sizeof(ssid[idx].SSID) - 1); +- ssid[idx].SSID_len = strlen(str); +- } +- idx++; +- } +- return idx; +-} +- +-/* +- * Parse channel list from iwpriv CSCAN +- */ +-int +-wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num) +-{ +- int num; +- int val; +- char* str; +- char* endptr = NULL; +- +- if ((list_str == NULL)||(*list_str == NULL)) +- return -1; +- +- str = *list_str; +- num = 0; +- while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) { +- val = (int)strtoul(str, &endptr, 0); +- if (endptr == str) { +- printf("could not parse channel number starting at" +- " substring \"%s\" in list:\n%s\n", +- str, *list_str); +- return -1; +- } +- str = endptr + strspn(endptr, " ,"); +- +- if (num == channel_num) { +- DHD_ERROR(("too many channels (more than %d) in channel list:\n%s\n", +- channel_num, *list_str)); +- return -1; +- } +- +- channel_list[num++] = (uint16)val; +- } +- *list_str = str; +- return num; +-} +diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c +index b7d162c2172e5..d366e94d80392 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c ++++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c +@@ -32,7 +32,6 @@ + #include + + #include +-#include + + #define WL_ERROR(x) printf x + #define WL_TRACE(x) +@@ -140,6 +139,12 @@ dhd_custom_get_mac_address(void *adapter, unsigned char *buf) + } + #endif /* GET_CUSTOM_MAC_ENABLE */ + ++struct cntry_locales_custom { ++ char iso_abbrev[WLC_CNTRY_BUF_SZ]; ++ char custom_locale[WLC_CNTRY_BUF_SZ]; ++ int32 custom_locale_rev; ++}; ++ + /* Customized Locale table : OPTIONAL feature */ + const struct cntry_locales_custom translate_custom_table[] = { + /* Table should be filled out based on custom platform regulatory requirement */ +diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c +index 6fa42b097e058..e99abe6c64d27 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_linux.c ++++ b/drivers/net/wireless/bcmdhd/dhd_linux.c +@@ -246,12 +246,6 @@ print_tainted() + } + #endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */ + +-/* Linux wireless extension support */ +-#if defined(WL_WIRELESS_EXT) +-#include +-extern wl_iw_extra_params_t g_wl_iw_params; +-#endif /* defined(WL_WIRELESS_EXT) */ +- + #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) + #include + #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ +@@ -369,9 +363,6 @@ struct ipv6_work_info_t { + + /* Local private structure (extension of pub) */ + typedef struct dhd_info { +-#if defined(WL_WIRELESS_EXT) +- wl_iw_t iw; /* wireless extensions state (must be first) */ +-#endif /* defined(WL_WIRELESS_EXT) */ + dhd_pub_t pub; + dhd_if_t *iflist[DHD_MAX_IFS]; /* for supporting multiple interfaces */ + +@@ -692,10 +683,6 @@ int dhd_monitor_init(void *dhd_pub); + int dhd_monitor_uninit(void); + + +-#if defined(WL_WIRELESS_EXT) +-struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); +-#endif /* defined(WL_WIRELESS_EXT) */ +- + static void dhd_dpc(ulong data); + /* forward decl */ + extern int dhd_wait_pend8021x(struct net_device *dev); +@@ -4040,17 +4027,6 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) + return -1; + } + +-#if defined(WL_WIRELESS_EXT) +- /* linux wireless extensions */ +- if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { +- /* may recurse, do NOT lock */ +- ret = wl_iw_ioctl(net, ifr, cmd); +- DHD_PERIM_UNLOCK(&dhd->pub); +- DHD_OS_WAKE_UNLOCK(&dhd->pub); +- return ret; +- } +-#endif /* defined(WL_WIRELESS_EXT) */ +- + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) + if (cmd == SIOCETHTOOL) { + ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); +@@ -5017,17 +4993,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) + dhd_monitor_init(&dhd->pub); + dhd_state |= DHD_ATTACH_STATE_CFG80211; + #endif +-#if defined(WL_WIRELESS_EXT) +- /* Attach and link in the iw */ +- if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { +- if (wl_iw_attach(net, (void *)&dhd->pub) != 0) { +- DHD_ERROR(("wl_iw_attach failed\n")); +- goto fail; +- } +- dhd_state |= DHD_ATTACH_STATE_WL_ATTACH; +- } +-#endif /* defined(WL_WIRELESS_EXT) */ +- + /* attach debug support */ + if (dhd_os_dbg_attach(&dhd->pub)) { + DHD_ERROR(("%s debug module attach failed\n", __FUNCTION__)); +@@ -6831,15 +6796,6 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) + net->ethtool_ops = &dhd_ethtool_ops; + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ + +-#if defined(WL_WIRELESS_EXT) +-#if WIRELESS_EXT < 19 +- net->get_wireless_stats = dhd_get_wireless_stats; +-#endif /* WIRELESS_EXT < 19 */ +-#if WIRELESS_EXT > 12 +- net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; +-#endif /* WIRELESS_EXT > 12 */ +-#endif /* defined(WL_WIRELESS_EXT) */ +- + dhd->pub.rxsz = DBUS_RX_BUFFER_SIZE_DHD(net); + + memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); +@@ -6862,10 +6818,6 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) + printf("Register interface [%s] MAC: "MACDBG"\n\n", net->name, + MAC2STRDBG(net->dev_addr)); + +-#if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211) +- wl_iw_iscan_set_scan_broadcast_prep(net, 1); +-#endif +- + #if defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + if (ifidx == 0) { + #ifdef BCMLXSDMMC +@@ -6993,13 +6945,6 @@ void dhd_detach(dhd_pub_t *dhdp) + } + #endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ + +-#if defined(WL_WIRELESS_EXT) +- if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { +- /* Detatch and unlink in the iw */ +- wl_iw_detach(); +- } +-#endif /* defined(WL_WIRELESS_EXT) */ +- + /* delete all interfaces, start with virtual */ + if (dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) { + int i = 1; +@@ -7614,26 +7559,6 @@ void dhd_os_prefree(dhd_pub_t *dhdpub, void *addr, uint size) + { + } + +-#if defined(WL_WIRELESS_EXT) +-struct iw_statistics * +-dhd_get_wireless_stats(struct net_device *dev) +-{ +- int res = 0; +- dhd_info_t *dhd = DHD_DEV_INFO(dev); +- +- if (!dhd->pub.up) { +- return NULL; +- } +- +- res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats); +- +- if (res == 0) +- return &dhd->iw.wstats; +- else +- return NULL; +-} +-#endif /* defined(WL_WIRELESS_EXT) */ +- + static int + dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, size_t pktlen, + wl_event_msg_t *event, void **data) +@@ -7656,18 +7581,6 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, size_t pktlen, + if ((dhd->iflist[*ifidx] == NULL) || (dhd->iflist[*ifidx]->net == NULL)) + return BCME_ERROR; + +-#if defined(WL_WIRELESS_EXT) +- if (event->bsscfgidx == 0) { +- /* +- * Wireless ext is on primary interface only +- */ +- +- if (dhd->iflist[*ifidx]->net) { +- wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); +- } +- } +-#endif /* defined(WL_WIRELESS_EXT) */ +- + #ifdef WL_CFG80211 + + if (dhd->iflist[*ifidx]->net) +@@ -9370,9 +9283,6 @@ static void dhd_hang_process(void *dhd_info, void *event_info, u8 event) + dev_close(dev); + rtnl_unlock(); + #endif +-#if defined(WL_WIRELESS_EXT) +- wl_iw_send_priv_event(dev, "HANG"); +-#endif + #if defined(WL_CFG80211) + wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); + #endif +diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.h b/drivers/net/wireless/bcmdhd/dhd_linux.h +index e3cf3af82e547..b3d836c6b13c0 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_linux.h ++++ b/drivers/net/wireless/bcmdhd/dhd_linux.h +@@ -40,10 +40,7 @@ + #ifdef DHD_WMF + #include + #endif +-/* Linux wireless extension support */ +-#if defined(WL_WIRELESS_EXT) +-#include +-#endif /* defined(WL_WIRELESS_EXT) */ ++ + #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) + #include + #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ +diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c +deleted file mode 100644 +index fc037be8c29c9..0000000000000 +--- a/drivers/net/wireless/bcmdhd/wl_iw.c ++++ /dev/null +@@ -1,3696 +0,0 @@ +-/* +- * Linux Wireless Extensions support +- * +- * Copyright (C) 1999-2014, Broadcom Corporation +- * +- * Unless you and Broadcom execute a separate written software license +- * agreement governing use of this software, this software is licensed to you +- * under the terms of the GNU General Public License version 2 (the "GPL"), +- * available at http://www.broadcom.com/licenses/GPLv2.php, with the +- * following added to such license: +- * +- * As a special exception, the copyright holders of this software give you +- * permission to link this software with independent modules, and to copy and +- * distribute the resulting executable under terms of your choice, provided that +- * you also meet, for each linked independent module, the terms and conditions of +- * the license of that module. An independent module is a module which is not +- * derived from this software. The special exception does not apply to any +- * modifications of the software. +- * +- * Notwithstanding the above, under no circumstances may you combine this +- * software in any way with any other Broadcom software provided under a license +- * other than the GPL, without Broadcom's express prior written consent. +- * +- * $Id: wl_iw.c 467328 2014-04-03 01:23:40Z $ +- */ +- +-#if defined(USE_IW) +-#define LINUX_PORT +- +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include +-#include +- +-typedef const struct si_pub si_t; +-#include +- +- +-#include +-#include +- +- +-/* Broadcom extensions to WEXT, linux upstream has obsoleted WEXT */ +-#ifndef IW_AUTH_KEY_MGMT_FT_802_1X +-#define IW_AUTH_KEY_MGMT_FT_802_1X 0x04 +-#endif +- +-#ifndef IW_AUTH_KEY_MGMT_FT_PSK +-#define IW_AUTH_KEY_MGMT_FT_PSK 0x08 +-#endif +- +-#ifndef IW_ENC_CAPA_FW_ROAM_ENABLE +-#define IW_ENC_CAPA_FW_ROAM_ENABLE 0x00000020 +-#endif +- +- +-/* FC9: wireless.h 2.6.25-14.fc9.i686 is missing these, even though WIRELESS_EXT is set to latest +- * version 22. +- */ +-#ifndef IW_ENCODE_ALG_PMK +-#define IW_ENCODE_ALG_PMK 4 +-#endif +-#ifndef IW_ENC_CAPA_4WAY_HANDSHAKE +-#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010 +-#endif +-/* End FC9. */ +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +-#include +-#endif +-#if defined(SOFTAP) +-struct net_device *ap_net_dev = NULL; +-tsk_ctl_t ap_eth_ctl; /* apsta AP netdev waiter thread */ +-#endif /* SOFTAP */ +- +-extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, +- uint32 reason, char* stringBuf, uint buflen); +- +-uint wl_msg_level = WL_ERROR_VAL; +- +-#define MAX_WLIW_IOCTL_LEN 1024 +- +-/* IOCTL swapping mode for Big Endian host with Little Endian dongle. Default to off */ +-#define htod32(i) (i) +-#define htod16(i) (i) +-#define dtoh32(i) (i) +-#define dtoh16(i) (i) +-#define htodchanspec(i) (i) +-#define dtohchanspec(i) (i) +- +-extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); +-extern int dhd_wait_pend8021x(struct net_device *dev); +- +-#if WIRELESS_EXT < 19 +-#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) +-#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) +-#endif /* WIRELESS_EXT < 19 */ +- +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) +-#define DAEMONIZE(a) do { \ +- allow_signal(SIGKILL); \ +- allow_signal(SIGTERM); \ +- } while (0) +-#elif ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && \ +- (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))) +-#define DAEMONIZE(a) daemonize(a); \ +- allow_signal(SIGKILL); \ +- allow_signal(SIGTERM); +-#else /* Linux 2.4 (w/o preemption patch) */ +-#define RAISE_RX_SOFTIRQ() \ +- cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) +-#define DAEMONIZE(a) daemonize(); \ +- do { if (a) \ +- strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ +- } while (0); +-#endif /* LINUX_VERSION_CODE */ +- +-#define ISCAN_STATE_IDLE 0 +-#define ISCAN_STATE_SCANING 1 +- +-/* the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */ +-#define WLC_IW_ISCAN_MAXLEN 2048 +-typedef struct iscan_buf { +- struct iscan_buf * next; +- char iscan_buf[WLC_IW_ISCAN_MAXLEN]; +-} iscan_buf_t; +- +-typedef struct iscan_info { +- struct net_device *dev; +- struct timer_list timer; +- uint32 timer_ms; +- uint32 timer_on; +- int iscan_state; +- iscan_buf_t * list_hdr; +- iscan_buf_t * list_cur; +- +- /* Thread to work on iscan */ +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +- struct task_struct *kthread; +-#endif +- long sysioc_pid; +- struct semaphore sysioc_sem; +- struct completion sysioc_exited; +- +- +- char ioctlbuf[WLC_IOCTL_SMLEN]; +-} iscan_info_t; +-iscan_info_t *g_iscan = NULL; +-static void wl_iw_timerfunc(ulong data); +-static void wl_iw_set_event_mask(struct net_device *dev); +-static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action); +- +-/* priv_link becomes netdev->priv and is the link between netdev and wlif struct */ +-typedef struct priv_link { +- wl_iw_t *wliw; +-} priv_link_t; +- +-/* dev to priv_link */ +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) +-#define WL_DEV_LINK(dev) (priv_link_t*)(dev->priv) +-#else +-#define WL_DEV_LINK(dev) (priv_link_t*)netdev_priv(dev) +-#endif +- +-/* dev to wl_iw_t */ +-#define IW_DEV_IF(dev) ((wl_iw_t*)(WL_DEV_LINK(dev))->wliw) +- +-static void swap_key_from_BE( +- wl_wsec_key_t *key +-) +-{ +- key->index = htod32(key->index); +- key->len = htod32(key->len); +- key->algo = htod32(key->algo); +- key->flags = htod32(key->flags); +- key->rxiv.hi = htod32(key->rxiv.hi); +- key->rxiv.lo = htod16(key->rxiv.lo); +- key->iv_initialized = htod32(key->iv_initialized); +-} +- +-static void swap_key_to_BE( +- wl_wsec_key_t *key +-) +-{ +- key->index = dtoh32(key->index); +- key->len = dtoh32(key->len); +- key->algo = dtoh32(key->algo); +- key->flags = dtoh32(key->flags); +- key->rxiv.hi = dtoh32(key->rxiv.hi); +- key->rxiv.lo = dtoh16(key->rxiv.lo); +- key->iv_initialized = dtoh32(key->iv_initialized); +-} +- +-static int +-dev_wlc_ioctl( +- struct net_device *dev, +- int cmd, +- void *arg, +- int len +-) +-{ +- struct ifreq ifr; +- wl_ioctl_t ioc; +- mm_segment_t fs; +- int ret; +- +- memset(&ioc, 0, sizeof(ioc)); +- ioc.cmd = cmd; +- ioc.buf = arg; +- ioc.len = len; +- +- strcpy(ifr.ifr_name, dev->name); +- ifr.ifr_data = (caddr_t) &ioc; +- +- fs = get_fs(); +- set_fs(get_ds()); +-#if defined(WL_USE_NETDEV_OPS) +- ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); +-#else +- ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE); +-#endif +- set_fs(fs); +- +- return ret; +-} +- +-/* +-set named driver variable to int value and return error indication +-calling example: dev_wlc_intvar_set(dev, "arate", rate) +-*/ +- +-static int +-dev_wlc_intvar_set( +- struct net_device *dev, +- char *name, +- int val) +-{ +- char buf[WLC_IOCTL_SMLEN]; +- uint len; +- +- val = htod32(val); +- len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf)); +- DHD_WARN(len, return BCME_ERROR;); +- +- return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len)); +-} +- +-static int +-dev_iw_iovar_setbuf( +- struct net_device *dev, +- char *iovar, +- void *param, +- int paramlen, +- void *bufptr, +- int buflen) +-{ +- int iolen; +- +- iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); +- DHD_WARN(iolen, return BCME_ERROR;); +- BCM_REFERENCE(iolen); +- +- return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen)); +-} +- +-static int +-dev_iw_iovar_getbuf( +- struct net_device *dev, +- char *iovar, +- void *param, +- int paramlen, +- void *bufptr, +- int buflen) +-{ +- int iolen; +- +- iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); +- DHD_WARN(iolen, return BCME_ERROR;); +- BCM_REFERENCE(iolen); +- +- return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen)); +-} +- +-#if WIRELESS_EXT > 17 +-static int +-dev_wlc_bufvar_set( +- struct net_device *dev, +- char *name, +- char *buf, int len) +-{ +- char *ioctlbuf; +- uint buflen; +- int error; +- +- ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL); +- if (!ioctlbuf) +- return -ENOMEM; +- +- buflen = bcm_mkiovar(name, buf, len, ioctlbuf, MAX_WLIW_IOCTL_LEN); +- DHD_WARN(buflen, return BCME_ERROR;); +- error = dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen); +- +- kfree(ioctlbuf); +- return error; +-} +-#endif /* WIRELESS_EXT > 17 */ +- +-/* +-get named driver variable to int value and return error indication +-calling example: dev_wlc_bufvar_get(dev, "arate", &rate) +-*/ +- +-static int +-dev_wlc_bufvar_get( +- struct net_device *dev, +- char *name, +- char *buf, int buflen) +-{ +- char *ioctlbuf; +- int error; +- +- uint len; +- +- ioctlbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL); +- if (!ioctlbuf) +- return -ENOMEM; +- len = bcm_mkiovar(name, NULL, 0, ioctlbuf, MAX_WLIW_IOCTL_LEN); +- DHD_WARN(len, return BCME_ERROR;); +- BCM_REFERENCE(len); +- error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN); +- if (!error) +- bcopy(ioctlbuf, buf, buflen); +- +- kfree(ioctlbuf); +- return (error); +-} +- +-/* +-get named driver variable to int value and return error indication +-calling example: dev_wlc_intvar_get(dev, "arate", &rate) +-*/ +- +-static int +-dev_wlc_intvar_get( +- struct net_device *dev, +- char *name, +- int *retval) +-{ +- union { +- char buf[WLC_IOCTL_SMLEN]; +- int val; +- } var; +- int error; +- +- uint len; +- uint data_null; +- +- len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf)); +- DHD_WARN(len, return BCME_ERROR;); +- error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len); +- +- *retval = dtoh32(var.val); +- +- return (error); +-} +- +-/* Maintain backward compatibility */ +-#if WIRELESS_EXT < 13 +-struct iw_request_info +-{ +- __u16 cmd; /* Wireless Extension command */ +- __u16 flags; /* More to come ;-) */ +-}; +- +-typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info, +- void *wrqu, char *extra); +-#endif /* WIRELESS_EXT < 13 */ +- +-#if WIRELESS_EXT > 12 +-static int +-wl_iw_set_leddc( +- struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra +-) +-{ +- int dc = *(int *)extra; +- int error; +- +- error = dev_wlc_intvar_set(dev, "leddc", dc); +- return error; +-} +- +-static int +-wl_iw_set_vlanmode( +- struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra +-) +-{ +- int mode = *(int *)extra; +- int error; +- +- mode = htod32(mode); +- error = dev_wlc_intvar_set(dev, "vlan_mode", mode); +- return error; +-} +- +-static int +-wl_iw_set_pm( +- struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra +-) +-{ +- int pm = *(int *)extra; +- int error; +- +- pm = htod32(pm); +- error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); +- return error; +-} +- +-#if WIRELESS_EXT > 17 +-#endif /* WIRELESS_EXT > 17 */ +-#endif /* WIRELESS_EXT > 12 */ +- +-int +-wl_iw_send_priv_event( +- struct net_device *dev, +- char *flag +-) +-{ +- union iwreq_data wrqu; +- char extra[IW_CUSTOM_MAX + 1]; +- int cmd; +- +- cmd = IWEVCUSTOM; +- memset(&wrqu, 0, sizeof(wrqu)); +- if (strlen(flag) > sizeof(extra)) +- return -1; +- +- strcpy(extra, flag); +- wrqu.data.length = strlen(extra); +- wireless_send_event(dev, cmd, &wrqu, extra); +- WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra)); +- +- return 0; +-} +- +-static int +-wl_iw_config_commit( +- struct net_device *dev, +- struct iw_request_info *info, +- void *zwrq, +- char *extra +-) +-{ +- wlc_ssid_t ssid; +- int error; +- struct sockaddr bssid; +- +- WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name)); +- +- if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) +- return error; +- +- ssid.SSID_len = dtoh32(ssid.SSID_len); +- +- if (!ssid.SSID_len) +- return 0; +- +- bzero(&bssid, sizeof(struct sockaddr)); +- if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) { +- WL_ERROR(("%s: WLC_REASSOC failed (%d)\n", __FUNCTION__, error)); +- return error; +- } +- +- return 0; +-} +- +-static int +-wl_iw_get_name( +- struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *cwrq, +- char *extra +-) +-{ +- int phytype, err; +- uint band[3]; +- char cap[5]; +- +- WL_TRACE(("%s: SIOCGIWNAME\n", dev->name)); +- +- cap[0] = 0; +- if ((err = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype))) < 0) +- goto done; +- if ((err = dev_wlc_ioctl(dev, WLC_GET_BANDLIST, band, sizeof(band))) < 0) +- goto done; +- +- band[0] = dtoh32(band[0]); +- switch (phytype) { +- case WLC_PHY_TYPE_A: +- strcpy(cap, "a"); +- break; +- case WLC_PHY_TYPE_B: +- strcpy(cap, "b"); +- break; +- case WLC_PHY_TYPE_LP: +- case WLC_PHY_TYPE_G: +- if (band[0] >= 2) +- strcpy(cap, "abg"); +- else +- strcpy(cap, "bg"); +- break; +- case WLC_PHY_TYPE_N: +- if (band[0] >= 2) +- strcpy(cap, "abgn"); +- else +- strcpy(cap, "bgn"); +- break; +- } +-done: +- snprintf(cwrq->name, IFNAMSIZ, "IEEE 802.11%s", cap); +- return 0; +-} +- +-static int +-wl_iw_set_freq( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_freq *fwrq, +- char *extra +-) +-{ +- int error, chan; +- uint sf = 0; +- +- WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name)); +- +- /* Setting by channel number */ +- if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) { +- chan = fwrq->m; +- } +- +- /* Setting by frequency */ +- else { +- /* Convert to MHz as best we can */ +- if (fwrq->e >= 6) { +- fwrq->e -= 6; +- while (fwrq->e--) +- fwrq->m *= 10; +- } else if (fwrq->e < 6) { +- while (fwrq->e++ < 6) +- fwrq->m /= 10; +- } +- /* handle 4.9GHz frequencies as Japan 4 GHz based channelization */ +- if (fwrq->m > 4000 && fwrq->m < 5000) +- sf = WF_CHAN_FACTOR_4_G; /* start factor for 4 GHz */ +- +- chan = wf_mhz2channel(fwrq->m, sf); +- } +- chan = htod32(chan); +- if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan)))) +- return error; +- +- /* -EINPROGRESS: Call commit handler */ +- return -EINPROGRESS; +-} +- +-static int +-wl_iw_get_freq( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_freq *fwrq, +- char *extra +-) +-{ +- channel_info_t ci; +- int error; +- +- WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name)); +- +- if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) +- return error; +- +- /* Return radio channel in channel form */ +- fwrq->m = dtoh32(ci.hw_channel); +- fwrq->e = dtoh32(0); +- return 0; +-} +- +-static int +-wl_iw_set_mode( +- struct net_device *dev, +- struct iw_request_info *info, +- __u32 *uwrq, +- char *extra +-) +-{ +- int infra = 0, ap = 0, error = 0; +- +- WL_TRACE(("%s: SIOCSIWMODE\n", dev->name)); +- +- switch (*uwrq) { +- case IW_MODE_MASTER: +- infra = ap = 1; +- break; +- case IW_MODE_ADHOC: +- case IW_MODE_AUTO: +- break; +- case IW_MODE_INFRA: +- infra = 1; +- break; +- default: +- return -EINVAL; +- } +- infra = htod32(infra); +- ap = htod32(ap); +- +- if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) || +- (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap)))) +- return error; +- +- /* -EINPROGRESS: Call commit handler */ +- return -EINPROGRESS; +-} +- +-static int +-wl_iw_get_mode( +- struct net_device *dev, +- struct iw_request_info *info, +- __u32 *uwrq, +- char *extra +-) +-{ +- int error, infra = 0, ap = 0; +- +- WL_TRACE(("%s: SIOCGIWMODE\n", dev->name)); +- +- if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) || +- (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap)))) +- return error; +- +- infra = dtoh32(infra); +- ap = dtoh32(ap); +- *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC; +- +- return 0; +-} +- +-static int +-wl_iw_get_range( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- struct iw_range *range = (struct iw_range *) extra; +- static int channels[MAXCHANNEL+1]; +- wl_uint32_list_t *list = (wl_uint32_list_t *) channels; +- wl_rateset_t rateset; +- int error, i, k; +- uint sf, ch; +- +- int phytype; +- int bw_cap = 0, sgi_tx = 0, nmode = 0; +- channel_info_t ci; +- uint8 nrate_list2copy = 0; +- uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130}, +- {14, 29, 43, 58, 87, 116, 130, 144}, +- {27, 54, 81, 108, 162, 216, 243, 270}, +- {30, 60, 90, 120, 180, 240, 270, 300}}; +- int fbt_cap = 0; +- +- WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- dwrq->length = sizeof(struct iw_range); +- memset(range, 0, sizeof(*range)); +- +- /* We don't use nwids */ +- range->min_nwid = range->max_nwid = 0; +- +- /* Set available channels/frequencies */ +- list->count = htod32(MAXCHANNEL); +- if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, sizeof(channels)))) +- return error; +- for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) { +- range->freq[i].i = dtoh32(list->element[i]); +- +- ch = dtoh32(list->element[i]); +- if (ch <= CH_MAX_2G_CHANNEL) +- sf = WF_CHAN_FACTOR_2_4_G; +- else +- sf = WF_CHAN_FACTOR_5_G; +- +- range->freq[i].m = wf_channel2mhz(ch, sf); +- range->freq[i].e = 6; +- } +- range->num_frequency = range->num_channels = i; +- +- /* Link quality (use NDIS cutoffs) */ +- range->max_qual.qual = 5; +- /* Signal level (use RSSI) */ +- range->max_qual.level = 0x100 - 200; /* -200 dBm */ +- /* Noise level (use noise) */ +- range->max_qual.noise = 0x100 - 200; /* -200 dBm */ +- /* Signal level threshold range (?) */ +- range->sensitivity = 65535; +- +-#if WIRELESS_EXT > 11 +- /* Link quality (use NDIS cutoffs) */ +- range->avg_qual.qual = 3; +- /* Signal level (use RSSI) */ +- range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD; +- /* Noise level (use noise) */ +- range->avg_qual.noise = 0x100 - 75; /* -75 dBm */ +-#endif /* WIRELESS_EXT > 11 */ +- +- /* Set available bitrates */ +- if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) +- return error; +- rateset.count = dtoh32(rateset.count); +- range->num_bitrates = rateset.count; +- for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++) +- range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; /* convert to bps */ +- if ((error = dev_wlc_intvar_get(dev, "nmode", &nmode))) +- return error; +- if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)))) +- return error; +- if (nmode == 1 && ((phytype == WLC_PHY_TYPE_SSN) || (phytype == WLC_PHY_TYPE_LCN) || +- (phytype == WLC_PHY_TYPE_LCN40))) { +- if ((error = dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap))) +- return error; +- if ((error = dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx))) +- return error; +- if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)))) +- return error; +- ci.hw_channel = dtoh32(ci.hw_channel); +- +- if (bw_cap == 0 || +- (bw_cap == 2 && ci.hw_channel <= 14)) { +- if (sgi_tx == 0) +- nrate_list2copy = 0; +- else +- nrate_list2copy = 1; +- } +- if (bw_cap == 1 || +- (bw_cap == 2 && ci.hw_channel >= 36)) { +- if (sgi_tx == 0) +- nrate_list2copy = 2; +- else +- nrate_list2copy = 3; +- } +- range->num_bitrates += 8; +- DHD_WARN(range->num_bitrates < IW_MAX_BITRATES, return BCME_ERROR;); +- for (k = 0; i < range->num_bitrates; k++, i++) { +- /* convert to bps */ +- range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000; +- } +- } +- +- /* Set an indication of the max TCP throughput +- * in bit/s that we can expect using this interface. +- * May be use for QoS stuff... Jean II +- */ +- if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) +- return error; +- i = dtoh32(i); +- if (i == WLC_PHY_TYPE_A) +- range->throughput = 24000000; /* 24 Mbits/s */ +- else +- range->throughput = 1500000; /* 1.5 Mbits/s */ +- +- /* RTS and fragmentation thresholds */ +- range->min_rts = 0; +- range->max_rts = 2347; +- range->min_frag = 256; +- range->max_frag = 2346; +- +- range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS; +- range->num_encoding_sizes = 4; +- range->encoding_size[0] = WEP1_KEY_SIZE; +- range->encoding_size[1] = WEP128_KEY_SIZE; +-#if WIRELESS_EXT > 17 +- range->encoding_size[2] = TKIP_KEY_SIZE; +-#else +- range->encoding_size[2] = 0; +-#endif +- range->encoding_size[3] = AES_KEY_SIZE; +- +- /* Do not support power micro-management */ +- range->min_pmp = 0; +- range->max_pmp = 0; +- range->min_pmt = 0; +- range->max_pmt = 0; +- range->pmp_flags = 0; +- range->pm_capa = 0; +- +- /* Transmit Power - values are in mW */ +- range->num_txpower = 2; +- range->txpower[0] = 1; +- range->txpower[1] = 255; +- range->txpower_capa = IW_TXPOW_MWATT; +- +-#if WIRELESS_EXT > 10 +- range->we_version_compiled = WIRELESS_EXT; +- range->we_version_source = 19; +- +- /* Only support retry limits */ +- range->retry_capa = IW_RETRY_LIMIT; +- range->retry_flags = IW_RETRY_LIMIT; +- range->r_time_flags = 0; +- /* SRL and LRL limits */ +- range->min_retry = 1; +- range->max_retry = 255; +- /* Retry lifetime limits unsupported */ +- range->min_r_time = 0; +- range->max_r_time = 0; +-#endif /* WIRELESS_EXT > 10 */ +- +-#if WIRELESS_EXT > 17 +- range->enc_capa = IW_ENC_CAPA_WPA; +- range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; +- range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; +- range->enc_capa |= IW_ENC_CAPA_WPA2; +- +- /* Determine driver FBT capability. */ +- if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) { +- if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) { +- /* Tell the host (e.g. wpa_supplicant) to let driver do the handshake */ +- range->enc_capa |= IW_ENC_CAPA_4WAY_HANDSHAKE; +- } +- } +- +-#ifdef BCMFW_ROAM_ENABLE_WEXT +- /* Advertise firmware roam capability to the external supplicant */ +- range->enc_capa |= IW_ENC_CAPA_FW_ROAM_ENABLE; +-#endif /* BCMFW_ROAM_ENABLE_WEXT */ +- +- /* Event capability (kernel) */ +- IW_EVENT_CAPA_SET_KERNEL(range->event_capa); +- /* Event capability (driver) */ +- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); +- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); +- IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); +- IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE); +- IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE); +- IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE); +- IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND); +- +-#if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID) +- /* FC7 wireless.h defines EXT 22 but doesn't define scan_capa bits */ +- range->scan_capa = IW_SCAN_CAPA_ESSID; +-#endif +-#endif /* WIRELESS_EXT > 17 */ +- +- return 0; +-} +- +-static int +-rssi_to_qual(int rssi) +-{ +- if (rssi <= WL_IW_RSSI_NO_SIGNAL) +- return 0; +- else if (rssi <= WL_IW_RSSI_VERY_LOW) +- return 1; +- else if (rssi <= WL_IW_RSSI_LOW) +- return 2; +- else if (rssi <= WL_IW_RSSI_GOOD) +- return 3; +- else if (rssi <= WL_IW_RSSI_VERY_GOOD) +- return 4; +- else +- return 5; +-} +- +-static int +-wl_iw_set_spy( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_iw_t *iw = IW_DEV_IF(dev); +- struct sockaddr *addr = (struct sockaddr *) extra; +- int i; +- +- WL_TRACE(("%s: SIOCSIWSPY\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length); +- for (i = 0; i < iw->spy_num; i++) +- memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN); +- memset(iw->spy_qual, 0, sizeof(iw->spy_qual)); +- +- return 0; +-} +- +-static int +-wl_iw_get_spy( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_iw_t *iw = IW_DEV_IF(dev); +- struct sockaddr *addr = (struct sockaddr *) extra; +- struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num]; +- int i; +- +- WL_TRACE(("%s: SIOCGIWSPY\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- dwrq->length = iw->spy_num; +- for (i = 0; i < iw->spy_num; i++) { +- memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN); +- addr[i].sa_family = AF_UNIX; +- memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality)); +- iw->spy_qual[i].updated = 0; +- } +- +- return 0; +-} +- +-static int +-wl_iw_set_wap( +- struct net_device *dev, +- struct iw_request_info *info, +- struct sockaddr *awrq, +- char *extra +-) +-{ +- int error = -EINVAL; +- +- WL_TRACE(("%s: SIOCSIWAP\n", dev->name)); +- +- if (awrq->sa_family != ARPHRD_ETHER) { +- WL_ERROR(("%s: Invalid Header...sa_family\n", __FUNCTION__)); +- return -EINVAL; +- } +- +- /* Ignore "auto" or "off" */ +- if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) { +- scb_val_t scbval; +- bzero(&scbval, sizeof(scb_val_t)); +- if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) { +- WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error)); +- } +- return 0; +- } +- /* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(awrq->sa_data), +- * eabuf))); +- */ +- /* Reassociate to the specified AP */ +- if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) { +- WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error)); +- return error; +- } +- +- return 0; +-} +- +-static int +-wl_iw_get_wap( +- struct net_device *dev, +- struct iw_request_info *info, +- struct sockaddr *awrq, +- char *extra +-) +-{ +- WL_TRACE(("%s: SIOCGIWAP\n", dev->name)); +- +- awrq->sa_family = ARPHRD_ETHER; +- memset(awrq->sa_data, 0, ETHER_ADDR_LEN); +- +- /* Ignore error (may be down or disassociated) */ +- (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN); +- +- return 0; +-} +- +-#if WIRELESS_EXT > 17 +-static int +-wl_iw_mlme( +- struct net_device *dev, +- struct iw_request_info *info, +- struct sockaddr *awrq, +- char *extra +-) +-{ +- struct iw_mlme *mlme; +- scb_val_t scbval; +- int error = -EINVAL; +- +- WL_TRACE(("%s: SIOCSIWMLME\n", dev->name)); +- +- mlme = (struct iw_mlme *)extra; +- if (mlme == NULL) { +- WL_ERROR(("Invalid ioctl data.\n")); +- return error; +- } +- +- scbval.val = mlme->reason_code; +- bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN); +- +- if (mlme->cmd == IW_MLME_DISASSOC) { +- scbval.val = htod32(scbval.val); +- error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); +- } +- else if (mlme->cmd == IW_MLME_DEAUTH) { +- scbval.val = htod32(scbval.val); +- error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, +- sizeof(scb_val_t)); +- } +- else { +- WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__)); +- return error; +- } +- +- return error; +-} +-#endif /* WIRELESS_EXT > 17 */ +- +-static int +-wl_iw_get_aplist( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_scan_results_t *list; +- struct sockaddr *addr = (struct sockaddr *) extra; +- struct iw_quality qual[IW_MAX_AP]; +- wl_bss_info_t *bi = NULL; +- int error, i; +- uint buflen = dwrq->length; +- +- WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- /* Get scan results (too large to put on the stack) */ +- list = kmalloc(buflen, GFP_KERNEL); +- if (!list) +- return -ENOMEM; +- memset(list, 0, buflen); +- list->buflen = htod32(buflen); +- if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) { +- WL_ERROR(("%d: Scan results error %d\n", __LINE__, error)); +- kfree(list); +- return error; +- } +- list->buflen = dtoh32(list->buflen); +- list->version = dtoh32(list->version); +- list->count = dtoh32(list->count); +- DHD_WARN(list->version == WL_BSS_INFO_VERSION, kfree(list);return BCME_ERROR;); +- +- for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { +- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; +- DHD_WARN(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + +- buflen), kfree(list);return BCME_ERROR;); +- +- /* Infrastructure only */ +- if (!(dtoh16(bi->capability) & DOT11_CAP_ESS)) +- continue; +- +- /* BSSID */ +- memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN); +- addr[dwrq->length].sa_family = ARPHRD_ETHER; +- qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI)); +- qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI); +- qual[dwrq->length].noise = 0x100 + bi->phy_noise; +- +- /* Updated qual, level, and noise */ +-#if WIRELESS_EXT > 18 +- qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; +-#else +- qual[dwrq->length].updated = 7; +-#endif /* WIRELESS_EXT > 18 */ +- +- dwrq->length++; +- } +- +- kfree(list); +- +- if (dwrq->length) { +- memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length); +- /* Provided qual */ +- dwrq->flags = 1; +- } +- +- return 0; +-} +- +-static int +-wl_iw_iscan_get_aplist( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_scan_results_t *list; +- iscan_buf_t * buf; +- iscan_info_t *iscan = g_iscan; +- +- struct sockaddr *addr = (struct sockaddr *) extra; +- struct iw_quality qual[IW_MAX_AP]; +- wl_bss_info_t *bi = NULL; +- int i; +- +- WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- if ((!iscan) || (iscan->sysioc_pid < 0)) { +- return wl_iw_get_aplist(dev, info, dwrq, extra); +- } +- +- buf = iscan->list_hdr; +- /* Get scan results (too large to put on the stack) */ +- while (buf) { +- list = &((wl_iscan_results_t*)buf->iscan_buf)->results; +- DHD_WARN(list->version == WL_BSS_INFO_VERSION, return BCME_ERROR;); +- +- bi = NULL; +- for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { +- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; +- DHD_WARN(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + +- WLC_IW_ISCAN_MAXLEN), return BCME_ERROR;); +- +- /* Infrastructure only */ +- if (!(dtoh16(bi->capability) & DOT11_CAP_ESS)) +- continue; +- +- /* BSSID */ +- memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN); +- addr[dwrq->length].sa_family = ARPHRD_ETHER; +- qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI)); +- qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI); +- qual[dwrq->length].noise = 0x100 + bi->phy_noise; +- +- /* Updated qual, level, and noise */ +-#if WIRELESS_EXT > 18 +- qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; +-#else +- qual[dwrq->length].updated = 7; +-#endif /* WIRELESS_EXT > 18 */ +- +- dwrq->length++; +- } +- buf = buf->next; +- } +- if (dwrq->length) { +- memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length); +- /* Provided qual */ +- dwrq->flags = 1; +- } +- +- return 0; +-} +- +-#if WIRELESS_EXT > 13 +-static int +-wl_iw_set_scan( +- struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra +-) +-{ +- wlc_ssid_t ssid; +- +- WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name)); +- +- /* default Broadcast scan */ +- memset(&ssid, 0, sizeof(ssid)); +- +-#if WIRELESS_EXT > 17 +- /* check for given essid */ +- if (wrqu->data.length == sizeof(struct iw_scan_req)) { +- if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { +- struct iw_scan_req *req = (struct iw_scan_req *)extra; +- ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); +- memcpy(ssid.SSID, req->essid, ssid.SSID_len); +- ssid.SSID_len = htod32(ssid.SSID_len); +- } +- } +-#endif +- /* Ignore error (most likely scan in progress) */ +- (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid)); +- +- return 0; +-} +- +-static int +-wl_iw_iscan_set_scan( +- struct net_device *dev, +- struct iw_request_info *info, +- union iwreq_data *wrqu, +- char *extra +-) +-{ +- wlc_ssid_t ssid; +- iscan_info_t *iscan = g_iscan; +- +- WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name)); +- +- /* use backup if our thread is not successful */ +- if ((!iscan) || (iscan->sysioc_pid < 0)) { +- return wl_iw_set_scan(dev, info, wrqu, extra); +- } +- if (iscan->iscan_state == ISCAN_STATE_SCANING) { +- return 0; +- } +- +- /* default Broadcast scan */ +- memset(&ssid, 0, sizeof(ssid)); +- +-#if WIRELESS_EXT > 17 +- /* check for given essid */ +- if (wrqu->data.length == sizeof(struct iw_scan_req)) { +- if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { +- struct iw_scan_req *req = (struct iw_scan_req *)extra; +- ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); +- memcpy(ssid.SSID, req->essid, ssid.SSID_len); +- ssid.SSID_len = htod32(ssid.SSID_len); +- } +- } +-#endif +- +- iscan->list_cur = iscan->list_hdr; +- iscan->iscan_state = ISCAN_STATE_SCANING; +- +- +- wl_iw_set_event_mask(dev); +- wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START); +- +- iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); +- add_timer(&iscan->timer); +- iscan->timer_on = 1; +- +- return 0; +-} +- +-#if WIRELESS_EXT > 17 +-static bool +-ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len) +-{ +-/* Is this body of this tlvs entry a WPA entry? If */ +-/* not update the tlvs buffer pointer/length */ +- uint8 *ie = *wpaie; +- +- /* If the contents match the WPA_OUI and type=1 */ +- if ((ie[1] >= 6) && +- !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) { +- return TRUE; +- } +- +- /* point to the next ie */ +- ie += ie[1] + 2; +- /* calculate the length of the rest of the buffer */ +- *tlvs_len -= (int)(ie - *tlvs); +- /* update the pointer to the start of the buffer */ +- *tlvs = ie; +- return FALSE; +-} +- +-static bool +-ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len) +-{ +-/* Is this body of this tlvs entry a WPS entry? If */ +-/* not update the tlvs buffer pointer/length */ +- uint8 *ie = *wpsie; +- +- /* If the contents match the WPA_OUI and type=4 */ +- if ((ie[1] >= 4) && +- !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) { +- return TRUE; +- } +- +- /* point to the next ie */ +- ie += ie[1] + 2; +- /* calculate the length of the rest of the buffer */ +- *tlvs_len -= (int)(ie - *tlvs); +- /* update the pointer to the start of the buffer */ +- *tlvs = ie; +- return FALSE; +-} +-#endif /* WIRELESS_EXT > 17 */ +- +- +-static int +-wl_iw_handle_scanresults_ies(char **event_p, char *end, +- struct iw_request_info *info, wl_bss_info_t *bi) +-{ +-#if WIRELESS_EXT > 17 +- struct iw_event iwe; +- char *event; +- +- event = *event_p; +- if (bi->ie_length) { +- /* look for wpa/rsn ies in the ie list... */ +- bcm_tlv_t *ie; +- uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); +- int ptr_len = bi->ie_length; +- +- /* OSEN IE */ +- if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_VS_ID)) && +- ie->len > WFA_OUI_LEN + 1 && +- !bcmp((const void *)&ie->data[0], (const void *)WFA_OUI, WFA_OUI_LEN) && +- ie->data[WFA_OUI_LEN] == WFA_OUI_TYPE_OSEN) { +- iwe.cmd = IWEVGENIE; +- iwe.u.data.length = ie->len + 2; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); +- } +- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); +- +- if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) { +- iwe.cmd = IWEVGENIE; +- iwe.u.data.length = ie->len + 2; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); +- } +- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); +- +- if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_MDIE_ID))) { +- iwe.cmd = IWEVGENIE; +- iwe.u.data.length = ie->len + 2; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); +- } +- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); +- +- while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { +- /* look for WPS IE */ +- if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) { +- iwe.cmd = IWEVGENIE; +- iwe.u.data.length = ie->len + 2; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); +- break; +- } +- } +- +- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); +- ptr_len = bi->ie_length; +- while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { +- if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) { +- iwe.cmd = IWEVGENIE; +- iwe.u.data.length = ie->len + 2; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); +- break; +- } +- } +- +- *event_p = event; +- } +- +-#endif /* WIRELESS_EXT > 17 */ +- return 0; +-} +-static int +-wl_iw_get_scan( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- channel_info_t ci; +- wl_scan_results_t *list; +- struct iw_event iwe; +- wl_bss_info_t *bi = NULL; +- int error, i, j; +- char *event = extra, *end = extra + dwrq->length, *value; +- uint buflen = dwrq->length; +- +- WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- /* Check for scan in progress */ +- if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) +- return error; +- ci.scan_channel = dtoh32(ci.scan_channel); +- if (ci.scan_channel) +- return -EAGAIN; +- +- /* Get scan results (too large to put on the stack) */ +- list = kmalloc(buflen, GFP_KERNEL); +- if (!list) +- return -ENOMEM; +- memset(list, 0, buflen); +- list->buflen = htod32(buflen); +- if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) { +- kfree(list); +- return error; +- } +- list->buflen = dtoh32(list->buflen); +- list->version = dtoh32(list->version); +- list->count = dtoh32(list->count); +- +- for (i = 0; i < list->count && i < IW_MAX_AP; i++) { +- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; +- +- /* First entry must be the BSSID */ +- iwe.cmd = SIOCGIWAP; +- iwe.u.ap_addr.sa_family = ARPHRD_ETHER; +- memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); +- event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); +- +- /* SSID */ +- iwe.u.data.length = dtoh32(bi->SSID_len); +- iwe.cmd = SIOCGIWESSID; +- iwe.u.data.flags = 1; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); +- +- /* Mode */ +- if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { +- iwe.cmd = SIOCGIWMODE; +- if (dtoh16(bi->capability) & DOT11_CAP_ESS) +- iwe.u.mode = IW_MODE_INFRA; +- else +- iwe.u.mode = IW_MODE_ADHOC; +- event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); +- } +- +- /* Channel */ +- iwe.cmd = SIOCGIWFREQ; +- +- iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), +- (CHSPEC_IS2G(bi->chanspec)) ? +- WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); +- iwe.u.freq.e = 6; +- event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); +- +- /* Channel quality */ +- iwe.cmd = IWEVQUAL; +- iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); +- iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); +- iwe.u.qual.noise = 0x100 + bi->phy_noise; +- event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); +- +- /* WPA, WPA2, WPS, WAPI IEs */ +- wl_iw_handle_scanresults_ies(&event, end, info, bi); +- +- /* Encryption */ +- iwe.cmd = SIOCGIWENCODE; +- if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) +- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; +- else +- iwe.u.data.flags = IW_ENCODE_DISABLED; +- iwe.u.data.length = 0; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); +- +- /* Rates */ +- if (bi->rateset.count) { +- value = event + IW_EV_LCP_LEN; +- iwe.cmd = SIOCGIWRATE; +- /* Those two flags are ignored... */ +- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; +- for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { +- iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; +- value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, +- IW_EV_PARAM_LEN); +- } +- event = value; +- } +- } +- +- kfree(list); +- +- dwrq->length = event - extra; +- dwrq->flags = 0; /* todo */ +- +- return 0; +-} +- +-static int +-wl_iw_iscan_get_scan( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_scan_results_t *list; +- struct iw_event iwe; +- wl_bss_info_t *bi = NULL; +- int ii, j; +- int apcnt; +- char *event = extra, *end = extra + dwrq->length, *value; +- iscan_info_t *iscan = g_iscan; +- iscan_buf_t * p_buf; +- +- WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- /* use backup if our thread is not successful */ +- if ((!iscan) || (iscan->sysioc_pid < 0)) { +- return wl_iw_get_scan(dev, info, dwrq, extra); +- } +- +- /* Check for scan in progress */ +- if (iscan->iscan_state == ISCAN_STATE_SCANING) +- return -EAGAIN; +- +- apcnt = 0; +- p_buf = iscan->list_hdr; +- /* Get scan results */ +- while (p_buf != iscan->list_cur) { +- list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results; +- +- if (list->version != WL_BSS_INFO_VERSION) { +- WL_ERROR(("list->version %d != WL_BSS_INFO_VERSION\n", list->version)); +- } +- +- bi = NULL; +- for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) { +- bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; +- +- /* overflow check cover fields before wpa IEs */ +- if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN + +- IW_EV_QUAL_LEN >= end) +- return -E2BIG; +- /* First entry must be the BSSID */ +- iwe.cmd = SIOCGIWAP; +- iwe.u.ap_addr.sa_family = ARPHRD_ETHER; +- memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); +- event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); +- +- /* SSID */ +- iwe.u.data.length = dtoh32(bi->SSID_len); +- iwe.cmd = SIOCGIWESSID; +- iwe.u.data.flags = 1; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); +- +- /* Mode */ +- if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { +- iwe.cmd = SIOCGIWMODE; +- if (dtoh16(bi->capability) & DOT11_CAP_ESS) +- iwe.u.mode = IW_MODE_INFRA; +- else +- iwe.u.mode = IW_MODE_ADHOC; +- event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); +- } +- +- /* Channel */ +- iwe.cmd = SIOCGIWFREQ; +- +- iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), +- (CHSPEC_IS2G(bi->chanspec)) ? +- WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); +- iwe.u.freq.e = 6; +- event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); +- +- /* Channel quality */ +- iwe.cmd = IWEVQUAL; +- iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); +- iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); +- iwe.u.qual.noise = 0x100 + bi->phy_noise; +- event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); +- +- /* WPA, WPA2, WPS, WAPI IEs */ +- wl_iw_handle_scanresults_ies(&event, end, info, bi); +- +- /* Encryption */ +- iwe.cmd = SIOCGIWENCODE; +- if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) +- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; +- else +- iwe.u.data.flags = IW_ENCODE_DISABLED; +- iwe.u.data.length = 0; +- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); +- +- /* Rates */ +- if (bi->rateset.count <= sizeof(bi->rateset.rates)) { +- if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) +- return -E2BIG; +- +- value = event + IW_EV_LCP_LEN; +- iwe.cmd = SIOCGIWRATE; +- /* Those two flags are ignored... */ +- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; +- for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { +- iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; +- value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, +- IW_EV_PARAM_LEN); +- } +- event = value; +- } +- } +- p_buf = p_buf->next; +- } /* while (p_buf) */ +- +- dwrq->length = event - extra; +- dwrq->flags = 0; /* todo */ +- +- return 0; +-} +- +-#endif /* WIRELESS_EXT > 13 */ +- +- +-static int +-wl_iw_set_essid( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wlc_ssid_t ssid; +- int error; +- +- WL_TRACE(("%s: SIOCSIWESSID\n", dev->name)); +- +- /* default Broadcast SSID */ +- memset(&ssid, 0, sizeof(ssid)); +- if (dwrq->length && extra) { +-#if WIRELESS_EXT > 20 +- ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length); +-#else +- ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1); +-#endif +- memcpy(ssid.SSID, extra, ssid.SSID_len); +- ssid.SSID_len = htod32(ssid.SSID_len); +- +- if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid)))) +- return error; +- } +- /* If essid null then it is "iwconfig essid off" command */ +- else { +- scb_val_t scbval; +- bzero(&scbval, sizeof(scb_val_t)); +- if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) +- return error; +- } +- return 0; +-} +- +-static int +-wl_iw_get_essid( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wlc_ssid_t ssid; +- int error; +- +- WL_TRACE(("%s: SIOCGIWESSID\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) { +- WL_ERROR(("Error getting the SSID\n")); +- return error; +- } +- +- ssid.SSID_len = dtoh32(ssid.SSID_len); +- +- /* Get the current SSID */ +- memcpy(extra, ssid.SSID, ssid.SSID_len); +- +- dwrq->length = ssid.SSID_len; +- +- dwrq->flags = 1; /* active */ +- +- return 0; +-} +- +-static int +-wl_iw_set_nick( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_iw_t *iw = IW_DEV_IF(dev); +- WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- /* Check the size of the string */ +- if (dwrq->length > sizeof(iw->nickname)) +- return -E2BIG; +- +- memcpy(iw->nickname, extra, dwrq->length); +- iw->nickname[dwrq->length - 1] = '\0'; +- +- return 0; +-} +- +-static int +-wl_iw_get_nick( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_iw_t *iw = IW_DEV_IF(dev); +- WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name)); +- +- if (!extra) +- return -EINVAL; +- +- strcpy(extra, iw->nickname); +- dwrq->length = strlen(extra) + 1; +- +- return 0; +-} +- +-static int wl_iw_set_rate( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- wl_rateset_t rateset; +- int error, rate, i, error_bg, error_a; +- +- WL_TRACE(("%s: SIOCSIWRATE\n", dev->name)); +- +- /* Get current rateset */ +- if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) +- return error; +- +- rateset.count = dtoh32(rateset.count); +- +- if (vwrq->value < 0) { +- /* Select maximum rate */ +- rate = rateset.rates[rateset.count - 1] & 0x7f; +- } else if (vwrq->value < rateset.count) { +- /* Select rate by rateset index */ +- rate = rateset.rates[vwrq->value] & 0x7f; +- } else { +- /* Specified rate in bps */ +- rate = vwrq->value / 500000; +- } +- +- if (vwrq->fixed) { +- /* +- Set rate override, +- Since the is a/b/g-blind, both a/bg_rate are enforced. +- */ +- error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate); +- error_a = dev_wlc_intvar_set(dev, "a_rate", rate); +- +- if (error_bg && error_a) +- return (error_bg | error_a); +- } else { +- /* +- clear rate override +- Since the is a/b/g-blind, both a/bg_rate are enforced. +- */ +- /* 0 is for clearing rate override */ +- error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0); +- /* 0 is for clearing rate override */ +- error_a = dev_wlc_intvar_set(dev, "a_rate", 0); +- +- if (error_bg && error_a) +- return (error_bg | error_a); +- +- /* Remove rates above selected rate */ +- for (i = 0; i < rateset.count; i++) +- if ((rateset.rates[i] & 0x7f) > rate) +- break; +- rateset.count = htod32(i); +- +- /* Set current rateset */ +- if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset)))) +- return error; +- } +- +- return 0; +-} +- +-static int wl_iw_get_rate( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, rate; +- +- WL_TRACE(("%s: SIOCGIWRATE\n", dev->name)); +- +- /* Report the current tx rate */ +- if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate)))) +- return error; +- rate = dtoh32(rate); +- vwrq->value = rate * 500000; +- +- return 0; +-} +- +-static int +-wl_iw_set_rts( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, rts; +- +- WL_TRACE(("%s: SIOCSIWRTS\n", dev->name)); +- +- if (vwrq->disabled) +- rts = DOT11_DEFAULT_RTS_LEN; +- else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN) +- return -EINVAL; +- else +- rts = vwrq->value; +- +- if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts))) +- return error; +- +- return 0; +-} +- +-static int +-wl_iw_get_rts( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, rts; +- +- WL_TRACE(("%s: SIOCGIWRTS\n", dev->name)); +- +- if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts))) +- return error; +- +- vwrq->value = rts; +- vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN); +- vwrq->fixed = 1; +- +- return 0; +-} +- +-static int +-wl_iw_set_frag( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, frag; +- +- WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name)); +- +- if (vwrq->disabled) +- frag = DOT11_DEFAULT_FRAG_LEN; +- else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN) +- return -EINVAL; +- else +- frag = vwrq->value; +- +- if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag))) +- return error; +- +- return 0; +-} +- +-static int +-wl_iw_get_frag( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, fragthreshold; +- +- WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name)); +- +- if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold))) +- return error; +- +- vwrq->value = fragthreshold; +- vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN); +- vwrq->fixed = 1; +- +- return 0; +-} +- +-static int +-wl_iw_set_txpow( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, disable; +- uint16 txpwrmw; +- WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name)); +- +- /* Make sure radio is off or on as far as software is concerned */ +- disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0; +- disable += WL_RADIO_SW_DISABLE << 16; +- +- disable = htod32(disable); +- if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable)))) +- return error; +- +- /* If Radio is off, nothing more to do */ +- if (disable & WL_RADIO_SW_DISABLE) +- return 0; +- +- /* Only handle mW */ +- if (!(vwrq->flags & IW_TXPOW_MWATT)) +- return -EINVAL; +- +- /* Value < 0 means just "on" or "off" */ +- if (vwrq->value < 0) +- return 0; +- +- if (vwrq->value > 0xffff) txpwrmw = 0xffff; +- else txpwrmw = (uint16)vwrq->value; +- +- +- error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw))); +- return error; +-} +- +-static int +-wl_iw_get_txpow( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, disable, txpwrdbm; +- uint8 result; +- +- WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name)); +- +- if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) || +- (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm))) +- return error; +- +- disable = dtoh32(disable); +- result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE); +- vwrq->value = (int32)bcm_qdbm_to_mw(result); +- vwrq->fixed = 0; +- vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0; +- vwrq->flags = IW_TXPOW_MWATT; +- +- return 0; +-} +- +-#if WIRELESS_EXT > 10 +-static int +-wl_iw_set_retry( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, lrl, srl; +- +- WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name)); +- +- /* Do not handle "off" or "lifetime" */ +- if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME)) +- return -EINVAL; +- +- /* Handle "[min|max] limit" */ +- if (vwrq->flags & IW_RETRY_LIMIT) { +- /* "max limit" or just "limit" */ +-#if WIRELESS_EXT > 20 +- if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) || +- !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) { +-#else +- if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) { +-#endif /* WIRELESS_EXT > 20 */ +- +- lrl = htod32(vwrq->value); +- if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl)))) +- return error; +- } +- /* "min limit" or just "limit" */ +-#if WIRELESS_EXT > 20 +- if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) || +- !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) { +-#else +- if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) { +-#endif /* WIRELESS_EXT > 20 */ +- +- srl = htod32(vwrq->value); +- if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl)))) +- return error; +- } +- } +- +- return 0; +-} +- +-static int +-wl_iw_get_retry( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, lrl, srl; +- +- WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name)); +- +- vwrq->disabled = 0; /* Can't be disabled */ +- +- /* Do not handle lifetime queries */ +- if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) +- return -EINVAL; +- +- /* Get retry limits */ +- if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) || +- (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl)))) +- return error; +- +- lrl = dtoh32(lrl); +- srl = dtoh32(srl); +- +- /* Note : by default, display the min retry number */ +- if (vwrq->flags & IW_RETRY_MAX) { +- vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; +- vwrq->value = lrl; +- } else { +- vwrq->flags = IW_RETRY_LIMIT; +- vwrq->value = srl; +- if (srl != lrl) +- vwrq->flags |= IW_RETRY_MIN; +- } +- +- return 0; +-} +-#endif /* WIRELESS_EXT > 10 */ +- +-static int +-wl_iw_set_encode( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_wsec_key_t key; +- int error, val, wsec; +- +- WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name)); +- +- memset(&key, 0, sizeof(key)); +- +- if ((dwrq->flags & IW_ENCODE_INDEX) == 0) { +- /* Find the current key */ +- for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) { +- val = htod32(key.index); +- if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val)))) +- return error; +- val = dtoh32(val); +- if (val) +- break; +- } +- /* Default to 0 */ +- if (key.index == DOT11_MAX_DEFAULT_KEYS) +- key.index = 0; +- } else { +- key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; +- if (key.index >= DOT11_MAX_DEFAULT_KEYS) +- return -EINVAL; +- } +- +- /* Interpret "off" to mean no encryption */ +- wsec = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED; +- +- if ((error = dev_wlc_intvar_set(dev, "wsec", wsec))) +- return error; +- +- /* Old API used to pass a NULL pointer instead of IW_ENCODE_NOKEY */ +- if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) { +- /* Just select a new current key */ +- val = htod32(key.index); +- if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val)))) +- return error; +- } else { +- key.len = dwrq->length; +- +- if (dwrq->length > sizeof(key.data)) +- return -EINVAL; +- +- memcpy(key.data, extra, dwrq->length); +- +- key.flags = WL_PRIMARY_KEY; +- switch (key.len) { +- case WEP1_KEY_SIZE: +- key.algo = CRYPTO_ALGO_WEP1; +- break; +- case WEP128_KEY_SIZE: +- key.algo = CRYPTO_ALGO_WEP128; +- break; +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) +- case TKIP_KEY_SIZE: +- key.algo = CRYPTO_ALGO_TKIP; +- break; +-#endif +- case AES_KEY_SIZE: +- key.algo = CRYPTO_ALGO_AES_CCM; +- break; +- default: +- return -EINVAL; +- } +- +- /* Set the new key/index */ +- swap_key_from_BE(&key); +- if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)))) +- return error; +- } +- +- /* Interpret "restricted" to mean shared key authentication */ +- val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0; +- val = htod32(val); +- if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val)))) +- return error; +- +- return 0; +-} +- +-static int +-wl_iw_get_encode( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_wsec_key_t key; +- int error, val, wsec, auth; +- +- WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name)); +- +- /* assure default values of zero for things we don't touch */ +- bzero(&key, sizeof(wl_wsec_key_t)); +- +- if ((dwrq->flags & IW_ENCODE_INDEX) == 0) { +- /* Find the current key */ +- for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) { +- val = key.index; +- if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val)))) +- return error; +- val = dtoh32(val); +- if (val) +- break; +- } +- } else +- key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; +- +- if (key.index >= DOT11_MAX_DEFAULT_KEYS) +- key.index = 0; +- +- /* Get info */ +- +- if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) || +- (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth)))) +- return error; +- +- swap_key_to_BE(&key); +- +- wsec = dtoh32(wsec); +- auth = dtoh32(auth); +- /* Get key length */ +- dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len); +- +- /* Get flags */ +- dwrq->flags = key.index + 1; +- if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) { +- /* Interpret "off" to mean no encryption */ +- dwrq->flags |= IW_ENCODE_DISABLED; +- } +- if (auth) { +- /* Interpret "restricted" to mean shared key authentication */ +- dwrq->flags |= IW_ENCODE_RESTRICTED; +- } +- +- /* Get key */ +- if (dwrq->length && extra) +- memcpy(extra, key.data, dwrq->length); +- +- return 0; +-} +- +-static int +-wl_iw_set_power( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, pm; +- +- WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name)); +- +- pm = vwrq->disabled ? PM_OFF : PM_MAX; +- +- pm = htod32(pm); +- if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)))) +- return error; +- +- return 0; +-} +- +-static int +-wl_iw_get_power( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error, pm; +- +- WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name)); +- +- if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm)))) +- return error; +- +- pm = dtoh32(pm); +- vwrq->disabled = pm ? 0 : 1; +- vwrq->flags = IW_POWER_ALL_R; +- +- return 0; +-} +- +-#if WIRELESS_EXT > 17 +-static int +-wl_iw_set_wpaie( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *iwp, +- char *extra +-) +-{ +- dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length); +- +- return 0; +-} +- +-static int +-wl_iw_get_wpaie( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *iwp, +- char *extra +-) +-{ +- WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name)); +- iwp->length = 64; +- dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length); +- return 0; +-} +- +-static int +-wl_iw_set_encodeext( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_point *dwrq, +- char *extra +-) +-{ +- wl_wsec_key_t key; +- int error; +- struct iw_encode_ext *iwe; +- +- WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name)); +- +- memset(&key, 0, sizeof(key)); +- iwe = (struct iw_encode_ext *)extra; +- +- /* disable encryption completely */ +- if (dwrq->flags & IW_ENCODE_DISABLED) { +- +- } +- +- /* get the key index */ +- key.index = 0; +- if (dwrq->flags & IW_ENCODE_INDEX) +- key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; +- +- key.len = iwe->key_len; +- +- /* Instead of bcast for ea address for default wep keys, driver needs it to be Null */ +- if (!ETHER_ISMULTI(iwe->addr.sa_data)) +- bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN); +- +- /* check for key index change */ +- if (key.len == 0) { +- if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { +- WL_WSEC(("Changing the the primary Key to %d\n", key.index)); +- /* change the key index .... */ +- key.index = htod32(key.index); +- error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, +- &key.index, sizeof(key.index)); +- if (error) +- return error; +- } +- /* key delete */ +- else { +- swap_key_from_BE(&key); +- error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); +- if (error) +- return error; +- } +- } +- /* This case is used to allow an external 802.1x supplicant +- * to pass the PMK to the in-driver supplicant for use in +- * the 4-way handshake. +- */ +- else if (iwe->alg == IW_ENCODE_ALG_PMK) { +- int j; +- wsec_pmk_t pmk; +- char keystring[WSEC_MAX_PSK_LEN + 1]; +- char* charptr = keystring; +- uint len; +- +- /* copy the raw hex key to the appropriate format */ +- for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) { +- sprintf(charptr, "%02x", iwe->key[j]); +- charptr += 2; +- } +- len = strlen(keystring); +- pmk.key_len = htod16(len); +- bcopy(keystring, pmk.key, len); +- pmk.flags = htod16(WSEC_PASSPHRASE); +- +- error = dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk)); +- if (error) +- return error; +- } +- +- else { +- if (iwe->key_len > sizeof(key.data)) +- return -EINVAL; +- +- WL_WSEC(("Setting the key index %d\n", key.index)); +- if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { +- WL_WSEC(("key is a Primary Key\n")); +- key.flags = WL_PRIMARY_KEY; +- } +- +- bcopy((void *)iwe->key, key.data, iwe->key_len); +- +- if (iwe->alg == IW_ENCODE_ALG_TKIP) { +- uint8 keybuf[8]; +- bcopy(&key.data[24], keybuf, sizeof(keybuf)); +- bcopy(&key.data[16], &key.data[24], sizeof(keybuf)); +- bcopy(keybuf, &key.data[16], sizeof(keybuf)); +- } +- +- /* rx iv */ +- if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { +- uchar *ivptr; +- ivptr = (uchar *)iwe->rx_seq; +- key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | +- (ivptr[3] << 8) | ivptr[2]; +- key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; +- key.iv_initialized = TRUE; +- } +- +- switch (iwe->alg) { +- case IW_ENCODE_ALG_NONE: +- key.algo = CRYPTO_ALGO_OFF; +- break; +- case IW_ENCODE_ALG_WEP: +- if (iwe->key_len == WEP1_KEY_SIZE) +- key.algo = CRYPTO_ALGO_WEP1; +- else +- key.algo = CRYPTO_ALGO_WEP128; +- break; +- case IW_ENCODE_ALG_TKIP: +- key.algo = CRYPTO_ALGO_TKIP; +- break; +- case IW_ENCODE_ALG_CCMP: +- key.algo = CRYPTO_ALGO_AES_CCM; +- break; +- default: +- break; +- } +- swap_key_from_BE(&key); +- +- dhd_wait_pend8021x(dev); +- +- error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); +- if (error) +- return error; +- } +- return 0; +-} +- +- +-#if WIRELESS_EXT > 17 +-struct { +- pmkid_list_t pmkids; +- pmkid_t foo[MAXPMKID-1]; +-} pmkid_list; +-static int +-wl_iw_set_pmksa( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- struct iw_pmksa *iwpmksa; +- uint i; +- char eabuf[ETHER_ADDR_STR_LEN]; +- pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid; +- +- WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name)); +- iwpmksa = (struct iw_pmksa *)extra; +- bzero((char *)eabuf, ETHER_ADDR_STR_LEN); +- if (iwpmksa->cmd == IW_PMKSA_FLUSH) { +- WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n")); +- bzero((char *)&pmkid_list, sizeof(pmkid_list)); +- } +- if (iwpmksa->cmd == IW_PMKSA_REMOVE) { +- pmkid_list_t pmkid, *pmkidptr; +- pmkidptr = &pmkid; +- bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN); +- bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN); +- { +- uint j; +- WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ", +- bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID, +- eabuf))); +- for (j = 0; j < WPA2_PMKID_LEN; j++) +- WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j])); +- WL_TRACE(("\n")); +- } +- for (i = 0; i < pmkid_list.pmkids.npmkid; i++) +- if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID, +- ETHER_ADDR_LEN)) +- break; +- for (; i < pmkid_list.pmkids.npmkid; i++) { +- bcopy(&pmkid_array[i+1].BSSID, +- &pmkid_array[i].BSSID, +- ETHER_ADDR_LEN); +- bcopy(&pmkid_array[i+1].PMKID, +- &pmkid_array[i].PMKID, +- WPA2_PMKID_LEN); +- } +- pmkid_list.pmkids.npmkid--; +- } +- if (iwpmksa->cmd == IW_PMKSA_ADD) { +- bcopy(&iwpmksa->bssid.sa_data[0], +- &pmkid_array[pmkid_list.pmkids.npmkid].BSSID, +- ETHER_ADDR_LEN); +- bcopy(&iwpmksa->pmkid[0], &pmkid_array[pmkid_list.pmkids.npmkid].PMKID, +- WPA2_PMKID_LEN); +- { +- uint j; +- uint k; +- k = pmkid_list.pmkids.npmkid; +- BCM_REFERENCE(k); +- WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ", +- bcm_ether_ntoa(&pmkid_array[k].BSSID, +- eabuf))); +- for (j = 0; j < WPA2_PMKID_LEN; j++) +- WL_TRACE(("%02x ", pmkid_array[k].PMKID[j])); +- WL_TRACE(("\n")); +- } +- pmkid_list.pmkids.npmkid++; +- } +- WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid)); +- for (i = 0; i < pmkid_list.pmkids.npmkid; i++) { +- uint j; +- WL_TRACE(("PMKID[%d]: %s = ", i, +- bcm_ether_ntoa(&pmkid_array[i].BSSID, +- eabuf))); +- for (j = 0; j < WPA2_PMKID_LEN; j++) +- WL_TRACE(("%02x ", pmkid_array[i].PMKID[j])); +- printf("\n"); +- } +- WL_TRACE(("\n")); +- dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list)); +- return 0; +-} +-#endif /* WIRELESS_EXT > 17 */ +- +-static int +-wl_iw_get_encodeext( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name)); +- return 0; +-} +- +-static int +-wl_iw_set_wpaauth( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error = 0; +- int paramid; +- int paramval; +- uint32 cipher_combined; +- int val = 0; +- wl_iw_t *iw = IW_DEV_IF(dev); +- +- WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name)); +- +- paramid = vwrq->flags & IW_AUTH_INDEX; +- paramval = vwrq->value; +- +- WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n", +- dev->name, paramid, paramval)); +- +- switch (paramid) { +- +- case IW_AUTH_WPA_VERSION: +- /* supported wpa version disabled or wpa or wpa2 */ +- if (paramval & IW_AUTH_WPA_VERSION_DISABLED) +- val = WPA_AUTH_DISABLED; +- else if (paramval & (IW_AUTH_WPA_VERSION_WPA)) +- val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; +- else if (paramval & IW_AUTH_WPA_VERSION_WPA2) +- val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; +- WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val)); +- if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) +- return error; +- break; +- +- case IW_AUTH_CIPHER_PAIRWISE: +- case IW_AUTH_CIPHER_GROUP: { +- int fbt_cap = 0; +- +- if (paramid == IW_AUTH_CIPHER_PAIRWISE) { +- iw->pwsec = paramval; +- } +- else { +- iw->gwsec = paramval; +- } +- +- if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) +- return error; +- +- cipher_combined = iw->gwsec | iw->pwsec; +- val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED); +- if (cipher_combined & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) +- val |= WEP_ENABLED; +- if (cipher_combined & IW_AUTH_CIPHER_TKIP) +- val |= TKIP_ENABLED; +- if (cipher_combined & IW_AUTH_CIPHER_CCMP) +- val |= AES_ENABLED; +- +- if (iw->privacy_invoked && !val) { +- WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming " +- "we're a WPS enrollee\n", dev->name, __FUNCTION__)); +- if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) { +- WL_WSEC(("Failed to set iovar is_WPS_enrollee\n")); +- return error; +- } +- } else if (val) { +- if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { +- WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n")); +- return error; +- } +- } +- +- if ((error = dev_wlc_intvar_set(dev, "wsec", val))) +- return error; +- +- /* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way +- * handshake. +- */ +- if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) { +- if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) { +- if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val & AES_ENABLED)) { +- if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1))) +- return error; +- } +- else if (val == 0) { +- if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0))) +- return error; +- } +- } +- } +- break; +- } +- +- case IW_AUTH_KEY_MGMT: +- if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) +- return error; +- +- if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { +- if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK)) +- val = WPA_AUTH_PSK; +- else +- val = WPA_AUTH_UNSPECIFIED; +- if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK)) +- val |= WPA2_AUTH_FT; +- } +- else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { +- if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK)) +- val = WPA2_AUTH_PSK; +- else +- val = WPA2_AUTH_UNSPECIFIED; +- if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK)) +- val |= WPA2_AUTH_FT; +- } +- WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); +- if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) +- return error; +- break; +- +- case IW_AUTH_TKIP_COUNTERMEASURES: +- dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)¶mval, 1); +- break; +- +- case IW_AUTH_80211_AUTH_ALG: +- /* open shared */ +- WL_ERROR(("Setting the D11auth %d\n", paramval)); +- if (paramval & IW_AUTH_ALG_OPEN_SYSTEM) +- val = 0; +- else if (paramval & IW_AUTH_ALG_SHARED_KEY) +- val = 1; +- else +- error = 1; +- if (!error && (error = dev_wlc_intvar_set(dev, "auth", val))) +- return error; +- break; +- +- case IW_AUTH_WPA_ENABLED: +- if (paramval == 0) { +- val = 0; +- WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); +- error = dev_wlc_intvar_set(dev, "wpa_auth", val); +- return error; +- } +- else { +- /* If WPA is enabled, wpa_auth is set elsewhere */ +- } +- break; +- +- case IW_AUTH_DROP_UNENCRYPTED: +- dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)¶mval, 1); +- break; +- +- case IW_AUTH_RX_UNENCRYPTED_EAPOL: +- dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)¶mval, 1); +- break; +- +-#if WIRELESS_EXT > 17 +- +- case IW_AUTH_ROAMING_CONTROL: +- WL_TRACE(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__)); +- /* driver control or user space app control */ +- break; +- +- case IW_AUTH_PRIVACY_INVOKED: { +- int wsec; +- +- if (paramval == 0) { +- iw->privacy_invoked = FALSE; +- if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { +- WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n")); +- return error; +- } +- } else { +- iw->privacy_invoked = TRUE; +- if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec))) +- return error; +- +- if (!WSEC_ENABLED(wsec)) { +- /* if privacy is true, but wsec is false, we are a WPS enrollee */ +- if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) { +- WL_WSEC(("Failed to set iovar is_WPS_enrollee\n")); +- return error; +- } +- } else { +- if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { +- WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n")); +- return error; +- } +- } +- } +- break; +- } +- +- +-#endif /* WIRELESS_EXT > 17 */ +- +- +- default: +- break; +- } +- return 0; +-} +-#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK)) +- +-static int +-wl_iw_get_wpaauth( +- struct net_device *dev, +- struct iw_request_info *info, +- struct iw_param *vwrq, +- char *extra +-) +-{ +- int error; +- int paramid; +- int paramval = 0; +- int val; +- wl_iw_t *iw = IW_DEV_IF(dev); +- +- WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name)); +- +- paramid = vwrq->flags & IW_AUTH_INDEX; +- +- switch (paramid) { +- case IW_AUTH_WPA_VERSION: +- /* supported wpa version disabled or wpa or wpa2 */ +- if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) +- return error; +- if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED)) +- paramval = IW_AUTH_WPA_VERSION_DISABLED; +- else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) +- paramval = IW_AUTH_WPA_VERSION_WPA; +- else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) +- paramval = IW_AUTH_WPA_VERSION_WPA2; +- break; +- +- case IW_AUTH_CIPHER_PAIRWISE: +- paramval = iw->pwsec; +- break; +- +- case IW_AUTH_CIPHER_GROUP: +- paramval = iw->gwsec; +- break; +- +- case IW_AUTH_KEY_MGMT: +- /* psk, 1x */ +- if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) +- return error; +- if (VAL_PSK(val)) +- paramval = IW_AUTH_KEY_MGMT_PSK; +- else +- paramval = IW_AUTH_KEY_MGMT_802_1X; +- +- break; +- case IW_AUTH_TKIP_COUNTERMEASURES: +- dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)¶mval, 1); +- break; +- +- case IW_AUTH_DROP_UNENCRYPTED: +- dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)¶mval, 1); +- break; +- +- case IW_AUTH_RX_UNENCRYPTED_EAPOL: +- dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)¶mval, 1); +- break; +- +- case IW_AUTH_80211_AUTH_ALG: +- /* open, shared, leap */ +- if ((error = dev_wlc_intvar_get(dev, "auth", &val))) +- return error; +- if (!val) +- paramval = IW_AUTH_ALG_OPEN_SYSTEM; +- else +- paramval = IW_AUTH_ALG_SHARED_KEY; +- break; +- case IW_AUTH_WPA_ENABLED: +- if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) +- return error; +- if (val) +- paramval = TRUE; +- else +- paramval = FALSE; +- break; +- +-#if WIRELESS_EXT > 17 +- +- case IW_AUTH_ROAMING_CONTROL: +- WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__)); +- /* driver control or user space app control */ +- break; +- +- case IW_AUTH_PRIVACY_INVOKED: +- paramval = iw->privacy_invoked; +- break; +- +-#endif /* WIRELESS_EXT > 17 */ +- } +- vwrq->value = paramval; +- return 0; +-} +-#endif /* WIRELESS_EXT > 17 */ +- +-static const iw_handler wl_iw_handler[] = +-{ +- (iw_handler) wl_iw_config_commit, /* SIOCSIWCOMMIT */ +- (iw_handler) wl_iw_get_name, /* SIOCGIWNAME */ +- (iw_handler) NULL, /* SIOCSIWNWID */ +- (iw_handler) NULL, /* SIOCGIWNWID */ +- (iw_handler) wl_iw_set_freq, /* SIOCSIWFREQ */ +- (iw_handler) wl_iw_get_freq, /* SIOCGIWFREQ */ +- (iw_handler) wl_iw_set_mode, /* SIOCSIWMODE */ +- (iw_handler) wl_iw_get_mode, /* SIOCGIWMODE */ +- (iw_handler) NULL, /* SIOCSIWSENS */ +- (iw_handler) NULL, /* SIOCGIWSENS */ +- (iw_handler) NULL, /* SIOCSIWRANGE */ +- (iw_handler) wl_iw_get_range, /* SIOCGIWRANGE */ +- (iw_handler) NULL, /* SIOCSIWPRIV */ +- (iw_handler) NULL, /* SIOCGIWPRIV */ +- (iw_handler) NULL, /* SIOCSIWSTATS */ +- (iw_handler) NULL, /* SIOCGIWSTATS */ +- (iw_handler) wl_iw_set_spy, /* SIOCSIWSPY */ +- (iw_handler) wl_iw_get_spy, /* SIOCGIWSPY */ +- (iw_handler) NULL, /* -- hole -- */ +- (iw_handler) NULL, /* -- hole -- */ +- (iw_handler) wl_iw_set_wap, /* SIOCSIWAP */ +- (iw_handler) wl_iw_get_wap, /* SIOCGIWAP */ +-#if WIRELESS_EXT > 17 +- (iw_handler) wl_iw_mlme, /* SIOCSIWMLME */ +-#else +- (iw_handler) NULL, /* -- hole -- */ +-#endif +- (iw_handler) wl_iw_iscan_get_aplist, /* SIOCGIWAPLIST */ +-#if WIRELESS_EXT > 13 +- (iw_handler) wl_iw_iscan_set_scan, /* SIOCSIWSCAN */ +- (iw_handler) wl_iw_iscan_get_scan, /* SIOCGIWSCAN */ +-#else /* WIRELESS_EXT > 13 */ +- (iw_handler) NULL, /* SIOCSIWSCAN */ +- (iw_handler) NULL, /* SIOCGIWSCAN */ +-#endif /* WIRELESS_EXT > 13 */ +- (iw_handler) wl_iw_set_essid, /* SIOCSIWESSID */ +- (iw_handler) wl_iw_get_essid, /* SIOCGIWESSID */ +- (iw_handler) wl_iw_set_nick, /* SIOCSIWNICKN */ +- (iw_handler) wl_iw_get_nick, /* SIOCGIWNICKN */ +- (iw_handler) NULL, /* -- hole -- */ +- (iw_handler) NULL, /* -- hole -- */ +- (iw_handler) wl_iw_set_rate, /* SIOCSIWRATE */ +- (iw_handler) wl_iw_get_rate, /* SIOCGIWRATE */ +- (iw_handler) wl_iw_set_rts, /* SIOCSIWRTS */ +- (iw_handler) wl_iw_get_rts, /* SIOCGIWRTS */ +- (iw_handler) wl_iw_set_frag, /* SIOCSIWFRAG */ +- (iw_handler) wl_iw_get_frag, /* SIOCGIWFRAG */ +- (iw_handler) wl_iw_set_txpow, /* SIOCSIWTXPOW */ +- (iw_handler) wl_iw_get_txpow, /* SIOCGIWTXPOW */ +-#if WIRELESS_EXT > 10 +- (iw_handler) wl_iw_set_retry, /* SIOCSIWRETRY */ +- (iw_handler) wl_iw_get_retry, /* SIOCGIWRETRY */ +-#endif /* WIRELESS_EXT > 10 */ +- (iw_handler) wl_iw_set_encode, /* SIOCSIWENCODE */ +- (iw_handler) wl_iw_get_encode, /* SIOCGIWENCODE */ +- (iw_handler) wl_iw_set_power, /* SIOCSIWPOWER */ +- (iw_handler) wl_iw_get_power, /* SIOCGIWPOWER */ +-#if WIRELESS_EXT > 17 +- (iw_handler) NULL, /* -- hole -- */ +- (iw_handler) NULL, /* -- hole -- */ +- (iw_handler) wl_iw_set_wpaie, /* SIOCSIWGENIE */ +- (iw_handler) wl_iw_get_wpaie, /* SIOCGIWGENIE */ +- (iw_handler) wl_iw_set_wpaauth, /* SIOCSIWAUTH */ +- (iw_handler) wl_iw_get_wpaauth, /* SIOCGIWAUTH */ +- (iw_handler) wl_iw_set_encodeext, /* SIOCSIWENCODEEXT */ +- (iw_handler) wl_iw_get_encodeext, /* SIOCGIWENCODEEXT */ +- (iw_handler) wl_iw_set_pmksa, /* SIOCSIWPMKSA */ +-#endif /* WIRELESS_EXT > 17 */ +-}; +- +-#if WIRELESS_EXT > 12 +-enum { +- WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV, +- WL_IW_SET_VLANMODE, +- WL_IW_SET_PM, +-#if WIRELESS_EXT > 17 +-#endif /* WIRELESS_EXT > 17 */ +- WL_IW_SET_LAST +-}; +- +-static iw_handler wl_iw_priv_handler[] = { +- wl_iw_set_leddc, +- wl_iw_set_vlanmode, +- wl_iw_set_pm, +-#if WIRELESS_EXT > 17 +-#endif /* WIRELESS_EXT > 17 */ +- NULL +-}; +- +-static struct iw_priv_args wl_iw_priv_args[] = { +- { +- WL_IW_SET_LEDDC, +- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, +- 0, +- "set_leddc" +- }, +- { +- WL_IW_SET_VLANMODE, +- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, +- 0, +- "set_vlanmode" +- }, +- { +- WL_IW_SET_PM, +- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, +- 0, +- "set_pm" +- }, +-#if WIRELESS_EXT > 17 +-#endif /* WIRELESS_EXT > 17 */ +- { 0, 0, 0, { 0 } } +-}; +- +-const struct iw_handler_def wl_iw_handler_def = +-{ +- .num_standard = ARRAYSIZE(wl_iw_handler), +- .num_private = ARRAY_SIZE(wl_iw_priv_handler), +- .num_private_args = ARRAY_SIZE(wl_iw_priv_args), +- .standard = (iw_handler *) wl_iw_handler, +- .private = wl_iw_priv_handler, +- .private_args = wl_iw_priv_args, +-#if WIRELESS_EXT >= 19 +- get_wireless_stats: dhd_get_wireless_stats, +-#endif /* WIRELESS_EXT >= 19 */ +- }; +-#endif /* WIRELESS_EXT > 12 */ +- +-int +-wl_iw_ioctl( +- struct net_device *dev, +- struct ifreq *rq, +- int cmd +-) +-{ +- struct iwreq *wrq = (struct iwreq *) rq; +- struct iw_request_info info; +- iw_handler handler; +- char *extra = NULL; +- size_t token_size = 1; +- int max_tokens = 0, ret = 0; +- +- if (cmd < SIOCIWFIRST || +- IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) || +- !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) +- return -EOPNOTSUPP; +- +- switch (cmd) { +- +- case SIOCSIWESSID: +- case SIOCGIWESSID: +- case SIOCSIWNICKN: +- case SIOCGIWNICKN: +- max_tokens = IW_ESSID_MAX_SIZE + 1; +- break; +- +- case SIOCSIWENCODE: +- case SIOCGIWENCODE: +-#if WIRELESS_EXT > 17 +- case SIOCSIWENCODEEXT: +- case SIOCGIWENCODEEXT: +-#endif +- max_tokens = IW_ENCODING_TOKEN_MAX; +- break; +- +- case SIOCGIWRANGE: +- max_tokens = sizeof(struct iw_range); +- break; +- +- case SIOCGIWAPLIST: +- token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality); +- max_tokens = IW_MAX_AP; +- break; +- +-#if WIRELESS_EXT > 13 +- case SIOCGIWSCAN: +- if (g_iscan) +- max_tokens = wrq->u.data.length; +- else +- max_tokens = IW_SCAN_MAX_DATA; +- break; +-#endif /* WIRELESS_EXT > 13 */ +- +- case SIOCSIWSPY: +- token_size = sizeof(struct sockaddr); +- max_tokens = IW_MAX_SPY; +- break; +- +- case SIOCGIWSPY: +- token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality); +- max_tokens = IW_MAX_SPY; +- break; +- default: +- break; +- } +- +- if (max_tokens && wrq->u.data.pointer) { +- if (wrq->u.data.length > max_tokens) +- return -E2BIG; +- +- if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) +- return -ENOMEM; +- +- if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) { +- kfree(extra); +- return -EFAULT; +- } +- } +- +- info.cmd = cmd; +- info.flags = 0; +- +- ret = handler(dev, &info, &wrq->u, extra); +- +- if (extra) { +- if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) { +- kfree(extra); +- return -EFAULT; +- } +- +- kfree(extra); +- } +- +- return ret; +-} +- +-/* Convert a connection status event into a connection status string. +- * Returns TRUE if a matching connection status string was found. +- */ +-bool +-wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason, +- char* stringBuf, uint buflen) +-{ +- typedef struct conn_fail_event_map_t { +- uint32 inEvent; /* input: event type to match */ +- uint32 inStatus; /* input: event status code to match */ +- uint32 inReason; /* input: event reason code to match */ +- const char* outName; /* output: failure type */ +- const char* outCause; /* output: failure cause */ +- } conn_fail_event_map_t; +- +- /* Map of WLC_E events to connection failure strings */ +-# define WL_IW_DONT_CARE 9999 +- const conn_fail_event_map_t event_map [] = { +- /* inEvent inStatus inReason */ +- /* outName outCause */ +- {WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE, +- "Conn", "Success"}, +- {WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE, +- "Conn", "NoNetworks"}, +- {WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, +- "Conn", "ConfigMismatch"}, +- {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH, +- "Conn", "EncrypMismatch"}, +- {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH, +- "Conn", "RsnMismatch"}, +- {WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE, +- "Conn", "AuthTimeout"}, +- {WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, +- "Conn", "AuthFail"}, +- {WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE, +- "Conn", "AuthNoAck"}, +- {WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, +- "Conn", "ReassocFail"}, +- {WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE, +- "Conn", "ReassocTimeout"}, +- {WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE, +- "Conn", "ReassocAbort"}, +- {WLC_E_PSK_SUP, WLC_SUP_KEYED, WL_IW_DONT_CARE, +- "Sup", "ConnSuccess"}, +- {WLC_E_PSK_SUP, WL_IW_DONT_CARE, WL_IW_DONT_CARE, +- "Sup", "WpaHandshakeFail"}, +- {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE, +- "Conn", "Deauth"}, +- {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE, +- "Conn", "DisassocInd"}, +- {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE, +- "Conn", "Disassoc"} +- }; +- +- const char* name = ""; +- const char* cause = NULL; +- int i; +- +- /* Search the event map table for a matching event */ +- for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) { +- const conn_fail_event_map_t* row = &event_map[i]; +- if (row->inEvent == event_type && +- (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) && +- (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) { +- name = row->outName; +- cause = row->outCause; +- break; +- } +- } +- +- /* If found, generate a connection failure string and return TRUE */ +- if (cause) { +- memset(stringBuf, 0, buflen); +- snprintf(stringBuf, buflen, "%s %s %02d %02d", +- name, cause, status, reason); +- WL_TRACE(("Connection status: %s\n", stringBuf)); +- return TRUE; +- } else { +- return FALSE; +- } +-} +- +-#if (WIRELESS_EXT > 14) +-/* Check if we have received an event that indicates connection failure +- * If so, generate a connection failure report string. +- * The caller supplies a buffer to hold the generated string. +- */ +-static bool +-wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen) +-{ +- uint32 event = ntoh32(e->event_type); +- uint32 status = ntoh32(e->status); +- uint32 reason = ntoh32(e->reason); +- +- if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) { +- return TRUE; +- } else +- { +- return FALSE; +- } +-} +-#endif /* WIRELESS_EXT > 14 */ +- +-#ifndef IW_CUSTOM_MAX +-#define IW_CUSTOM_MAX 256 /* size of extra buffer used for translation of events */ +-#endif /* IW_CUSTOM_MAX */ +- +-void +-wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) +-{ +-#if WIRELESS_EXT > 13 +- union iwreq_data wrqu; +- char extra[IW_CUSTOM_MAX + 1]; +- int cmd = 0; +- uint32 event_type = ntoh32(e->event_type); +- uint16 flags = ntoh16(e->flags); +- uint32 datalen = ntoh32(e->datalen); +- uint32 status = ntoh32(e->status); +- +- memset(&wrqu, 0, sizeof(wrqu)); +- memset(extra, 0, sizeof(extra)); +- +- memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); +- wrqu.addr.sa_family = ARPHRD_ETHER; +- +- switch (event_type) { +- case WLC_E_TXFAIL: +- cmd = IWEVTXDROP; +- break; +-#if WIRELESS_EXT > 14 +- case WLC_E_JOIN: +- case WLC_E_ASSOC_IND: +- case WLC_E_REASSOC_IND: +- cmd = IWEVREGISTERED; +- break; +- case WLC_E_DEAUTH_IND: +- case WLC_E_DISASSOC_IND: +- cmd = SIOCGIWAP; +- wrqu.data.length = strlen(extra); +- bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); +- bzero(&extra, ETHER_ADDR_LEN); +- break; +- +- case WLC_E_LINK: +- case WLC_E_NDIS_LINK: +- cmd = SIOCGIWAP; +- wrqu.data.length = strlen(extra); +- if (!(flags & WLC_EVENT_MSG_LINK)) { +- bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); +- bzero(&extra, ETHER_ADDR_LEN); +- } +- break; +- case WLC_E_ACTION_FRAME: +- cmd = IWEVCUSTOM; +- if (datalen + 1 <= sizeof(extra)) { +- wrqu.data.length = datalen + 1; +- extra[0] = WLC_E_ACTION_FRAME; +- memcpy(&extra[1], data, datalen); +- WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length)); +- } +- break; +- +- case WLC_E_ACTION_FRAME_COMPLETE: +- cmd = IWEVCUSTOM; +- if (sizeof(status) + 1 <= sizeof(extra)) { +- wrqu.data.length = sizeof(status) + 1; +- extra[0] = WLC_E_ACTION_FRAME_COMPLETE; +- memcpy(&extra[1], &status, sizeof(status)); +- WL_TRACE(("wl_iw_event status %d \n", status)); +- } +- break; +-#endif /* WIRELESS_EXT > 14 */ +-#if WIRELESS_EXT > 17 +- case WLC_E_MIC_ERROR: { +- struct iw_michaelmicfailure *micerrevt = (struct iw_michaelmicfailure *)&extra; +- cmd = IWEVMICHAELMICFAILURE; +- wrqu.data.length = sizeof(struct iw_michaelmicfailure); +- if (flags & WLC_EVENT_MSG_GROUP) +- micerrevt->flags |= IW_MICFAILURE_GROUP; +- else +- micerrevt->flags |= IW_MICFAILURE_PAIRWISE; +- memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN); +- micerrevt->src_addr.sa_family = ARPHRD_ETHER; +- +- break; +- } +- +- case WLC_E_ASSOC_REQ_IE: +- cmd = IWEVASSOCREQIE; +- wrqu.data.length = datalen; +- if (datalen < sizeof(extra)) +- memcpy(extra, data, datalen); +- break; +- +- case WLC_E_ASSOC_RESP_IE: +- cmd = IWEVASSOCRESPIE; +- wrqu.data.length = datalen; +- if (datalen < sizeof(extra)) +- memcpy(extra, data, datalen); +- break; +- +- case WLC_E_PMKID_CACHE: { +- struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra; +- pmkid_cand_list_t *pmkcandlist; +- pmkid_cand_t *pmkidcand; +- int count; +- +- if (data == NULL) +- break; +- +- cmd = IWEVPMKIDCAND; +- pmkcandlist = data; +- count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand); +- wrqu.data.length = sizeof(struct iw_pmkid_cand); +- pmkidcand = pmkcandlist->pmkid_cand; +- while (count) { +- bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand)); +- if (pmkidcand->preauth) +- iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH; +- bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data, +- ETHER_ADDR_LEN); +- wireless_send_event(dev, cmd, &wrqu, extra); +- pmkidcand++; +- count--; +- } +- break; +- } +-#endif /* WIRELESS_EXT > 17 */ +- +- case WLC_E_SCAN_COMPLETE: +-#if WIRELESS_EXT > 14 +- cmd = SIOCGIWSCAN; +-#endif +- WL_TRACE(("event WLC_E_SCAN_COMPLETE\n")); +- if ((g_iscan) && (g_iscan->sysioc_pid >= 0) && +- (g_iscan->iscan_state != ISCAN_STATE_IDLE)) +- up(&g_iscan->sysioc_sem); +- break; +- +- default: +- /* Cannot translate event */ +- break; +- } +- +- if (cmd) { +- if (cmd == SIOCGIWSCAN) +- wireless_send_event(dev, cmd, &wrqu, NULL); +- else +- wireless_send_event(dev, cmd, &wrqu, extra); +- } +- +-#if WIRELESS_EXT > 14 +- /* Look for WLC events that indicate a connection failure. +- * If found, generate an IWEVCUSTOM event. +- */ +- memset(extra, 0, sizeof(extra)); +- if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) { +- cmd = IWEVCUSTOM; +- wrqu.data.length = strlen(extra); +- wireless_send_event(dev, cmd, &wrqu, extra); +- } +-#endif /* WIRELESS_EXT > 14 */ +- +-#endif /* WIRELESS_EXT > 13 */ +-} +- +-int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats) +-{ +- int res = 0; +- wl_cnt_t cnt; +- int phy_noise; +- int rssi; +- scb_val_t scb_val; +- +- phy_noise = 0; +- if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise)))) +- goto done; +- +- phy_noise = dtoh32(phy_noise); +- WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise)); +- +- scb_val.val = 0; +- if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) +- goto done; +- +- rssi = dtoh32(scb_val.val); +- WL_TRACE(("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi)); +- if (rssi <= WL_IW_RSSI_NO_SIGNAL) +- wstats->qual.qual = 0; +- else if (rssi <= WL_IW_RSSI_VERY_LOW) +- wstats->qual.qual = 1; +- else if (rssi <= WL_IW_RSSI_LOW) +- wstats->qual.qual = 2; +- else if (rssi <= WL_IW_RSSI_GOOD) +- wstats->qual.qual = 3; +- else if (rssi <= WL_IW_RSSI_VERY_GOOD) +- wstats->qual.qual = 4; +- else +- wstats->qual.qual = 5; +- +- /* Wraps to 0 if RSSI is 0 */ +- wstats->qual.level = 0x100 + rssi; +- wstats->qual.noise = 0x100 + phy_noise; +-#if WIRELESS_EXT > 18 +- wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM); +-#else +- wstats->qual.updated |= 7; +-#endif /* WIRELESS_EXT > 18 */ +- +-#if WIRELESS_EXT > 11 +- WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n *****", (int)sizeof(wl_cnt_t))); +- +- memset(&cnt, 0, sizeof(wl_cnt_t)); +- res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t)); +- if (res) +- { +- WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res)); +- goto done; +- } +- +- cnt.version = dtoh16(cnt.version); +- if (cnt.version != WL_CNT_T_VERSION) { +- WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n", +- WL_CNT_T_VERSION, cnt.version)); +- goto done; +- } +- +- wstats->discard.nwid = 0; +- wstats->discard.code = dtoh32(cnt.rxundec); +- wstats->discard.fragment = dtoh32(cnt.rxfragerr); +- wstats->discard.retries = dtoh32(cnt.txfail); +- wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant); +- wstats->miss.beacon = 0; +- +- WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n", +- dtoh32(cnt.txframe), dtoh32(cnt.txbyte))); +- WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong))); +- WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp))); +- WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec))); +- WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr))); +- WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail))); +- WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt))); +- WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant))); +- +-#endif /* WIRELESS_EXT > 11 */ +- +-done: +- return res; +-} +- +-static void +-wl_iw_timerfunc(ulong data) +-{ +- iscan_info_t *iscan = (iscan_info_t *)data; +- iscan->timer_on = 0; +- if (iscan->iscan_state != ISCAN_STATE_IDLE) { +- WL_TRACE(("timer trigger\n")); +- up(&iscan->sysioc_sem); +- } +-} +- +-static void +-wl_iw_set_event_mask(struct net_device *dev) +-{ +- char eventmask[WL_EVENTING_MASK_LEN]; +- char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ +- +- dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf)); +- bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN); +- setbit(eventmask, WLC_E_SCAN_COMPLETE); +- dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, +- iovbuf, sizeof(iovbuf)); +- +-} +- +-static int +-wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid) +-{ +- int err = 0; +- +- memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); +- params->bss_type = DOT11_BSSTYPE_ANY; +- params->scan_type = 0; +- params->nprobes = -1; +- params->active_time = -1; +- params->passive_time = -1; +- params->home_time = -1; +- params->channel_num = 0; +- +- params->nprobes = htod32(params->nprobes); +- params->active_time = htod32(params->active_time); +- params->passive_time = htod32(params->passive_time); +- params->home_time = htod32(params->home_time); +- if (ssid && ssid->SSID_len) +- memcpy(¶ms->ssid, ssid, sizeof(wlc_ssid_t)); +- +- return err; +-} +- +-static int +-wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action) +-{ +- int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)); +- wl_iscan_params_t *params; +- int err = 0; +- +- if (ssid && ssid->SSID_len) { +- params_size += sizeof(wlc_ssid_t); +- } +- params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL); +- if (params == NULL) { +- return -ENOMEM; +- } +- memset(params, 0, params_size); +- DHD_WARN(params_size < WLC_IOCTL_SMLEN, kfree(params);return BCME_ERROR;); +- +- err = wl_iw_iscan_prep(¶ms->params, ssid); +- +- if (!err) { +- params->version = htod32(ISCAN_REQ_VERSION); +- params->action = htod16(action); +- params->scan_duration = htod16(0); +- +- /* params_size += OFFSETOF(wl_iscan_params_t, params); */ +- (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size, +- iscan->ioctlbuf, WLC_IOCTL_SMLEN); +- } +- +- kfree(params); +- return err; +-} +- +-static uint32 +-wl_iw_iscan_get(iscan_info_t *iscan) +-{ +- iscan_buf_t * buf; +- iscan_buf_t * ptr; +- wl_iscan_results_t * list_buf; +- wl_iscan_results_t list; +- wl_scan_results_t *results; +- uint32 status; +- +- /* buffers are allocated on demand */ +- if (iscan->list_cur) { +- buf = iscan->list_cur; +- iscan->list_cur = buf->next; +- } +- else { +- buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL); +- if (!buf) +- return WL_SCAN_RESULTS_ABORTED; +- buf->next = NULL; +- if (!iscan->list_hdr) +- iscan->list_hdr = buf; +- else { +- ptr = iscan->list_hdr; +- while (ptr->next) { +- ptr = ptr->next; +- } +- ptr->next = buf; +- } +- } +- memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN); +- list_buf = (wl_iscan_results_t*)buf->iscan_buf; +- results = &list_buf->results; +- results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; +- results->version = 0; +- results->count = 0; +- +- memset(&list, 0, sizeof(list)); +- list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN); +- (void) dev_iw_iovar_getbuf( +- iscan->dev, +- "iscanresults", +- &list, +- WL_ISCAN_RESULTS_FIXED_SIZE, +- buf->iscan_buf, +- WLC_IW_ISCAN_MAXLEN); +- results->buflen = dtoh32(results->buflen); +- results->version = dtoh32(results->version); +- results->count = dtoh32(results->count); +- WL_TRACE(("results->count = %d\n", results->count)); +- +- WL_TRACE(("results->buflen = %d\n", results->buflen)); +- status = dtoh32(list_buf->status); +- return status; +-} +- +-static void wl_iw_send_scan_complete(iscan_info_t *iscan) +-{ +- union iwreq_data wrqu; +- +- memset(&wrqu, 0, sizeof(wrqu)); +- +- /* wext expects to get no data for SIOCGIWSCAN Event */ +- wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL); +-} +- +-static int +-_iscan_sysioc_thread(void *data) +-{ +- uint32 status; +- iscan_info_t *iscan = (iscan_info_t *)data; +- +- DAEMONIZE("iscan_sysioc"); +- +- status = WL_SCAN_RESULTS_PARTIAL; +- while (down_interruptible(&iscan->sysioc_sem) == 0) { +- if (iscan->timer_on) { +- del_timer(&iscan->timer); +- iscan->timer_on = 0; +- } +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +- rtnl_lock(); +-#endif +- status = wl_iw_iscan_get(iscan); +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +- rtnl_unlock(); +-#endif +- +- switch (status) { +- case WL_SCAN_RESULTS_PARTIAL: +- WL_TRACE(("iscanresults incomplete\n")); +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +- rtnl_lock(); +-#endif +- /* make sure our buffer size is enough before going next round */ +- wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +- rtnl_unlock(); +-#endif +- /* Reschedule the timer */ +- iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); +- add_timer(&iscan->timer); +- iscan->timer_on = 1; +- break; +- case WL_SCAN_RESULTS_SUCCESS: +- WL_TRACE(("iscanresults complete\n")); +- iscan->iscan_state = ISCAN_STATE_IDLE; +- wl_iw_send_scan_complete(iscan); +- break; +- case WL_SCAN_RESULTS_PENDING: +- WL_TRACE(("iscanresults pending\n")); +- /* Reschedule the timer */ +- iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); +- add_timer(&iscan->timer); +- iscan->timer_on = 1; +- break; +- case WL_SCAN_RESULTS_ABORTED: +- WL_TRACE(("iscanresults aborted\n")); +- iscan->iscan_state = ISCAN_STATE_IDLE; +- wl_iw_send_scan_complete(iscan); +- break; +- default: +- WL_TRACE(("iscanresults returned unknown status %d\n", status)); +- break; +- } +- } +- complete_and_exit(&iscan->sysioc_exited, 0); +-} +- +-int +-wl_iw_attach(struct net_device *dev, void * dhdp) +-{ +- iscan_info_t *iscan = NULL; +- +- if (!dev) +- return 0; +- +- iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL); +- if (!iscan) +- return -ENOMEM; +- memset(iscan, 0, sizeof(iscan_info_t)); +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +- iscan->kthread = NULL; +-#endif +- iscan->sysioc_pid = -1; +- /* we only care about main interface so save a global here */ +- g_iscan = iscan; +- iscan->dev = dev; +- iscan->iscan_state = ISCAN_STATE_IDLE; +- +- +- /* Set up the timer */ +- iscan->timer_ms = 2000; +- init_timer(&iscan->timer); +- iscan->timer.data = (ulong)iscan; +- iscan->timer.function = wl_iw_timerfunc; +- +- sema_init(&iscan->sysioc_sem, 0); +- init_completion(&iscan->sysioc_exited); +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +- iscan->kthread = kthread_run(_iscan_sysioc_thread, iscan, "iscan_sysioc"); +- iscan->sysioc_pid = iscan->kthread->pid; +-#else +- iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0); +-#endif +- if (iscan->sysioc_pid < 0) +- return -ENOMEM; +- return 0; +-} +- +-void wl_iw_detach(void) +-{ +- iscan_buf_t *buf; +- iscan_info_t *iscan = g_iscan; +- if (!iscan) +- return; +- if (iscan->sysioc_pid >= 0) { +- KILL_PROC(iscan->sysioc_pid, SIGTERM); +- wait_for_completion(&iscan->sysioc_exited); +- } +- +- while (iscan->list_hdr) { +- buf = iscan->list_hdr->next; +- kfree(iscan->list_hdr); +- iscan->list_hdr = buf; +- } +- kfree(iscan); +- g_iscan = NULL; +-} +- +-#endif /* USE_IW */ +diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h +deleted file mode 100644 +index 95b2abdbd7c58..0000000000000 +--- a/drivers/net/wireless/bcmdhd/wl_iw.h ++++ /dev/null +@@ -1,161 +0,0 @@ +-/* +- * Linux Wireless Extensions support +- * +- * Copyright (C) 1999-2014, Broadcom Corporation +- * +- * Unless you and Broadcom execute a separate written software license +- * agreement governing use of this software, this software is licensed to you +- * under the terms of the GNU General Public License version 2 (the "GPL"), +- * available at http://www.broadcom.com/licenses/GPLv2.php, with the +- * following added to such license: +- * +- * As a special exception, the copyright holders of this software give you +- * permission to link this software with independent modules, and to copy and +- * distribute the resulting executable under terms of your choice, provided that +- * you also meet, for each linked independent module, the terms and conditions of +- * the license of that module. An independent module is a module which is not +- * derived from this software. The special exception does not apply to any +- * modifications of the software. +- * +- * Notwithstanding the above, under no circumstances may you combine this +- * software in any way with any other Broadcom software provided under a license +- * other than the GPL, without Broadcom's express prior written consent. +- * +- * $Id: wl_iw.h 467328 2014-04-03 01:23:40Z $ +- */ +- +-#ifndef _wl_iw_h_ +-#define _wl_iw_h_ +- +-#include +- +-#include +-#include +-#include +- +-#define WL_SCAN_PARAMS_SSID_MAX 10 +-#define GET_SSID "SSID=" +-#define GET_CHANNEL "CH=" +-#define GET_NPROBE "NPROBE=" +-#define GET_ACTIVE_ASSOC_DWELL "ACTIVE=" +-#define GET_PASSIVE_ASSOC_DWELL "PASSIVE=" +-#define GET_HOME_DWELL "HOME=" +-#define GET_SCAN_TYPE "TYPE=" +- +-#define BAND_GET_CMD "GETBAND" +-#define BAND_SET_CMD "SETBAND" +-#define DTIM_SKIP_GET_CMD "DTIMSKIPGET" +-#define DTIM_SKIP_SET_CMD "DTIMSKIPSET" +-#define SETSUSPEND_CMD "SETSUSPENDOPT" +-#define PNOSSIDCLR_SET_CMD "PNOSSIDCLR" +-/* Lin - Is the extra space needed? */ +-#define PNOSETUP_SET_CMD "PNOSETUP " /* TLV command has extra end space */ +-#define PNOENABLE_SET_CMD "PNOFORCE" +-#define PNODEBUG_SET_CMD "PNODEBUG" +-#define TXPOWER_SET_CMD "TXPOWER" +- +-#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +-#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +- +-/* Structure to keep global parameters */ +-typedef struct wl_iw_extra_params { +- int target_channel; /* target channel */ +-} wl_iw_extra_params_t; +- +-struct cntry_locales_custom { +- char iso_abbrev[WLC_CNTRY_BUF_SZ]; /* ISO 3166-1 country abbreviation */ +- char custom_locale[WLC_CNTRY_BUF_SZ]; /* Custom firmware locale */ +- int32 custom_locale_rev; /* Custom local revisin default -1 */ +-}; +-/* ============================================== */ +-/* Defines from wlc_pub.h */ +-#define WL_IW_RSSI_MINVAL -200 /* Low value, e.g. for forcing roam */ +-#define WL_IW_RSSI_NO_SIGNAL -91 /* NDIS RSSI link quality cutoffs */ +-#define WL_IW_RSSI_VERY_LOW -80 /* Very low quality cutoffs */ +-#define WL_IW_RSSI_LOW -70 /* Low quality cutoffs */ +-#define WL_IW_RSSI_GOOD -68 /* Good quality cutoffs */ +-#define WL_IW_RSSI_VERY_GOOD -58 /* Very good quality cutoffs */ +-#define WL_IW_RSSI_EXCELLENT -57 /* Excellent quality cutoffs */ +-#define WL_IW_RSSI_INVALID 0 /* invalid RSSI value */ +-#define MAX_WX_STRING 80 +-#define SSID_FMT_BUF_LEN ((4 * 32) + 1) +-#define isprint(c) bcm_isprint(c) +-#define WL_IW_SET_ACTIVE_SCAN (SIOCIWFIRSTPRIV+1) +-#define WL_IW_GET_RSSI (SIOCIWFIRSTPRIV+3) +-#define WL_IW_SET_PASSIVE_SCAN (SIOCIWFIRSTPRIV+5) +-#define WL_IW_GET_LINK_SPEED (SIOCIWFIRSTPRIV+7) +-#define WL_IW_GET_CURR_MACADDR (SIOCIWFIRSTPRIV+9) +-#define WL_IW_SET_STOP (SIOCIWFIRSTPRIV+11) +-#define WL_IW_SET_START (SIOCIWFIRSTPRIV+13) +- +-#define G_SCAN_RESULTS 8*1024 +-#define WE_ADD_EVENT_FIX 0x80 +-#define G_WLAN_SET_ON 0 +-#define G_WLAN_SET_OFF 1 +- +- +-typedef struct wl_iw { +- char nickname[IW_ESSID_MAX_SIZE]; +- +- struct iw_statistics wstats; +- +- int spy_num; +- uint32 pwsec; /* pairwise wsec setting */ +- uint32 gwsec; /* group wsec setting */ +- bool privacy_invoked; /* IW_AUTH_PRIVACY_INVOKED setting */ +- struct ether_addr spy_addr[IW_MAX_SPY]; +- struct iw_quality spy_qual[IW_MAX_SPY]; +- void *wlinfo; +-} wl_iw_t; +- +-struct wl_ctrl { +- struct timer_list *timer; +- struct net_device *dev; +- long sysioc_pid; +- struct semaphore sysioc_sem; +- struct completion sysioc_exited; +-}; +- +- +-#if WIRELESS_EXT > 12 +-#include +-extern const struct iw_handler_def wl_iw_handler_def; +-#endif /* WIRELESS_EXT > 12 */ +- +-extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +-extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data); +-extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats); +-int wl_iw_attach(struct net_device *dev, void * dhdp); +-int wl_iw_send_priv_event(struct net_device *dev, char *flag); +- +-void wl_iw_detach(void); +- +-#define CSCAN_COMMAND "CSCAN " +-#define CSCAN_TLV_PREFIX 'S' +-#define CSCAN_TLV_VERSION 1 +-#define CSCAN_TLV_SUBVERSION 0 +-#define CSCAN_TLV_TYPE_SSID_IE 'S' +-#define CSCAN_TLV_TYPE_CHANNEL_IE 'C' +-#define CSCAN_TLV_TYPE_NPROBE_IE 'N' +-#define CSCAN_TLV_TYPE_ACTIVE_IE 'A' +-#define CSCAN_TLV_TYPE_PASSIVE_IE 'P' +-#define CSCAN_TLV_TYPE_HOME_IE 'H' +-#define CSCAN_TLV_TYPE_STYPE_IE 'T' +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) +-#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \ +- iwe_stream_add_event(info, stream, ends, iwe, extra) +-#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \ +- iwe_stream_add_value(info, event, value, ends, iwe, event_len) +-#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \ +- iwe_stream_add_point(info, stream, ends, iwe, extra) +-#else +-#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \ +- iwe_stream_add_event(stream, ends, iwe, extra) +-#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \ +- iwe_stream_add_value(event, value, ends, iwe, event_len) +-#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \ +- iwe_stream_add_point(stream, ends, iwe, extra) +-#endif +- +-#endif /* _wl_iw_h_ */ diff --git a/Patches/Linux_CVEs/CVE-2017-0510/0.patch b/Patches/Linux_CVEs/CVE-2017-0510/0.patch new file mode 100644 index 00000000..9ae4f425 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0510/0.patch @@ -0,0 +1,206 @@ +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 + diff --git a/Patches/Linux_CVEs/CVE-2017-0510/1.patch b/Patches/Linux_CVEs/CVE-2017-0510/1.patch new file mode 100644 index 00000000..423f121c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0510/1.patch @@ -0,0 +1,206 @@ +From 7a4fd6fb0df85d16db29561e0063b41a62f11e4d 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 52f6816..0abced1 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 (kstrtoul(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 d0c19b1..2ecb363 100644 +--- a/drivers/tty/sysrq.c ++++ b/drivers/tty/sysrq.c +@@ -58,10 +58,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 387fa7d..d802692 100644 +--- a/include/linux/sysrq.h ++++ b/include/linux/sysrq.h +@@ -42,6 +42,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 + diff --git a/Patches/Linux_CVEs/CVE-2017-0516/0.patch b/Patches/Linux_CVEs/CVE-2017-0516/0.patch new file mode 100644 index 00000000..0c26e111 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0516/0.patch @@ -0,0 +1,37 @@ +From 1e2b69bf3ab61979a05e796e76c8ecd1ec251c42 Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Thu, 5 Jan 2017 17:22:13 -0800 +Subject: [PATCH] input: misc: fix heap overflow issue in hbtp_input.c + +Add the boundary check for ABS code before setting ABS params, +to avoid heap overflow. + +Bug: 32341680 +CRs-fixed: 1096301 +Change-Id: I6aad9916c92d2f775632406374dbb803063148de +Signed-off-by: Vevek Venkatesan +Signed-off-by: Dennis Cagle +--- + drivers/input/misc/hbtp_input.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c +index ef17d386644c9..7877e9b9f5162 100644 +--- a/drivers/input/misc/hbtp_input.c ++++ b/drivers/input/misc/hbtp_input.c +@@ -129,9 +129,13 @@ static int hbtp_input_create_input_dev(struct hbtp_input_absinfo *absinfo) + input_mt_init_slots(input_dev, HBTP_MAX_FINGER, 0); + for (i = 0; i <= ABS_MT_LAST - ABS_MT_FIRST; i++) { + abs = absinfo + i; +- if (abs->active) +- input_set_abs_params(input_dev, abs->code, ++ if (abs->active) { ++ if (abs->code >= 0 && abs->code < ABS_CNT) ++ input_set_abs_params(input_dev, abs->code, + abs->minimum, abs->maximum, 0, 0); ++ else ++ pr_err("%s: ABS code out of bound\n", __func__); ++ } + } + + error = input_register_device(input_dev); diff --git a/Patches/Linux_CVEs/CVE-2017-0518/0.patch b/Patches/Linux_CVEs/CVE-2017-0518/0.patch new file mode 100644 index 00000000..3af62a34 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0518/0.patch @@ -0,0 +1,39 @@ +From 015d1d5dc8c42d6ab92a31b99cd9f089fae1d27e Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Fri, 6 Jan 2017 15:50:35 -0800 +Subject: [PATCH] QBT1000: check for null pointer before copying command + +A null command buffer will cause a null pointer crash. +Check for it. + +Bug: 32372915 +Bug: 32370896 +CRs-fixed: 1041652, 1081802 +Change-Id: I37a0c8b9fe2c144fb4e75036509bf7ec07604ea7 +Signed-off-by: Lior Barenboim +Signed-off-by: Dennis Cagle +--- + drivers/soc/qcom/qbt1000.c | 7 +++++++ + 1 file changed, 7 insertions(+) + mode change 100644 => 100755 drivers/soc/qcom/qbt1000.c + +diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c +old mode 100644 +new mode 100755 +index 135e2b834db30..101fcedd1f2c0 +--- a/drivers/soc/qcom/qbt1000.c ++++ b/drivers/soc/qcom/qbt1000.c +@@ -862,6 +862,13 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + if (rc != 0) + goto end; + ++ if (!aligned_cmd) { ++ dev_err(drvdata->dev, "%s: Null command buffer\n", ++ __func__); ++ rc = -EINVAL; ++ goto end; ++ } ++ + rc = copy_from_user(aligned_cmd, (void __user *)tzcmd.req_buf, + tzcmd.req_buf_len); + if (rc != 0) { diff --git a/Patches/Linux_CVEs/CVE-2017-0518/1.patch b/Patches/Linux_CVEs/CVE-2017-0518/1.patch new file mode 100644 index 00000000..8c22345b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0518/1.patch @@ -0,0 +1,138 @@ +From a064a44e03158dbf655a866ba21f5d1baa2dee9e Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Fri, 6 Jan 2017 15:28:20 -0800 +Subject: [PATCH] QBT1000: copy qseecom handle to user when loading/unloading + app + +QBT1000 provides IOCTLs for loading and unloading a QSEE app. +In the input structure for these IOCTLs there is a pointer +to a qseecom handle which serves as an output parameter for +the IOCTLs. That is, the given handle (in client address space) +should be set to a valid handle value on load, and should be set +to 0 on unload. + +The driver was missing a proper copy_to_user() call for this handle, +which sometimes resulted in unload not setting the handle to 0. + +Bug: 32372915 +Bug: 32370896 +CRs-fixed: 1059327 +Change-Id: I31f205afb1f9bf0b6243e3f20f54022525c93b28 +Signed-off-by: Lior Barenboim +Signed-off-by: Dennis Cagle +--- + drivers/soc/qcom/qbt1000.c | 59 ++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 55 insertions(+), 4 deletions(-) + +diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c +index 101fcedd1f2c0..961800e2f963f 100755 +--- a/drivers/soc/qcom/qbt1000.c ++++ b/drivers/soc/qcom/qbt1000.c +@@ -772,6 +772,7 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + case QBT1000_LOAD_APP: + { + struct qbt1000_app app; ++ struct qseecom_handle *app_handle; + + if (copy_from_user(&app, priv_arg, + sizeof(app)) != 0) { +@@ -782,8 +783,15 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + goto end; + } + ++ if (!app.app_handle) { ++ dev_err(drvdata->dev, "%s: LOAD app_handle is null\n", ++ __func__); ++ rc = -EINVAL; ++ goto end; ++ } ++ + /* start the TZ app */ +- rc = qseecom_start_app(app.app_handle, app.name, app.size); ++ rc = qseecom_start_app(&app_handle, app.name, app.size); + if (rc == 0) { + g_app_buf_size = app.size; + } else { +@@ -792,36 +800,79 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + goto end; + } + ++ /* copy the app handle to user */ ++ rc = copy_to_user((void __user *)app.app_handle, &app_handle, ++ sizeof(*app.app_handle)); ++ ++ if (rc != 0) { ++ dev_err(drvdata->dev, ++ "%s: Failed copy 2us LOAD rc:%d\n", ++ __func__, rc); ++ rc = -ENOMEM; ++ goto end; ++ } ++ + break; + } + case QBT1000_UNLOAD_APP: + { + struct qbt1000_app app; ++ struct qseecom_handle *app_handle; + + if (copy_from_user(&app, priv_arg, + sizeof(app)) != 0) { + rc = -ENOMEM; + dev_err(drvdata->dev, +- "%s: Failed copy from user space-LOAD\n", ++ "%s: Failed copy from user space-UNLOAD\n", + __func__); + goto end; + } + +- /* if the app hasn't been loaded already, return err */ + if (!app.app_handle) { ++ dev_err(drvdata->dev, "%s: UNLOAD app_handle is null\n", ++ __func__); ++ rc = -EINVAL; ++ goto end; ++ } ++ ++ rc = copy_from_user(&app_handle, app.app_handle, ++ sizeof(app_handle)); ++ ++ if (rc != 0) { ++ dev_err(drvdata->dev, ++ "%s: Failed copy from user space-UNLOAD handle rc:%d\n", ++ __func__, rc); ++ rc = -ENOMEM; ++ goto end; ++ } ++ ++ /* if the app hasn't been loaded already, return err */ ++ if (!app_handle) { + dev_err(drvdata->dev, "%s: App not loaded\n", + __func__); + rc = -EINVAL; + goto end; + } + +- rc = qseecom_shutdown_app(app.app_handle); ++ rc = qseecom_shutdown_app(&app_handle); + if (rc != 0) { + dev_err(drvdata->dev, "%s: App failed to shutdown\n", + __func__); + goto end; + } + ++ /* copy the app handle (should be null) to user */ ++ rc = copy_to_user((void __user *)app.app_handle, &app_handle, ++ sizeof(*app.app_handle)); ++ ++ if (rc != 0) { ++ dev_err(drvdata->dev, ++ "%s: Failed copy 2us UNLOAD rc:%d\n", ++ __func__, rc); ++ rc = -ENOMEM; ++ goto end; ++ } ++ + break; + } + case QBT1000_SEND_TZCMD: diff --git a/Patches/Linux_CVEs/CVE-2017-0519/0.patch b/Patches/Linux_CVEs/CVE-2017-0519/0.patch new file mode 100644 index 00000000..87beefe6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0519/0.patch @@ -0,0 +1,123 @@ +From 2f264730e26a73da973c6eef0e1ee252294ec740 Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Fri, 6 Jan 2017 15:28:29 -0800 +Subject: [PATCH] soc: qcom: fingerprint: keep QSEE handle in kernel space + +Move the QSEE handle from user space to kernel space. +In addition, fix possible overflow when checking that +the command and response buffers fit in the shared buffer. + +Bug: 32372915 +CRs-fixed: 1086530 +Change-Id: I21b1866546a2825fe348a260c60e341bbe9600ea +Signed-off-by: Lior Barenboim +Signed-off-by: Dennis Cagle +--- + drivers/soc/qcom/qbt1000.c | 31 ++++++++++++++++++++++--------- + 1 file changed, 22 insertions(+), 9 deletions(-) + +diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c +index 961800e2f963f..f76cf0f45ecaa 100755 +--- a/drivers/soc/qcom/qbt1000.c ++++ b/drivers/soc/qcom/qbt1000.c +@@ -86,6 +86,7 @@ struct qbt1000_drvdata { + uint32_t ssc_spi_port; + uint32_t ssc_spi_port_slave_index; + struct wakeup_source w_lock; ++ struct qseecom_handle *app_handle; + }; + #define W_LOCK_DELAY_MS (2000) + +@@ -110,7 +111,7 @@ static int get_cmd_rsp_buffers(struct qseecom_handle *hdl, + *cmd_len = ALIGN(*cmd_len, 64); + *rsp_len = ALIGN(*rsp_len, 64); + +- if ((*rsp_len + *cmd_len) > g_app_buf_size) ++ if (((uint64_t)*rsp_len + (uint64_t)*cmd_len) > (uint64_t)g_app_buf_size) + return -ENOMEM; + + *cmd = hdl->sbuf; +@@ -790,8 +791,19 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + goto end; + } + ++ if (drvdata->app_handle) { ++ dev_err(drvdata->dev, "%s: LOAD app already loaded, unloading first\n", ++ __func__); ++ rc = qseecom_shutdown_app(&drvdata->app_handle); ++ if (rc != 0) { ++ dev_err(drvdata->dev, "%s: LOAD current app failed to shutdown\n", ++ __func__); ++ goto end; ++ } ++ } ++ + /* start the TZ app */ +- rc = qseecom_start_app(&app_handle, app.name, app.size); ++ rc = qseecom_start_app(&drvdata->app_handle, app.name, app.size); + if (rc == 0) { + g_app_buf_size = app.size; + } else { +@@ -800,7 +812,8 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + goto end; + } + +- /* copy the app handle to user */ ++ /* copy a fake app handle to user */ ++ app_handle = drvdata->app_handle ? (struct qseecom_handle *)123456 : 0; + rc = copy_to_user((void __user *)app.app_handle, &app_handle, + sizeof(*app.app_handle)); + +@@ -817,7 +830,7 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + case QBT1000_UNLOAD_APP: + { + struct qbt1000_app app; +- struct qseecom_handle *app_handle; ++ struct qseecom_handle *app_handle = 0; + + if (copy_from_user(&app, priv_arg, + sizeof(app)) != 0) { +@@ -847,14 +860,14 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + } + + /* if the app hasn't been loaded already, return err */ +- if (!app_handle) { ++ if (!drvdata->app_handle) { + dev_err(drvdata->dev, "%s: App not loaded\n", + __func__); + rc = -EINVAL; + goto end; + } + +- rc = qseecom_shutdown_app(&app_handle); ++ rc = qseecom_shutdown_app(&drvdata->app_handle); + if (rc != 0) { + dev_err(drvdata->dev, "%s: App failed to shutdown\n", + __func__); +@@ -895,7 +908,7 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + } + + /* if the app hasn't been loaded already, return err */ +- if (!tzcmd.app_handle) { ++ if (!drvdata->app_handle) { + dev_err(drvdata->dev, "%s: App not loaded\n", + __func__); + rc = -EINVAL; +@@ -905,7 +918,7 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + /* init command and response buffers and align lengths */ + aligned_cmd_len = tzcmd.req_buf_len; + aligned_rsp_len = tzcmd.rsp_buf_len; +- rc = get_cmd_rsp_buffers(tzcmd.app_handle, ++ rc = get_cmd_rsp_buffers(drvdata->app_handle, + (void **)&aligned_cmd, + &aligned_cmd_len, + (void **)&aligned_rsp, +@@ -930,7 +943,7 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + } + + /* send cmd to TZ */ +- rc = qseecom_send_command(tzcmd.app_handle, ++ rc = qseecom_send_command(drvdata->app_handle, + aligned_cmd, + aligned_cmd_len, + aligned_rsp, diff --git a/Patches/Linux_CVEs/CVE-2017-0520/0.patch b/Patches/Linux_CVEs/CVE-2017-0520/0.patch new file mode 100644 index 00000000..9ab0b23b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0520/0.patch @@ -0,0 +1,304 @@ +From eb2aad752c43f57e88ab9b0c3c5ee7b976ee31dd Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Mon, 31 Oct 2016 15:23:19 -0700 +Subject: msm: crypto: fix issues on digest buf and copy_from_user in qcedev.c + +Make the digest length not larger than the size of the buffer +qcedev_areq.sha_op_req.digest; and use the checked variants of +the copy_from/to_user() APIs to avoid small race window of their +unchecked variants. + +Change-Id: I3db0c20ac5fa47ed278f3d60368c406f472430c1 +Signed-off-by: Zhen Kong +--- + drivers/crypto/msm/qcedev.c | 120 ++++++++++---------------------------------- + 1 file changed, 27 insertions(+), 93 deletions(-) + +diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c +index 1402d3d..433e478 100644 +--- a/drivers/crypto/msm/qcedev.c ++++ b/drivers/crypto/msm/qcedev.c +@@ -603,7 +603,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq, + while (len > 0) { + user_src = + (void __user *)qcedev_areq->sha_op_req.data[i].vaddr; +- if (user_src && __copy_from_user(k_src, ++ if (user_src && copy_from_user(k_src, + (void __user *)user_src, + qcedev_areq->sha_op_req.data[i].len)) + return -EFAULT; +@@ -639,7 +639,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq, + + /* Copy data from user src(s) */ + user_src = (void __user *)qcedev_areq->sha_op_req.data[0].vaddr; +- if (user_src && __copy_from_user(k_src, ++ if (user_src && copy_from_user(k_src, + (void __user *)user_src, + qcedev_areq->sha_op_req.data[0].len)) { + kzfree(k_buf_src); +@@ -648,7 +648,7 @@ static int qcedev_sha_update_max_xfer(struct qcedev_async_req *qcedev_areq, + k_src += qcedev_areq->sha_op_req.data[0].len; + for (i = 1; i < qcedev_areq->sha_op_req.entries; i++) { + user_src = (void __user *)qcedev_areq->sha_op_req.data[i].vaddr; +- if (user_src && __copy_from_user(k_src, ++ if (user_src && copy_from_user(k_src, + (void __user *)user_src, + qcedev_areq->sha_op_req.data[i].len)) { + kzfree(k_buf_src); +@@ -702,13 +702,6 @@ static int qcedev_sha_update(struct qcedev_async_req *qcedev_areq, + return -EINVAL; + } + +- /* verify address src(s) */ +- for (i = 0; i < qcedev_areq->sha_op_req.entries; i++) +- if (!access_ok(VERIFY_READ, +- (void __user *)qcedev_areq->sha_op_req.data[i].vaddr, +- qcedev_areq->sha_op_req.data[i].len)) +- return -EFAULT; +- + if (qcedev_areq->sha_op_req.data_len > QCE_MAX_OPER_DATA) { + + struct qcedev_sha_op_req *saved_req; +@@ -868,19 +861,7 @@ static int qcedev_hash_cmac(struct qcedev_async_req *qcedev_areq, + + total = qcedev_areq->sha_op_req.data_len; + +- /* verify address src(s) */ +- for (i = 0; i < qcedev_areq->sha_op_req.entries; i++) +- if (!access_ok(VERIFY_READ, +- (void __user *)qcedev_areq->sha_op_req.data[i].vaddr, +- qcedev_areq->sha_op_req.data[i].len)) +- return -EFAULT; +- +- /* Verify Source Address */ +- if (!access_ok(VERIFY_READ, +- (void __user *)qcedev_areq->sha_op_req.authkey, +- qcedev_areq->sha_op_req.authklen)) +- return -EFAULT; +- if (__copy_from_user(&handle->sha_ctxt.authkey[0], ++ if (copy_from_user(&handle->sha_ctxt.authkey[0], + (void __user *)qcedev_areq->sha_op_req.authkey, + qcedev_areq->sha_op_req.authklen)) + return -EFAULT; +@@ -900,7 +881,7 @@ static int qcedev_hash_cmac(struct qcedev_async_req *qcedev_areq, + for (i = 0; i < qcedev_areq->sha_op_req.entries; i++) { + user_src = + (void __user *)qcedev_areq->sha_op_req.data[i].vaddr; +- if (user_src && __copy_from_user(k_src, (void __user *)user_src, ++ if (user_src && copy_from_user(k_src, (void __user *)user_src, + qcedev_areq->sha_op_req.data[i].len)) { + kzfree(k_buf_src); + return -EFAULT; +@@ -928,12 +909,7 @@ static int qcedev_set_hmac_auth_key(struct qcedev_async_req *areq, + + if (areq->sha_op_req.authklen <= QCEDEV_MAX_KEY_SIZE) { + qcedev_sha_init(areq, handle); +- /* Verify Source Address */ +- if (!access_ok(VERIFY_READ, +- (void __user *)areq->sha_op_req.authkey, +- areq->sha_op_req.authklen)) +- return -EFAULT; +- if (__copy_from_user(&handle->sha_ctxt.authkey[0], ++ if (copy_from_user(&handle->sha_ctxt.authkey[0], + (void __user *)areq->sha_op_req.authkey, + areq->sha_op_req.authklen)) + return -EFAULT; +@@ -1146,7 +1122,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq, + byteoffset = areq->cipher_op_req.byteoffset; + + user_src = (void __user *)areq->cipher_op_req.vbuf.src[0].vaddr; +- if (user_src && __copy_from_user((k_align_src + byteoffset), ++ if (user_src && copy_from_user((k_align_src + byteoffset), + (void __user *)user_src, + areq->cipher_op_req.vbuf.src[0].len)) + return -EFAULT; +@@ -1156,7 +1132,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq, + for (i = 1; i < areq->cipher_op_req.entries; i++) { + user_src = + (void __user *)areq->cipher_op_req.vbuf.src[i].vaddr; +- if (user_src && __copy_from_user(k_align_src, ++ if (user_src && copy_from_user(k_align_src, + (void __user *)user_src, + areq->cipher_op_req.vbuf.src[i].len)) { + return -EFAULT; +@@ -1188,7 +1164,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq, + + while (creq->data_len > 0) { + if (creq->vbuf.dst[dst_i].len <= creq->data_len) { +- if (err == 0 && __copy_to_user( ++ if (err == 0 && copy_to_user( + (void __user *)creq->vbuf.dst[dst_i].vaddr, + (k_align_dst + byteoffset), + creq->vbuf.dst[dst_i].len)) +@@ -1199,7 +1175,7 @@ static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq, + creq->data_len -= creq->vbuf.dst[dst_i].len; + dst_i++; + } else { +- if (err == 0 && __copy_to_user( ++ if (err == 0 && copy_to_user( + (void __user *)creq->vbuf.dst[dst_i].vaddr, + (k_align_dst + byteoffset), + creq->data_len)) +@@ -1531,36 +1507,6 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, + __func__, total, req->data_len); + goto error; + } +- /* Verify Source Address's */ +- for (i = 0, total = 0; i < req->entries; i++) { +- if (total < req->data_len) { +- if (!access_ok(VERIFY_READ, +- (void __user *)req->vbuf.src[i].vaddr, +- req->vbuf.src[i].len)) { +- pr_err("%s:SRC RD_VERIFY err %d=0x%lx\n", +- __func__, i, (uintptr_t) +- req->vbuf.src[i].vaddr); +- goto error; +- } +- total += req->vbuf.src[i].len; +- } +- } +- +- /* Verify Destination Address's */ +- for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) { +- if ((req->vbuf.dst[i].vaddr != 0) && +- (total < req->data_len)) { +- if (!access_ok(VERIFY_WRITE, +- (void __user *)req->vbuf.dst[i].vaddr, +- req->vbuf.dst[i].len)) { +- pr_err("%s:DST WR_VERIFY err %d=0x%lx\n", +- __func__, i, (uintptr_t) +- req->vbuf.dst[i].vaddr); +- goto error; +- } +- total += req->vbuf.dst[i].len; +- } +- } + return 0; + error: + return -EINVAL; +@@ -1656,11 +1602,7 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + switch (cmd) { + case QCEDEV_IOCTL_ENC_REQ: + case QCEDEV_IOCTL_DEC_REQ: +- if (!access_ok(VERIFY_WRITE, (void __user *)arg, +- sizeof(struct qcedev_cipher_op_req))) +- return -EFAULT; +- +- if (__copy_from_user(&qcedev_areq.cipher_op_req, ++ if (copy_from_user(&qcedev_areq.cipher_op_req, + (void __user *)arg, + sizeof(struct qcedev_cipher_op_req))) + return -EFAULT; +@@ -1673,20 +1615,17 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle); + if (err) + return err; +- if (__copy_to_user((void __user *)arg, ++ if (copy_to_user((void __user *)arg, + &qcedev_areq.cipher_op_req, + sizeof(struct qcedev_cipher_op_req))) +- return -EFAULT; ++ return -EFAULT; + break; + + case QCEDEV_IOCTL_SHA_INIT_REQ: + { + struct scatterlist sg_src; +- if (!access_ok(VERIFY_WRITE, (void __user *)arg, +- sizeof(struct qcedev_sha_op_req))) +- return -EFAULT; + +- if (__copy_from_user(&qcedev_areq.sha_op_req, ++ if (copy_from_user(&qcedev_areq.sha_op_req, + (void __user *)arg, + sizeof(struct qcedev_sha_op_req))) + return -EFAULT; +@@ -1696,9 +1635,9 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + err = qcedev_hash_init(&qcedev_areq, handle, &sg_src); + if (err) + return err; +- if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, ++ if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, + sizeof(struct qcedev_sha_op_req))) +- return -EFAULT; ++ return -EFAULT; + } + handle->sha_ctxt.init_done = true; + break; +@@ -1708,11 +1647,8 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + case QCEDEV_IOCTL_SHA_UPDATE_REQ: + { + struct scatterlist sg_src; +- if (!access_ok(VERIFY_WRITE, (void __user *)arg, +- sizeof(struct qcedev_sha_op_req))) +- return -EFAULT; + +- if (__copy_from_user(&qcedev_areq.sha_op_req, ++ if (copy_from_user(&qcedev_areq.sha_op_req, + (void __user *)arg, + sizeof(struct qcedev_sha_op_req))) + return -EFAULT; +@@ -1734,10 +1670,15 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + return err; + } + ++ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) { ++ pr_err("Invalid sha_ctxt.diglen %d\n", ++ handle->sha_ctxt.diglen); ++ return -EINVAL; ++ } + memcpy(&qcedev_areq.sha_op_req.digest[0], + &handle->sha_ctxt.digest[0], + handle->sha_ctxt.diglen); +- if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, ++ if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, + sizeof(struct qcedev_sha_op_req))) + return -EFAULT; + } +@@ -1749,11 +1690,7 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + pr_err("%s Init was not called\n", __func__); + return -EINVAL; + } +- if (!access_ok(VERIFY_WRITE, (void __user *)arg, +- sizeof(struct qcedev_sha_op_req))) +- return -EFAULT; +- +- if (__copy_from_user(&qcedev_areq.sha_op_req, ++ if (copy_from_user(&qcedev_areq.sha_op_req, + (void __user *)arg, + sizeof(struct qcedev_sha_op_req))) + return -EFAULT; +@@ -1767,7 +1704,7 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + memcpy(&qcedev_areq.sha_op_req.digest[0], + &handle->sha_ctxt.digest[0], + handle->sha_ctxt.diglen); +- if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, ++ if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, + sizeof(struct qcedev_sha_op_req))) + return -EFAULT; + handle->sha_ctxt.init_done = false; +@@ -1776,11 +1713,8 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + case QCEDEV_IOCTL_GET_SHA_REQ: + { + struct scatterlist sg_src; +- if (!access_ok(VERIFY_WRITE, (void __user *)arg, +- sizeof(struct qcedev_sha_op_req))) +- return -EFAULT; + +- if (__copy_from_user(&qcedev_areq.sha_op_req, ++ if (copy_from_user(&qcedev_areq.sha_op_req, + (void __user *)arg, + sizeof(struct qcedev_sha_op_req))) + return -EFAULT; +@@ -1798,7 +1732,7 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + memcpy(&qcedev_areq.sha_op_req.digest[0], + &handle->sha_ctxt.digest[0], + handle->sha_ctxt.diglen); +- if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, ++ if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req, + sizeof(struct qcedev_sha_op_req))) + return -EFAULT; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0521/0.patch b/Patches/Linux_CVEs/CVE-2017-0521/0.patch new file mode 100644 index 00000000..21f4cc92 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0521/0.patch @@ -0,0 +1,46 @@ +From dbe4f26f200db10deaf38676b96d8738afcc10c8 Mon Sep 17 00:00:00 2001 +From: Kumar Behera +Date: Fri, 9 Dec 2016 09:55:00 -0800 +Subject: msm: cpp: Fix for integer overflow in cpp + +Due to integer overflow ,the bound check in config frame function +may pass and this may allow user to access invalid buffer. This +fix takes care of proper bound and don't allow integer overflow. + +CRs-Fxied: 1097709 +Change-Id: I504ad591633afaba82268b5ee27a321691d75c80 +Signed-off-by: Kumar Behera +--- + drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +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 f64f79b..e81a9f9 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 +@@ -2376,7 +2376,7 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + struct msm_buf_mngr_info buff_mgr_info, dup_buff_mgr_info; + int32_t in_fd; + int32_t num_output_bufs = 1; +- int32_t stripe_base = 0; ++ uint32_t stripe_base = 0; + uint32_t stripe_size; + uint8_t tnr_enabled; + enum msm_camera_buf_mngr_buf_type buf_type = +@@ -2411,6 +2411,13 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + return -EINVAL; + } + ++ if (stripe_base == UINT_MAX || new_frame->num_strips > ++ (UINT_MAX - 1 - stripe_base) / stripe_size) { ++ pr_err("Invalid frame message,num_strips %d is large\n", ++ new_frame->num_strips); ++ return -EINVAL; ++ } ++ + if ((stripe_base + new_frame->num_strips * stripe_size + 1) != + new_frame->msg_len) { + pr_err("Invalid frame message,len=%d,expected=%d\n", +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0523/0.patch b/Patches/Linux_CVEs/CVE-2017-0523/0.patch new file mode 100644 index 00000000..cbd30c4a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0523/0.patch @@ -0,0 +1,75 @@ +From 5bb646471da76d3d5cd02cf3da7a03ce6e3cb582 Mon Sep 17 00:00:00 2001 +From: Hamad Kadmany +Date: Sun, 18 Dec 2016 15:03:11 +0200 +Subject: wil6210: Block write ioctl to the card by default + +The ability to write to the card is used for debug purposes. +The ability is disabled by default to prevent misuse of +this functionality. + +CRs-Fixed: 1096945 +Change-Id: I8fc3f646a0127ec705239be6a7de858a4f805acc +Signed-off-by: Hamad Kadmany +--- + drivers/net/wireless/ath/wil6210/Kconfig | 11 +++++++++++ + drivers/net/wireless/ath/wil6210/ioctl.c | 4 ++++ + 2 files changed, 15 insertions(+) + +diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig +index 481680a..eaa5a9d 100644 +--- a/drivers/net/wireless/ath/wil6210/Kconfig ++++ b/drivers/net/wireless/ath/wil6210/Kconfig +@@ -40,6 +40,17 @@ config WIL6210_TRACING + + If unsure, say Y to make it easier to debug problems. + ++config WIL6210_WRITE_IOCTL ++ bool "wil6210 write ioctl to the device" ++ depends on WIL6210 ++ default n ++ ---help--- ++ Say Y here to allow write-access from user-space to ++ the device memory through ioctl. This is useful for ++ debugging purposes only. ++ ++ If unsure, say N. ++ + config WIL6210_PLATFORM_MSM + bool "wil6210 MSM platform specific support" + depends on WIL6210 +diff --git a/drivers/net/wireless/ath/wil6210/ioctl.c b/drivers/net/wireless/ath/wil6210/ioctl.c +index e9c0673..f5ad473 100644 +--- a/drivers/net/wireless/ath/wil6210/ioctl.c ++++ b/drivers/net/wireless/ath/wil6210/ioctl.c +@@ -79,10 +79,12 @@ static int wil_ioc_memio_dword(struct wil6210_priv *wil, void __user *data) + io.val = ioread32(a); + need_copy = true; + break; ++#if defined(CONFIG_WIL6210_WRITE_IOCTL) + case wil_mmio_write: + iowrite32(io.val, a); + wmb(); /* make sure write propagated to HW */ + break; ++#endif + default: + wil_err(wil, "Unsupported operation, op = 0x%08x\n", io.op); + return -EINVAL; +@@ -139,6 +141,7 @@ static int wil_ioc_memio_block(struct wil6210_priv *wil, void __user *data) + goto out_free; + } + break; ++#if defined(CONFIG_WIL6210_WRITE_IOCTL) + case wil_mmio_write: + if (copy_from_user(block, io.block, io.size)) { + rc = -EFAULT; +@@ -148,6 +151,7 @@ static int wil_ioc_memio_block(struct wil6210_priv *wil, void __user *data) + wmb(); /* make sure write propagated to HW */ + wil_hex_dump_ioctl("Write ", block, io.size); + break; ++#endif + default: + wil_err(wil, "Unsupported operation, op = 0x%08x\n", io.op); + rc = -EINVAL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0524/0.patch b/Patches/Linux_CVEs/CVE-2017-0524/0.patch new file mode 100644 index 00000000..e4a248b6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0524/0.patch @@ -0,0 +1,118 @@ +From e1fb1600fc222337989e3084d68df929882deae5 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Tue, 17 Jan 2017 07:37:52 -0800 +Subject: [PATCH] input: synaptics: put offset checks under mutex. + +Place file offset validity checks under mutex. + +BUG: 33555878 +BUG: 33002026 + +Change-Id: I1945cfc8af7d1a310ae0d7bbb85002d4c448f30b +Signed-off-by: Andrew Chant +--- + drivers/input/touchscreen/synaptics_rmi_dev.c | 52 ++++++++++++++++++--------- + 1 file changed, 36 insertions(+), 16 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c +index e2d7c27eb6832..e7c19d00c0544 100644 +--- a/drivers/input/touchscreen/synaptics_rmi_dev.c ++++ b/drivers/input/touchscreen/synaptics_rmi_dev.c +@@ -299,18 +299,26 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + return -EBADF; + } + +- if (count == 0) +- return 0; ++ mutex_lock(&(dev_data->file_mutex)); + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + +- tmpbuf = kzalloc(count + 1, GFP_KERNEL); +- if (!tmpbuf) +- return -ENOMEM; ++ if (count == 0) { ++ retval = 0; ++ goto unlock; ++ } + +- mutex_lock(&(dev_data->file_mutex)); ++ if (*f_pos > REG_ADDR_LIMIT) { ++ retval = -EFAULT; ++ goto unlock; ++ } + ++ tmpbuf = kzalloc(count + 1, GFP_KERNEL); ++ if (!tmpbuf) { ++ retval = -ENOMEM; ++ goto unlock; ++ } + retval = rmidev->fn_ptr->read(rmidev->rmi4_data, + *f_pos, + tmpbuf, +@@ -324,9 +332,10 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + *f_pos += retval; + + clean_up: ++ kfree(tmpbuf); ++unlock: + mutex_unlock(&(dev_data->file_mutex)); + +- kfree(tmpbuf); + return retval; + } + +@@ -350,23 +359,32 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + return -EBADF; + } + +- if (count == 0) +- return 0; ++ mutex_lock(&(dev_data->file_mutex)); ++ ++ if (*f_pos > REG_ADDR_LIMIT) { ++ retval = -EFAULT; ++ goto unlock; ++ } + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + ++ if (count == 0) { ++ retval = 0; ++ goto unlock; ++ } ++ + tmpbuf = kzalloc(count + 1, GFP_KERNEL); +- if (!tmpbuf) +- return -ENOMEM; ++ if (!tmpbuf) { ++ retval = -ENOMEM; ++ goto unlock; ++ } + + if (copy_from_user(tmpbuf, buf, count)) { +- kfree(tmpbuf); +- return -EFAULT; ++ retval = -EFAULT; ++ goto clean_up; + } + +- mutex_lock(&(dev_data->file_mutex)); +- + retval = rmidev->fn_ptr->write(rmidev->rmi4_data, + *f_pos, + tmpbuf, +@@ -374,8 +392,10 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + if (retval >= 0) + *f_pos += retval; + +- mutex_unlock(&(dev_data->file_mutex)); ++clean_up: + kfree(tmpbuf); ++unlock: ++ mutex_unlock(&(dev_data->file_mutex)); + return retval; + } + diff --git a/Patches/Linux_CVEs/CVE-2017-0524/1.patch b/Patches/Linux_CVEs/CVE-2017-0524/1.patch new file mode 100644 index 00000000..e4a087c5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0524/1.patch @@ -0,0 +1,85 @@ +From 0ab30d91fb178c5967753343029581983a4e9b67 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Fri, 13 Jan 2017 13:33:57 -0800 +Subject: [PATCH] input: synaptics_dsx: protect tmpbuf allocation. + +Protect tmpbuf from concurrent access by mutex. + +BUG: 33555878 +BUG: 33002026 +Change-Id: Ia986a34647d5825946594ea17a5cd6fa0abb115f +Signed-off-by: Andrew Chant +--- + .../synaptics_dsx25/synaptics_dsx_rmi_dev.c | 33 +++++++++++++++------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_rmi_dev.c +index 87abf86cdc6b4..018c621c0cfeb 100644 +--- a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_rmi_dev.c ++++ b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_rmi_dev.c +@@ -483,16 +483,21 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + return -EBADF; + } + +- if (count == 0) +- return 0; ++ mutex_lock(&(dev_data->file_mutex)); + ++ if (*f_pos > REG_ADDR_LIMIT) { ++ retval = -EFAULT; ++ goto clean_up; ++ } + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; ++ if (count == 0) { ++ retval = 0; ++ goto clean_up; ++ } + + rmidev_allocate_buffer(count); + +- mutex_lock(&(dev_data->file_mutex)); +- + retval = synaptics_rmi4_reg_read(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, +@@ -530,18 +535,25 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + return -EBADF; + } + +- if (count == 0) +- return 0; ++ mutex_lock(&(dev_data->file_mutex)); + ++ if (*f_pos > REG_ADDR_LIMIT) { ++ retval = -EFAULT; ++ goto unlock; ++ } + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; ++ if (count == 0) { ++ retval = 0; ++ goto unlock; ++ } + + rmidev_allocate_buffer(count); + +- if (copy_from_user(rmidev->tmpbuf, buf, count)) +- return -EFAULT; +- +- mutex_lock(&(dev_data->file_mutex)); ++ if (copy_from_user(rmidev->tmpbuf, buf, count)) { ++ retval = -EFAULT; ++ goto unlock; ++ } + + retval = synaptics_rmi4_reg_write(rmidev->rmi4_data, + *f_pos, +@@ -550,6 +562,7 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + if (retval >= 0) + *f_pos += retval; + ++unlock: + mutex_unlock(&(dev_data->file_mutex)); + + return retval; diff --git a/Patches/Linux_CVEs/CVE-2017-0524/2.patch b/Patches/Linux_CVEs/CVE-2017-0524/2.patch new file mode 100644 index 00000000..24e8b2ed --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0524/2.patch @@ -0,0 +1,91 @@ +From e6430a4da1fb0212a546379eadbe986f629c3ae9 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Fri, 13 Jan 2017 11:41:03 -0800 +Subject: [PATCH] input: synaptics_dsx: protect tmpbuf allocation. + +Protect tmpbuf from concurrent access by mutex. + +BUG: 33555878 +BUG: 33002026 +Change-Id: Ia7eeb59ca7b626f416e2298b4b9ffd960fe909e4 +Signed-off-by: Andrew Chant +--- + .../synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c | 36 ++++++++++++++-------- + 1 file changed, 24 insertions(+), 12 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c +index e699dfea50c81..6878b71da9be0 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c ++++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c +@@ -565,18 +565,24 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + return -EBADF; + } + +- if (count == 0) +- return 0; ++ mutex_lock(&(dev_data->file_mutex)); ++ ++ if (*f_pos > REG_ADDR_LIMIT) { ++ retval = -EFAULT; ++ goto clean_up; ++ } + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + ++ if (count == 0) { ++ retval = 0; ++ goto clean_up; ++ } + address = (unsigned short)(*f_pos); + + rmidev_allocate_buffer(count); + +- mutex_lock(&(dev_data->file_mutex)); +- + retval = synaptics_rmi4_reg_read(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, +@@ -636,19 +642,25 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + return -EBADF; + } + +- if (count == 0) +- return 0; ++ mutex_lock(&(dev_data->file_mutex)); + ++ if (*f_pos > REG_ADDR_LIMIT) { ++ retval = -EFAULT; ++ goto unlock; ++ } + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; ++ if (count == 0) { ++ retval = 0; ++ goto unlock; ++ } + + rmidev_allocate_buffer(count); + +- if (copy_from_user(rmidev->tmpbuf, buf, count)) +- return -EFAULT; +- +- mutex_lock(&(dev_data->file_mutex)); +- ++ if (copy_from_user(rmidev->tmpbuf, buf, count)) { ++ retval = -EFAULT; ++ goto unlock; ++ } + retval = synaptics_rmi4_reg_write(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, +@@ -656,8 +668,8 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + if (retval >= 0) + *f_pos += retval; + ++unlock: + mutex_unlock(&(dev_data->file_mutex)); +- + return retval; + } + diff --git a/Patches/Linux_CVEs/CVE-2017-0525/0.patch b/Patches/Linux_CVEs/CVE-2017-0525/0.patch new file mode 100644 index 00000000..7f1b17e4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0525/0.patch @@ -0,0 +1,663 @@ +From 050ee9e77ca89e9997792a0ab371470218da9a97 Mon Sep 17 00:00:00 2001 +From: Aaron Tzeng +Date: Thu, 12 Jan 2017 15:14:15 +0200 +Subject: msm: ipa: Prevent multiple header deletion from user space + +An IPA header or processing context can be added once +and later deleted once from user space. +Multiple deletion may cause invalid state of the headers +software cache. + +Change-Id: Ic0b8472b7fd8a76233a007d90c832af726184574 +CRs-fixed: 1097714 +Signed-off-by: Ghanim Fodi +--- + drivers/platform/msm/ipa/ipa_v2/ipa.c | 13 ++--- + drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c | 79 +++++++++++++++++++++++++------ + drivers/platform/msm/ipa/ipa_v2/ipa_i.h | 13 ++++- + drivers/platform/msm/ipa/ipa_v3/ipa.c | 11 +++-- + drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c | 79 +++++++++++++++++++++++++------ + drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 11 ++++- + 6 files changed, 162 insertions(+), 44 deletions(-) + +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c +index 393d580..011500c 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -777,7 +777,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EINVAL; + break; + } +- if (ipa2_del_hdr((struct ipa_ioc_del_hdr *)param)) { ++ if (ipa2_del_hdr_by_user((struct ipa_ioc_del_hdr *)param, ++ true)) { + retval = -EFAULT; + break; + } +@@ -1461,8 +1462,8 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EINVAL; + break; + } +- if (ipa2_del_hdr_proc_ctx( +- (struct ipa_ioc_del_hdr_proc_ctx *)param)) { ++ if (ipa2_del_hdr_proc_ctx_by_user( ++ (struct ipa_ioc_del_hdr_proc_ctx *)param, true)) { + retval = -EFAULT; + break; + } +@@ -2755,7 +2756,7 @@ fail_schedule_delayed_work: + if (ipa_ctx->dflt_v4_rt_rule_hdl) + __ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl); + if (ipa_ctx->excp_hdr_hdl) +- __ipa_del_hdr(ipa_ctx->excp_hdr_hdl); ++ __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false); + ipa2_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd); + fail_cmd: + return result; +@@ -2767,7 +2768,7 @@ static void ipa_teardown_apps_pipes(void) + ipa2_teardown_sys_pipe(ipa_ctx->clnt_hdl_data_in); + __ipa_del_rt_rule(ipa_ctx->dflt_v6_rt_rule_hdl); + __ipa_del_rt_rule(ipa_ctx->dflt_v4_rt_rule_hdl); +- __ipa_del_hdr(ipa_ctx->excp_hdr_hdl); ++ __ipa_del_hdr(ipa_ctx->excp_hdr_hdl, false); + ipa2_teardown_sys_pipe(ipa_ctx->clnt_hdl_cmd); + } + +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c +index 1452c59..a3caf3e 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2015, 2017, The 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 +@@ -731,7 +731,8 @@ error: + return -EPERM; + } + +-static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) ++static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, ++ bool release_hdr, bool by_user) + { + struct ipa_hdr_proc_ctx_entry *entry; + struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; +@@ -745,6 +746,14 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) + IPADBG("del ctx proc cnt=%d ofst=%d\n", + htbl->proc_ctx_cnt, entry->offset_entry->offset); + ++ if (by_user && entry->user_deleted) { ++ IPAERR("proc_ctx already deleted by user\n"); ++ return -EINVAL; ++ } ++ ++ if (by_user) ++ entry->user_deleted = true; ++ + if (--entry->ref_cnt) { + IPADBG("proc_ctx_hdl %x ref_cnt %d\n", + proc_ctx_hdl, entry->ref_cnt); +@@ -752,7 +761,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) + } + + if (release_hdr) +- __ipa_release_hdr(entry->hdr->id); ++ __ipa_del_hdr(entry->hdr->id, false); + + /* move the offset entry to appropriate free list */ + list_move(&entry->offset_entry->link, +@@ -769,7 +778,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) + } + + +-int __ipa_del_hdr(u32 hdr_hdl) ++int __ipa_del_hdr(u32 hdr_hdl, bool by_user) + { + struct ipa_hdr_entry *entry; + struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl; +@@ -780,7 +789,7 @@ int __ipa_del_hdr(u32 hdr_hdl) + return -EINVAL; + } + +- if (!entry || (entry->cookie != IPA_COOKIE)) { ++ if (entry->cookie != IPA_COOKIE) { + IPAERR("bad parm\n"); + return -EINVAL; + } +@@ -788,6 +797,14 @@ int __ipa_del_hdr(u32 hdr_hdl) + IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len, + htbl->hdr_cnt, entry->offset_entry->offset); + ++ if (by_user && entry->user_deleted) { ++ IPAERR("hdr already deleted by user\n"); ++ return -EINVAL; ++ } ++ ++ if (by_user) ++ entry->user_deleted = true; ++ + if (--entry->ref_cnt) { + IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt); + return 0; +@@ -798,7 +815,7 @@ int __ipa_del_hdr(u32 hdr_hdl) + entry->phys_base, + entry->hdr_len, + DMA_TO_DEVICE); +- __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false); ++ __ipa_del_hdr_proc_ctx(entry->proc_ctx->id, false, false); + } else { + /* move the offset entry to appropriate free list */ + list_move(&entry->offset_entry->link, +@@ -865,15 +882,16 @@ bail: + } + + /** +- * ipa2_del_hdr() - Remove the specified headers from SW and optionally commit them +- * to IPA HW ++ * ipa2_del_hdr_by_user() - Remove the specified headers ++ * from SW and optionally commit them to IPA HW + * @hdls: [inout] set of headers to delete ++ * @by_user: Operation requested by user? + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +-int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls) ++int ipa2_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user) + { + int i; + int result = -EFAULT; +@@ -890,7 +908,7 @@ int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls) + + mutex_lock(&ipa_ctx->lock); + for (i = 0; i < hdls->num_hdls; i++) { +- if (__ipa_del_hdr(hdls->hdl[i].hdl)) { ++ if (__ipa_del_hdr(hdls->hdl[i].hdl, by_user)) { + IPAERR("failed to del hdr %i\n", i); + hdls->hdl[i].status = -1; + } else { +@@ -911,6 +929,20 @@ bail: + } + + /** ++ * ipa2_del_hdr() - Remove the specified headers from SW and optionally commit them ++ * to IPA HW ++ * @hdls: [inout] set of headers to delete ++ * ++ * Returns: 0 on success, negative on failure ++ * ++ * Note: Should not be called from atomic context ++ */ ++int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls) ++{ ++ return ipa2_del_hdr_by_user(hdls, false); ++} ++ ++/** + * ipa2_add_hdr_proc_ctx() - add the specified headers to SW + * and optionally commit them to IPA HW + * @proc_ctxs: [inout] set of processing context headers to add +@@ -962,16 +994,18 @@ bail: + } + + /** +- * ipa2_del_hdr_proc_ctx() - ++ * ipa2_del_hdr_proc_ctx_by_user() - + * Remove the specified processing context headers from SW and + * optionally commit them to IPA HW. + * @hdls: [inout] set of processing context headers to delete ++ * @by_user: Operation requested by user? + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +-int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) ++int ipa2_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, ++ bool by_user) + { + int i; + int result; +@@ -990,7 +1024,7 @@ int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) + + mutex_lock(&ipa_ctx->lock); + for (i = 0; i < hdls->num_hdls; i++) { +- if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true)) { ++ if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) { + IPAERR("failed to del hdr %i\n", i); + hdls->hdl[i].status = -1; + } else { +@@ -1011,6 +1045,21 @@ bail: + } + + /** ++ * ipa2_del_hdr_proc_ctx() - ++ * Remove the specified processing context headers from SW and ++ * optionally commit them to IPA HW. ++ * @hdls: [inout] set of processing context headers to delete ++ * ++ * Returns: 0 on success, negative on failure ++ * ++ * Note: Should not be called from atomic context ++ */ ++int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) ++{ ++ return ipa2_del_hdr_proc_ctx_by_user(hdls, false); ++} ++ ++/** + * ipa2_commit_hdr() - commit to IPA HW the current header table in SW + * + * Returns: 0 on success, negative on failure +@@ -1231,7 +1280,7 @@ int __ipa_release_hdr(u32 hdr_hdl) + { + int result = 0; + +- if (__ipa_del_hdr(hdr_hdl)) { ++ if (__ipa_del_hdr(hdr_hdl, false)) { + IPADBG("fail to del hdr %x\n", hdr_hdl); + result = -EFAULT; + goto bail; +@@ -1259,7 +1308,7 @@ int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl) + { + int result = 0; + +- if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true)) { ++ if (__ipa_del_hdr_proc_ctx(proc_ctx_hdl, true, false)) { + IPADBG("fail to del hdr %x\n", proc_ctx_hdl); + result = -EFAULT; + goto bail; +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +index b3827ab..13892ce 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -367,6 +367,7 @@ struct ipa_rt_tbl { + * @id: header entry id + * @is_eth2_ofst_valid: is eth2_ofst field valid? + * @eth2_ofst: offset to start of Ethernet-II/802.3 header ++ * @user_deleted: is the header deleted by the user? + */ + struct ipa_hdr_entry { + struct list_head link; +@@ -384,6 +385,7 @@ struct ipa_hdr_entry { + int id; + u8 is_eth2_ofst_valid; + u16 eth2_ofst; ++ bool user_deleted; + }; + + /** +@@ -459,6 +461,7 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq { + * @cookie: cookie used for validity check + * @ref_cnt: reference counter of routing table + * @id: processing context header entry id ++ * @user_deleted: is the hdr processing context deleted by the user? + */ + struct ipa_hdr_proc_ctx_entry { + struct list_head link; +@@ -468,6 +471,7 @@ struct ipa_hdr_proc_ctx_entry { + u32 cookie; + u32 ref_cnt; + int id; ++ bool user_deleted; + }; + + /** +@@ -1634,6 +1638,8 @@ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs); + + int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls); + ++int ipa2_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user); ++ + int ipa2_commit_hdr(void); + + int ipa2_reset_hdr(void); +@@ -1651,6 +1657,9 @@ int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); + + int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); + ++int ipa2_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, ++ bool by_user); ++ + /* + * Routing + */ +@@ -1979,7 +1988,7 @@ int ipa2_active_clients_log_print_table(char *buf, int size); + void ipa2_active_clients_log_clear(void); + int ipa_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev); + int __ipa_del_rt_rule(u32 rule_hdl); +-int __ipa_del_hdr(u32 hdr_hdl); ++int __ipa_del_hdr(u32 hdr_hdl, bool by_user); + int __ipa_release_hdr(u32 hdr_hdl); + int __ipa_release_hdr_proc_ctx(u32 proc_ctx_hdl); + int _ipa_read_gen_reg_v1_1(char *buff, int max_len); +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c +index 96089b1..56e7ab8 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c +@@ -794,7 +794,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EINVAL; + break; + } +- if (ipa3_del_hdr((struct ipa_ioc_del_hdr *)param)) { ++ if (ipa3_del_hdr_by_user((struct ipa_ioc_del_hdr *)param, ++ true)) { + retval = -EFAULT; + break; + } +@@ -1563,8 +1564,8 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + retval = -EINVAL; + break; + } +- if (ipa3_del_hdr_proc_ctx( +- (struct ipa_ioc_del_hdr_proc_ctx *)param)) { ++ if (ipa3_del_hdr_proc_ctx_by_user( ++ (struct ipa_ioc_del_hdr_proc_ctx *)param, true)) { + retval = -EFAULT; + break; + } +@@ -3038,7 +3039,7 @@ fail_schedule_delayed_work: + if (ipa3_ctx->dflt_v4_rt_rule_hdl) + __ipa3_del_rt_rule(ipa3_ctx->dflt_v4_rt_rule_hdl); + if (ipa3_ctx->excp_hdr_hdl) +- __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl); ++ __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl, false); + ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_cmd); + fail_cmd: + return result; +@@ -3050,7 +3051,7 @@ static void ipa3_teardown_apps_pipes(void) + ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_data_in); + __ipa3_del_rt_rule(ipa3_ctx->dflt_v6_rt_rule_hdl); + __ipa3_del_rt_rule(ipa3_ctx->dflt_v4_rt_rule_hdl); +- __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl); ++ __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl, false); + ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_cmd); + } + +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +index b8baa53..523c1df 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -603,7 +603,8 @@ error: + return -EPERM; + } + +-static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) ++static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, ++ bool release_hdr, bool by_user) + { + struct ipa3_hdr_proc_ctx_entry *entry; + struct ipa3_hdr_proc_ctx_tbl *htbl = &ipa3_ctx->hdr_proc_ctx_tbl; +@@ -617,6 +618,14 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) + IPADBG("del ctx proc cnt=%d ofst=%d\n", + htbl->proc_ctx_cnt, entry->offset_entry->offset); + ++ if (by_user && entry->user_deleted) { ++ IPAERR("proc_ctx already deleted by user\n"); ++ return -EINVAL; ++ } ++ ++ if (by_user) ++ entry->user_deleted = true; ++ + if (--entry->ref_cnt) { + IPADBG("proc_ctx_hdl %x ref_cnt %d\n", + proc_ctx_hdl, entry->ref_cnt); +@@ -624,7 +633,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) + } + + if (release_hdr) +- __ipa3_release_hdr(entry->hdr->id); ++ __ipa3_del_hdr(entry->hdr->id, false); + + /* move the offset entry to appropriate free list */ + list_move(&entry->offset_entry->link, +@@ -641,7 +650,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr) + } + + +-int __ipa3_del_hdr(u32 hdr_hdl) ++int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) + { + struct ipa3_hdr_entry *entry; + struct ipa3_hdr_tbl *htbl = &ipa3_ctx->hdr_tbl; +@@ -652,7 +661,7 @@ int __ipa3_del_hdr(u32 hdr_hdl) + return -EINVAL; + } + +- if (!entry || (entry->cookie != IPA_COOKIE)) { ++ if (entry->cookie != IPA_COOKIE) { + IPAERR("bad parm\n"); + return -EINVAL; + } +@@ -660,6 +669,14 @@ int __ipa3_del_hdr(u32 hdr_hdl) + IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len, + htbl->hdr_cnt, entry->offset_entry->offset); + ++ if (by_user && entry->user_deleted) { ++ IPAERR("proc_ctx already deleted by user\n"); ++ return -EINVAL; ++ } ++ ++ if (by_user) ++ entry->user_deleted = true; ++ + if (--entry->ref_cnt) { + IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt); + return 0; +@@ -670,7 +687,7 @@ int __ipa3_del_hdr(u32 hdr_hdl) + entry->phys_base, + entry->hdr_len, + DMA_TO_DEVICE); +- __ipa3_del_hdr_proc_ctx(entry->proc_ctx->id, false); ++ __ipa3_del_hdr_proc_ctx(entry->proc_ctx->id, false, false); + } else { + /* move the offset entry to appropriate free list */ + list_move(&entry->offset_entry->link, +@@ -732,15 +749,16 @@ bail: + } + + /** +- * ipa3_del_hdr() - Remove the specified headers from SW and optionally commit them +- * to IPA HW ++ * ipa3_del_hdr_by_user() - Remove the specified headers ++ * from SW and optionally commit them to IPA HW + * @hdls: [inout] set of headers to delete ++ * @by_user: Operation requested by user? + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +-int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls) ++int ipa3_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user) + { + int i; + int result = -EFAULT; +@@ -752,7 +770,7 @@ int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls) + + mutex_lock(&ipa3_ctx->lock); + for (i = 0; i < hdls->num_hdls; i++) { +- if (__ipa3_del_hdr(hdls->hdl[i].hdl)) { ++ if (__ipa3_del_hdr(hdls->hdl[i].hdl, by_user)) { + IPAERR("failed to del hdr %i\n", i); + hdls->hdl[i].status = -1; + } else { +@@ -773,6 +791,20 @@ bail: + } + + /** ++ * ipa3_del_hdr() - Remove the specified headers from SW and optionally commit them ++ * to IPA HW ++ * @hdls: [inout] set of headers to delete ++ * ++ * Returns: 0 on success, negative on failure ++ * ++ * Note: Should not be called from atomic context ++ */ ++int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls) ++{ ++ return ipa3_del_hdr_by_user(hdls, false); ++} ++ ++/** + * ipa3_add_hdr_proc_ctx() - add the specified headers to SW + * and optionally commit them to IPA HW + * @proc_ctxs: [inout] set of processing context headers to add +@@ -817,16 +849,18 @@ bail: + } + + /** +- * ipa3_del_hdr_proc_ctx() - ++ * ipa3_del_hdr_proc_ctx_by_user() - + * Remove the specified processing context headers from SW and + * optionally commit them to IPA HW. + * @hdls: [inout] set of processing context headers to delete ++ * @by_user: Operation requested by user? + * + * Returns: 0 on success, negative on failure + * + * Note: Should not be called from atomic context + */ +-int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) ++int ipa3_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, ++ bool by_user) + { + int i; + int result; +@@ -838,7 +872,7 @@ int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) + + mutex_lock(&ipa3_ctx->lock); + for (i = 0; i < hdls->num_hdls; i++) { +- if (__ipa3_del_hdr_proc_ctx(hdls->hdl[i].hdl, true)) { ++ if (__ipa3_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) { + IPAERR("failed to del hdr %i\n", i); + hdls->hdl[i].status = -1; + } else { +@@ -859,6 +893,21 @@ bail: + } + + /** ++ * ipa3_del_hdr_proc_ctx() - ++ * Remove the specified processing context headers from SW and ++ * optionally commit them to IPA HW. ++ * @hdls: [inout] set of processing context headers to delete ++ * ++ * Returns: 0 on success, negative on failure ++ * ++ * Note: Should not be called from atomic context ++ */ ++int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls) ++{ ++ return ipa3_del_hdr_proc_ctx_by_user(hdls, false); ++} ++ ++/** + * ipa3_commit_hdr() - commit to IPA HW the current header table in SW + * + * Returns: 0 on success, negative on failure +@@ -1079,7 +1128,7 @@ int __ipa3_release_hdr(u32 hdr_hdl) + { + int result = 0; + +- if (__ipa3_del_hdr(hdr_hdl)) { ++ if (__ipa3_del_hdr(hdr_hdl, false)) { + IPADBG("fail to del hdr %x\n", hdr_hdl); + result = -EFAULT; + goto bail; +@@ -1107,7 +1156,7 @@ int __ipa3_release_hdr_proc_ctx(u32 proc_ctx_hdl) + { + int result = 0; + +- if (__ipa3_del_hdr_proc_ctx(proc_ctx_hdl, true)) { ++ if (__ipa3_del_hdr_proc_ctx(proc_ctx_hdl, true, false)) { + IPADBG("fail to del hdr %x\n", proc_ctx_hdl); + result = -EFAULT; + goto bail; +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +index b4a9ac3..b2e6b90 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +@@ -430,6 +430,7 @@ struct ipa3_rt_tbl { + * @id: header entry id + * @is_eth2_ofst_valid: is eth2_ofst field valid? + * @eth2_ofst: offset to start of Ethernet-II/802.3 header ++ * @user_deleted: is the header deleted by the user? + */ + struct ipa3_hdr_entry { + struct list_head link; +@@ -447,6 +448,7 @@ struct ipa3_hdr_entry { + int id; + u8 is_eth2_ofst_valid; + u16 eth2_ofst; ++ bool user_deleted; + }; + + /** +@@ -522,6 +524,7 @@ struct ipa3_hdr_proc_ctx_add_hdr_cmd_seq { + * @cookie: cookie used for validity check + * @ref_cnt: reference counter of routing table + * @id: processing context header entry id ++ * @user_deleted: is the hdr processing context deleted by the user? + */ + struct ipa3_hdr_proc_ctx_entry { + struct list_head link; +@@ -531,6 +534,7 @@ struct ipa3_hdr_proc_ctx_entry { + u32 cookie; + u32 ref_cnt; + int id; ++ bool user_deleted; + }; + + /** +@@ -1816,6 +1820,8 @@ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs); + + int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls); + ++int ipa3_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user); ++ + int ipa3_commit_hdr(void); + + int ipa3_reset_hdr(void); +@@ -1833,6 +1839,9 @@ int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs); + + int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls); + ++int ipa3_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, ++ bool by_user); ++ + /* + * Routing + */ +@@ -2175,7 +2184,7 @@ int ipa3_active_clients_log_print_table(char *buf, int size); + void ipa3_active_clients_log_clear(void); + int ipa3_interrupts_init(u32 ipa_irq, u32 ee, struct device *ipa_dev); + int __ipa3_del_rt_rule(u32 rule_hdl); +-int __ipa3_del_hdr(u32 hdr_hdl); ++int __ipa3_del_hdr(u32 hdr_hdl, bool by_user); + int __ipa3_release_hdr(u32 hdr_hdl); + int __ipa3_release_hdr_proc_ctx(u32 proc_ctx_hdl); + int _ipa_read_ep_reg_v3_0(char *buf, int max_len, int pipe); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0531/0.patch b/Patches/Linux_CVEs/CVE-2017-0531/0.patch new file mode 100644 index 00000000..8c9dd352 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0531/0.patch @@ -0,0 +1,275 @@ +From 530f3a0fd837ed105eddaf99810bc13d97dc4302 Mon Sep 17 00:00:00 2001 +From: Bhalchandra Gajare +Date: Thu, 15 Dec 2016 16:43:45 -0800 +Subject: ASoC: msm-lsm-client: cleanup ioctl functions + +Some of the ioctl command handling is not properly using the +copy_from_user interface. Fix these issues and cleanup the ioctl +functions to make sure there is no illegal memory access. + +CRs-Fixed: 1087469 +Change-Id: Ieb1beb92e7854a05b8045de0ce179d12c9a6da74 +Signed-off-by: Bhalchandra Gajare +--- + sound/soc/msm/qdsp6v2/msm-lsm-client.c | 131 ++++++++++----------------------- + 1 file changed, 40 insertions(+), 91 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +index 32a16bf..c365220 100644 +--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c ++++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +@@ -727,8 +727,13 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + switch (cmd) { + case SNDRV_LSM_SET_SESSION_DATA: + dev_dbg(rtd->dev, "%s: set session data\n", __func__); +- memcpy(&session_data, arg, +- sizeof(struct snd_lsm_session_data)); ++ if (copy_from_user(&session_data, arg, ++ sizeof(session_data))) { ++ dev_err(rtd->dev, "%s: %s: copy_from_user failed\n", ++ __func__, "LSM_SET_SESSION_DATA"); ++ return -EFAULT; ++ } ++ + if (session_data.app_id != LSM_VOICE_WAKEUP_APP_ID_V2) { + dev_err(rtd->dev, + "%s:Invalid App id %d for Listen client\n", +@@ -817,13 +822,6 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + break; + + case SNDRV_LSM_SET_PARAMS: +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s Invalid argument\n", +- __func__, "SNDRV_LSM_SET_PARAMS"); +- return -EINVAL; +- } +- + dev_dbg(rtd->dev, "%s: set_params\n", __func__); + memcpy(&det_params, arg, + sizeof(det_params)); +@@ -975,45 +973,43 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + break; + } + case SNDRV_LSM_LAB_CONTROL: { +- u32 *enable = NULL; +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid param arg for ioctl %s session %d\n", +- __func__, "SNDRV_LSM_LAB_CONTROL", +- prtd->lsm_client->session); +- rc = -EINVAL; +- break; ++ u32 enable; ++ ++ if (copy_from_user(&enable, arg, sizeof(enable))) { ++ dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n", ++ __func__, "LSM_LAB_CONTROL"); ++ return -EFAULT; + } +- enable = (int *)arg; ++ + dev_dbg(rtd->dev, "%s: ioctl %s, enable = %d\n", +- __func__, "SNDRV_LSM_LAB_CONTROL", *enable); ++ __func__, "SNDRV_LSM_LAB_CONTROL", enable); + if (!prtd->lsm_client->started) { +- if (prtd->lsm_client->lab_enable == *enable) { ++ if (prtd->lsm_client->lab_enable == enable) { + dev_dbg(rtd->dev, + "%s: Lab for session %d already %s\n", + __func__, prtd->lsm_client->session, +- ((*enable) ? "enabled" : "disabled")); ++ enable ? "enabled" : "disabled"); + rc = 0; + break; + } +- rc = q6lsm_lab_control(prtd->lsm_client, *enable); ++ rc = q6lsm_lab_control(prtd->lsm_client, enable); + if (rc) { + dev_err(rtd->dev, + "%s: ioctl %s failed rc %d to %s lab for session %d\n", + __func__, "SNDRV_LAB_CONTROL", rc, +- ((*enable) ? "enable" : "disable"), ++ enable ? "enable" : "disable", + prtd->lsm_client->session); + } else { + rc = msm_lsm_lab_buffer_alloc(prtd, +- ((*enable) ? LAB_BUFFER_ALLOC +- : LAB_BUFFER_DEALLOC)); ++ enable ? LAB_BUFFER_ALLOC ++ : LAB_BUFFER_DEALLOC); + if (rc) + dev_err(rtd->dev, + "%s: msm_lsm_lab_buffer_alloc failed rc %d for %s", + __func__, rc, +- ((*enable) ? "ALLOC" : "DEALLOC")); ++ enable ? "ALLOC" : "DEALLOC"); + if (!rc) +- prtd->lsm_client->lab_enable = *enable; ++ prtd->lsm_client->lab_enable = enable; + } + } else { + dev_err(rtd->dev, "%s: ioctl %s issued after start", +@@ -1060,12 +1056,6 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + return rc; + } + #ifdef CONFIG_COMPAT +-struct snd_lsm_event_status32 { +- u16 status; +- u16 payload_size; +- u8 payload[0]; +-}; +- + struct snd_lsm_sound_model_v2_32 { + compat_uptr_t data; + compat_uptr_t confidence_level; +@@ -1097,8 +1087,6 @@ struct snd_lsm_module_params_32 { + }; + + enum { +- SNDRV_LSM_EVENT_STATUS32 = +- _IOW('U', 0x02, struct snd_lsm_event_status32), + SNDRV_LSM_REG_SND_MODEL_V2_32 = + _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32), + SNDRV_LSM_SET_PARAMS_32 = +@@ -1129,12 +1117,12 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + prtd = runtime->private_data; + + switch (cmd) { +- case SNDRV_LSM_EVENT_STATUS32: { +- struct snd_lsm_event_status32 userarg32, *user32 = NULL; +- struct snd_lsm_event_status *user = NULL; ++ case SNDRV_LSM_EVENT_STATUS: { ++ struct snd_lsm_event_status *user = NULL, userarg32; ++ struct snd_lsm_event_status *user32 = NULL; + if (copy_from_user(&userarg32, arg, sizeof(userarg32))) { + dev_err(rtd->dev, "%s: err copyuser ioctl %s\n", +- __func__, "SNDRV_LSM_EVENT_STATUS32"); ++ __func__, "SNDRV_LSM_EVENT_STATUS"); + return -EFAULT; + } + +@@ -1288,13 +1276,6 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s: No Param data to set\n", +- __func__, "SET_MODULE_PARAMS_32"); +- return -EINVAL; +- } +- + if (copy_from_user(&p_data_32, arg, + sizeof(p_data_32))) { + dev_err(rtd->dev, +@@ -1379,6 +1360,19 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + kfree(params32); + break; + } ++ case SNDRV_LSM_REG_SND_MODEL_V2: ++ case SNDRV_LSM_SET_PARAMS: ++ case SNDRV_LSM_SET_MODULE_PARAMS: ++ /* ++ * In ideal cases, the compat_ioctl should never be called ++ * with the above unlocked ioctl commands. Print error ++ * and return error if it does. ++ */ ++ dev_err(rtd->dev, ++ "%s: Invalid cmd for compat_ioctl\n", ++ __func__); ++ err = -EINVAL; ++ break; + default: + err = msm_lsm_ioctl_shared(substream, cmd, arg); + break; +@@ -1394,7 +1388,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + { + int err = 0; + u32 size = 0; +- struct snd_lsm_session_data session_data; + struct snd_pcm_runtime *runtime; + struct snd_soc_pcm_runtime *rtd; + struct lsm_priv *prtd; +@@ -1409,26 +1402,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + rtd = substream->private_data; + + switch (cmd) { +- case SNDRV_LSM_SET_SESSION_DATA: +- dev_dbg(rtd->dev, +- "%s: SNDRV_LSM_SET_SESSION_DATA\n", +- __func__); +- if (copy_from_user(&session_data, (void *)arg, +- sizeof(struct snd_lsm_session_data))) { +- err = -EFAULT; +- dev_err(rtd->dev, +- "%s: copy from user failed, size %zd\n", +- __func__, sizeof(struct snd_lsm_session_data)); +- break; +- } +- if (!err) +- err = msm_lsm_ioctl_shared(substream, +- cmd, &session_data); +- if (err) +- dev_err(rtd->dev, +- "%s REG_SND_MODEL failed err %d\n", +- __func__, err); +- break; + case SNDRV_LSM_REG_SND_MODEL_V2: { + struct snd_lsm_sound_model_v2 snd_model_v2; + +@@ -1439,11 +1412,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid params snd_model\n", __func__); +- return -EINVAL; +- } + if (copy_from_user(&snd_model_v2, arg, sizeof(snd_model_v2))) { + err = -EFAULT; + dev_err(rtd->dev, +@@ -1472,12 +1440,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + } + + pr_debug("%s: SNDRV_LSM_SET_PARAMS\n", __func__); +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s, Invalid params\n", +- __func__, "SNDRV_LSM_SET_PARAMS"); +- return -EINVAL; +- } + + if (copy_from_user(&det_params, arg, + sizeof(det_params))) { +@@ -1510,13 +1472,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s: No Param data to set\n", +- __func__, "SET_MODULE_PARAMS"); +- return -EINVAL; +- } +- + if (copy_from_user(&p_data, arg, + sizeof(p_data))) { + dev_err(rtd->dev, +@@ -1574,12 +1529,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + struct snd_lsm_event_status *user = NULL, userarg; + dev_dbg(rtd->dev, + "%s: SNDRV_LSM_EVENT_STATUS\n", __func__); +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid params event status\n", +- __func__); +- return -EINVAL; +- } + if (copy_from_user(&userarg, arg, sizeof(userarg))) { + dev_err(rtd->dev, + "%s: err copyuser event_status\n", +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0533/0.patch b/Patches/Linux_CVEs/CVE-2017-0533/0.patch new file mode 100644 index 00000000..b08ceefb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0533/0.patch @@ -0,0 +1,73 @@ +From e3af5e89426f1c8d4e703d415eff5435b925649f Mon Sep 17 00:00:00 2001 +From: Benet Clark +Date: Thu, 10 Nov 2016 17:49:09 -0800 +Subject: msm: mdss: Clear compat structures before copying to user + +In the compat layer, the temporary structures used to convert +data from 32bit to 64bit structures need to be set to 0 before +being assigned values. + +CRs-Fixed: 1088206 +Change-Id: I04497bc11e01c3df4beadfd6d9b06ab4321f1723 +Signed-off-by: Benet Clark +--- + drivers/video/msm/mdss/mdss_compat_utils.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c +index 5ad51dd..a9ab5c1 100644 +--- a/drivers/video/msm/mdss/mdss_compat_utils.c ++++ b/drivers/video/msm/mdss/mdss_compat_utils.c +@@ -846,6 +846,7 @@ static int __from_user_pcc_coeff_v17( + return -EFAULT; + } + ++ memset(&pcc_cfg_payload, 0, sizeof(pcc_cfg_payload)); + pcc_cfg_payload.r.b = pcc_cfg_payload32.r.b; + pcc_cfg_payload.r.g = pcc_cfg_payload32.r.g; + pcc_cfg_payload.r.c = pcc_cfg_payload32.r.c; +@@ -1127,6 +1128,8 @@ static int __from_user_igc_lut_data_v17( + pr_err("failed to copy payload from user for igc\n"); + return -EFAULT; + } ++ ++ memset(&igc_cfg_payload, 0, sizeof(igc_cfg_payload)); + igc_cfg_payload.c0_c1_data = compat_ptr(igc_cfg_payload_32.c0_c1_data); + igc_cfg_payload.c2_data = compat_ptr(igc_cfg_payload_32.c2_data); + igc_cfg_payload.len = igc_cfg_payload_32.len; +@@ -1261,6 +1264,7 @@ static int __from_user_pgc_lut_data_v1_7( + pr_err("failed to copy from user the pgc32 payload\n"); + return -EFAULT; + } ++ memset(&pgc_cfg_payload, 0, sizeof(pgc_cfg_payload)); + pgc_cfg_payload.c0_data = compat_ptr(pgc_cfg_payload_32.c0_data); + pgc_cfg_payload.c1_data = compat_ptr(pgc_cfg_payload_32.c1_data); + pgc_cfg_payload.c2_data = compat_ptr(pgc_cfg_payload_32.c2_data); +@@ -1470,6 +1474,7 @@ static int __from_user_hist_lut_data_v1_7( + return -EFAULT; + } + ++ memset(&hist_lut_cfg_payload, 0, sizeof(hist_lut_cfg_payload)); + hist_lut_cfg_payload.len = hist_lut_cfg_payload32.len; + hist_lut_cfg_payload.data = compat_ptr(hist_lut_cfg_payload32.data); + +@@ -2024,6 +2029,7 @@ static int __from_user_pa_data_v1_7( + return -EFAULT; + } + ++ memset(&pa_cfg_payload, 0, sizeof(pa_cfg_payload)); + pa_cfg_payload.mode = pa_cfg_payload32.mode; + pa_cfg_payload.global_hue_adj = pa_cfg_payload32.global_hue_adj; + pa_cfg_payload.global_sat_adj = pa_cfg_payload32.global_sat_adj; +@@ -2280,6 +2286,8 @@ static int __from_user_gamut_cfg_data_v17( + pr_err("failed to copy the gamut payload from userspace\n"); + return -EFAULT; + } ++ ++ memset(&gamut_cfg_payload, 0, sizeof(gamut_cfg_payload)); + gamut_cfg_payload.mode = gamut_cfg_payload32.mode; + for (i = 0; i < MDP_GAMUT_TABLE_NUM_V1_7; i++) { + gamut_cfg_payload.tbl_size[i] = +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0534/0.patch b/Patches/Linux_CVEs/CVE-2017-0534/0.patch new file mode 100644 index 00000000..b08ceefb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0534/0.patch @@ -0,0 +1,73 @@ +From e3af5e89426f1c8d4e703d415eff5435b925649f Mon Sep 17 00:00:00 2001 +From: Benet Clark +Date: Thu, 10 Nov 2016 17:49:09 -0800 +Subject: msm: mdss: Clear compat structures before copying to user + +In the compat layer, the temporary structures used to convert +data from 32bit to 64bit structures need to be set to 0 before +being assigned values. + +CRs-Fixed: 1088206 +Change-Id: I04497bc11e01c3df4beadfd6d9b06ab4321f1723 +Signed-off-by: Benet Clark +--- + drivers/video/msm/mdss/mdss_compat_utils.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c +index 5ad51dd..a9ab5c1 100644 +--- a/drivers/video/msm/mdss/mdss_compat_utils.c ++++ b/drivers/video/msm/mdss/mdss_compat_utils.c +@@ -846,6 +846,7 @@ static int __from_user_pcc_coeff_v17( + return -EFAULT; + } + ++ memset(&pcc_cfg_payload, 0, sizeof(pcc_cfg_payload)); + pcc_cfg_payload.r.b = pcc_cfg_payload32.r.b; + pcc_cfg_payload.r.g = pcc_cfg_payload32.r.g; + pcc_cfg_payload.r.c = pcc_cfg_payload32.r.c; +@@ -1127,6 +1128,8 @@ static int __from_user_igc_lut_data_v17( + pr_err("failed to copy payload from user for igc\n"); + return -EFAULT; + } ++ ++ memset(&igc_cfg_payload, 0, sizeof(igc_cfg_payload)); + igc_cfg_payload.c0_c1_data = compat_ptr(igc_cfg_payload_32.c0_c1_data); + igc_cfg_payload.c2_data = compat_ptr(igc_cfg_payload_32.c2_data); + igc_cfg_payload.len = igc_cfg_payload_32.len; +@@ -1261,6 +1264,7 @@ static int __from_user_pgc_lut_data_v1_7( + pr_err("failed to copy from user the pgc32 payload\n"); + return -EFAULT; + } ++ memset(&pgc_cfg_payload, 0, sizeof(pgc_cfg_payload)); + pgc_cfg_payload.c0_data = compat_ptr(pgc_cfg_payload_32.c0_data); + pgc_cfg_payload.c1_data = compat_ptr(pgc_cfg_payload_32.c1_data); + pgc_cfg_payload.c2_data = compat_ptr(pgc_cfg_payload_32.c2_data); +@@ -1470,6 +1474,7 @@ static int __from_user_hist_lut_data_v1_7( + return -EFAULT; + } + ++ memset(&hist_lut_cfg_payload, 0, sizeof(hist_lut_cfg_payload)); + hist_lut_cfg_payload.len = hist_lut_cfg_payload32.len; + hist_lut_cfg_payload.data = compat_ptr(hist_lut_cfg_payload32.data); + +@@ -2024,6 +2029,7 @@ static int __from_user_pa_data_v1_7( + return -EFAULT; + } + ++ memset(&pa_cfg_payload, 0, sizeof(pa_cfg_payload)); + pa_cfg_payload.mode = pa_cfg_payload32.mode; + pa_cfg_payload.global_hue_adj = pa_cfg_payload32.global_hue_adj; + pa_cfg_payload.global_sat_adj = pa_cfg_payload32.global_sat_adj; +@@ -2280,6 +2286,8 @@ static int __from_user_gamut_cfg_data_v17( + pr_err("failed to copy the gamut payload from userspace\n"); + return -EFAULT; + } ++ ++ memset(&gamut_cfg_payload, 0, sizeof(gamut_cfg_payload)); + gamut_cfg_payload.mode = gamut_cfg_payload32.mode; + for (i = 0; i < MDP_GAMUT_TABLE_NUM_V1_7; i++) { + gamut_cfg_payload.tbl_size[i] = +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0536/0.patch b/Patches/Linux_CVEs/CVE-2017-0536/0.patch new file mode 100644 index 00000000..24e8b2ed --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0536/0.patch @@ -0,0 +1,91 @@ +From e6430a4da1fb0212a546379eadbe986f629c3ae9 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Fri, 13 Jan 2017 11:41:03 -0800 +Subject: [PATCH] input: synaptics_dsx: protect tmpbuf allocation. + +Protect tmpbuf from concurrent access by mutex. + +BUG: 33555878 +BUG: 33002026 +Change-Id: Ia7eeb59ca7b626f416e2298b4b9ffd960fe909e4 +Signed-off-by: Andrew Chant +--- + .../synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c | 36 ++++++++++++++-------- + 1 file changed, 24 insertions(+), 12 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c +index e699dfea50c81..6878b71da9be0 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c ++++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_rmi_dev.c +@@ -565,18 +565,24 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf, + return -EBADF; + } + +- if (count == 0) +- return 0; ++ mutex_lock(&(dev_data->file_mutex)); ++ ++ if (*f_pos > REG_ADDR_LIMIT) { ++ retval = -EFAULT; ++ goto clean_up; ++ } + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + ++ if (count == 0) { ++ retval = 0; ++ goto clean_up; ++ } + address = (unsigned short)(*f_pos); + + rmidev_allocate_buffer(count); + +- mutex_lock(&(dev_data->file_mutex)); +- + retval = synaptics_rmi4_reg_read(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, +@@ -636,19 +642,25 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + return -EBADF; + } + +- if (count == 0) +- return 0; ++ mutex_lock(&(dev_data->file_mutex)); + ++ if (*f_pos > REG_ADDR_LIMIT) { ++ retval = -EFAULT; ++ goto unlock; ++ } + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; ++ if (count == 0) { ++ retval = 0; ++ goto unlock; ++ } + + rmidev_allocate_buffer(count); + +- if (copy_from_user(rmidev->tmpbuf, buf, count)) +- return -EFAULT; +- +- mutex_lock(&(dev_data->file_mutex)); +- ++ if (copy_from_user(rmidev->tmpbuf, buf, count)) { ++ retval = -EFAULT; ++ goto unlock; ++ } + retval = synaptics_rmi4_reg_write(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, +@@ -656,8 +668,8 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf, + if (retval >= 0) + *f_pos += retval; + ++unlock: + mutex_unlock(&(dev_data->file_mutex)); +- + return retval; + } + diff --git a/Patches/Linux_CVEs/CVE-2017-0537/0.patch b/Patches/Linux_CVEs/CVE-2017-0537/0.patch new file mode 100644 index 00000000..9e080cd4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0537/0.patch @@ -0,0 +1,94 @@ +From 389b185cb2f17fff994dbdf8d4bac003d4b2b6b3 Mon Sep 17 00:00:00 2001 +From: Jim Lin +Date: Fri, 13 Jan 2017 16:07:58 +0800 +Subject: FROMLIST: CHROMIUM: usb: gadget: configfs: Fix KASAN use-after-free + +When gadget is disconnected, running sequence is like this. +. android_work: sent uevent USB_STATE=DISCONNECTED +. Call trace: + usb_string_copy+0xd0/0x128 + gadget_config_name_configuration_store+0x4 + gadget_config_name_attr_store+0x40/0x50 + configfs_write_file+0x198/0x1f4 + vfs_write+0x100/0x220 + SyS_write+0x58/0xa8 +. configfs_composite_unbind +. configfs_composite_bind + +In configfs_composite_bind, it has +"cn->strings.s = cn->configuration;" + +When usb_string_copy is invoked. it would +allocate memory, copy input string, release previous pointed memory space, +and use new allocated memory. + +When gadget is connected, host sends down request to get information. +Call trace: + usb_gadget_get_string+0xec/0x168 + lookup_string+0x64/0x98 + composite_setup+0xa34/0x1ee8 + android_setup+0xb4/0x140 + +If gadget is disconnected and connected quickly, in the failed case, +cn->configuration memory has been released by usb_string_copy kfree but +configfs_composite_bind hasn't been run in time to assign new allocated +"cn->configuration" pointer to "cn->strings.s". + +When "strlen(s->s) of usb_gadget_get_string is being executed, the dangling +memory is accessed, "BUG: KASAN: use-after-free" error occurs. + +BUG=chrome-os-partner:58412 +TEST=After smaug device was connected to ubuntu PC host, detached and attached +type-C cable quickly several times without seeing +"BUG: KASAN: use-after-free in usb_gadget_get_string". + +Bug: 31614969 +Change-Id: I58240ee7c55ae8f8fb8597d14f09c5ac07abb032 +Signed-off-by: Jim Lin +Signed-off-by: Siqi Lin +(am from https://chromium-review.googlesource.com/#/c/428059/3) +--- + drivers/usb/gadget/configfs.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c +index c484d9a..f7d8a3d 100644 +--- a/drivers/usb/gadget/configfs.c ++++ b/drivers/usb/gadget/configfs.c +@@ -130,21 +130,28 @@ struct gadget_config_name { + struct list_head list; + }; + ++#define MAX_USB_STRING_LEN 126 ++#define MAX_USB_STRING_WITH_NULL_LEN (MAX_USB_STRING_LEN+1) ++ + static int usb_string_copy(const char *s, char **s_copy) + { + int ret; + char *str; + char *copy = *s_copy; + ret = strlen(s); +- if (ret > 126) ++ if (ret > MAX_USB_STRING_LEN) + return -EOVERFLOW; + +- str = kstrdup(s, GFP_KERNEL); +- if (!str) +- return -ENOMEM; ++ if (copy) { ++ str = copy; ++ } else { ++ str = kmalloc(MAX_USB_STRING_WITH_NULL_LEN, GFP_KERNEL); ++ if (!str) ++ return -ENOMEM; ++ } ++ strncpy(str, s, MAX_USB_STRING_WITH_NULL_LEN); + if (str[ret - 1] == '\n') + str[ret - 1] = '\0'; +- kfree(copy); + *s_copy = str; + return 0; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0564/0.patch b/Patches/Linux_CVEs/CVE-2017-0564/0.patch new file mode 100644 index 00000000..c58ee33a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0564/0.patch @@ -0,0 +1,157 @@ +From 941a80cf3340804e488c6ee2742e7a771bd01272 Mon Sep 17 00:00:00 2001 +From: Daniel Rosenberg +Date: Fri, 3 Feb 2017 20:37:06 -0800 +Subject: [PATCH] ANDROID: ion: Protect kref from userspace manipulation + +This separates the kref for ion handles into two components. +Userspace requests through the ioctl will hold at most one +reference to the internally used kref. All additional requests +will increment a separate counter, and the original reference is +only put once that counter hits 0. This protects the kernel from +a poorly behaving userspace. + +Bug: 34276203 + +Change-Id: Ibc36bc4405788ed0fea7337b541cad3be2b934c0 +Signed-off-by: Daniel Rosenberg +--- + drivers/staging/android/ion/ion.c | 83 +++++++++++++++++++++++++++++++++++---- + 1 file changed, 76 insertions(+), 7 deletions(-) + +diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c +index 73fc9fd4c3e82..fdf761f623201 100755 +--- a/drivers/staging/android/ion/ion.c ++++ b/drivers/staging/android/ion/ion.c +@@ -114,6 +114,7 @@ struct ion_client { + */ + struct ion_handle { + struct kref ref; ++ unsigned int user_ref_count; + struct ion_client *client; + struct ion_buffer *buffer; + struct rb_node node; +@@ -437,6 +438,48 @@ int ion_handle_put(struct ion_handle *handle) + return ret; + } + ++/* Must hold the client lock */ ++static void user_ion_handle_get(struct ion_handle *handle) ++{ ++ if (handle->user_ref_count++ == 0) ++ kref_get(&handle->ref); ++} ++ ++/* Must hold the client lock */ ++static struct ion_handle *user_ion_handle_get_check_overflow(struct ion_handle *handle) ++{ ++ if (handle->user_ref_count + 1 == 0) ++ return ERR_PTR(-EOVERFLOW); ++ user_ion_handle_get(handle); ++ return handle; ++} ++ ++/* passes a kref to the user ref count. ++ * We know we're holding a kref to the object before and ++ * after this call, so no need to reverify handle. */ ++static struct ion_handle *pass_to_user(struct ion_handle *handle) ++{ ++ struct ion_client *client = handle->client; ++ struct ion_handle *ret; ++ ++ mutex_lock(&client->lock); ++ ret = user_ion_handle_get_check_overflow(handle); ++ ion_handle_put_nolock(handle); ++ mutex_unlock(&client->lock); ++ return ret; ++} ++ ++/* Must hold the client lock */ ++static int user_ion_handle_put_nolock(struct ion_handle *handle) ++{ ++ int ret; ++ ++ if (--handle->user_ref_count == 0) ++ ret = ion_handle_put_nolock(handle); ++ ++ return ret; ++} ++ + static struct ion_handle *ion_handle_lookup(struct ion_client *client, + struct ion_buffer *buffer) + { +@@ -648,6 +691,25 @@ static void ion_free_nolock(struct ion_client *client, struct ion_handle *handle + ion_handle_put_nolock(handle); + } + ++/* Must hold the client lock */ ++static void user_ion_free_nolock(struct ion_client *client, struct ion_handle *handle) ++{ ++ bool valid_handle; ++ ++ BUG_ON(client != handle->client); ++ ++ valid_handle = ion_handle_validate(client, handle); ++ if (!valid_handle) { ++ WARN(1, "%s: invalid handle passed to free.\n", __func__); ++ return; ++ } ++ if (handle->user_ref_count == 0) { ++ WARN(1, "%s: User does not have access!\n", __func__); ++ return; ++ } ++ user_ion_handle_put_nolock(handle); ++} ++ + void ion_free(struct ion_client *client, struct ion_handle *handle) + { + BUG_ON(client != handle->client); +@@ -1513,7 +1575,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + data.allocation.flags, true); + if (IS_ERR(handle)) + return PTR_ERR(handle); +- ++ pass_to_user(handle); + data.allocation.handle = handle->id; + + cleanup_handle = handle; +@@ -1529,7 +1591,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + mutex_unlock(&client->lock); + return PTR_ERR(handle); + } +- ion_free_nolock(client, handle); ++ user_ion_free_nolock(client, handle); + ion_handle_put_nolock(handle); + mutex_unlock(&client->lock); + break; +@@ -1553,10 +1615,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + struct ion_handle *handle; + + handle = ion_import_dma_buf(client, data.fd.fd); +- if (IS_ERR(handle)) ++ if (IS_ERR(handle)) { + ret = PTR_ERR(handle); +- else +- data.handle.handle = handle->id; ++ } else { ++ handle = pass_to_user(handle); ++ if (IS_ERR(handle)) ++ ret = PTR_ERR(handle); ++ else ++ data.handle.handle = handle->id; ++ } + break; + } + case ION_IOC_SYNC: +@@ -1588,8 +1655,10 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + if (dir & _IOC_READ) { + if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) { + if (cleanup_handle) { +- ion_free(client, cleanup_handle); +- ion_handle_put(cleanup_handle); ++ mutex_lock(&client->lock); ++ user_ion_free_nolock(client, cleanup_handle); ++ ion_handle_put_nolock(cleanup_handle); ++ mutex_unlock(&client->lock); + } + return -EFAULT; + } diff --git a/Patches/Linux_CVEs/CVE-2017-0568/0.patch b/Patches/Linux_CVEs/CVE-2017-0568/0.patch new file mode 100644 index 00000000..6cc32e48 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0568/0.patch @@ -0,0 +1,79 @@ +From b7fb46c77af4623291f53a5453df733b8fb1fe18 Mon Sep 17 00:00:00 2001 +From: Sudhir Kohalli +Date: Fri, 20 Jan 2017 17:32:53 -0800 +Subject: [PATCH] net: wireless: bcmdhd: Heap overflow in wl_run_escan. + +1) The default_chan_list buffer overflow is avoided by checking +n_nodfs index does not exceed num_chans, which is the length +of default_chan_list buffer. +2) The SSID length check 32(max limit) is done and then the SSID +name copied in extra buffer is null terminated. The extra buffer +is allocated a length of of 33 in wl_iw_ioctl.c. +3) Issue of chances of cumulative results->pkt_count length +exceeding allocated memory length of results->total_count is +avoided in this fix. change_array is the destination array +whose length is allocated to results->total_count. + +Signed-off-by: Sudhir Kohalli + +Bug: 34197514 +Bug: 34199963 +Bug: 34198729 + +Change-Id: I0cd268ab696daac938a99f451607a3f4b2cfaed3 +--- + drivers/net/wireless/bcmdhd/dhd_pno.c | 12 +++++++++++- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 9 ++++++++- + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index ec2c347ca6219..95bfe2729855f 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -3622,7 +3622,17 @@ void * dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_ + } + + change_array = ¶ms->change_array[params->results_rxed_so_far]; +- memcpy(change_array, results->list, sizeof(wl_pfn_significant_net_t) * results->pkt_count); ++ if ((params->results_rxed_so_far + results->pkt_count) > ++ results->total_count) { ++ DHD_ERROR(("Error: Invalid data reset the counters!!\n")); ++ *send_evt_bytes = 0; ++ kfree(params->change_array); ++ params->change_array = NULL; ++ return ptr; ++ } ++ ++ memcpy(change_array, results->list, ++ sizeof(wl_pfn_significant_net_t) * results->pkt_count); + params->results_rxed_so_far += results->pkt_count; + + if (params->results_rxed_so_far == results->total_count) { +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index 6cadcb56582be..063d49015e5a6 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -2288,6 +2288,9 @@ wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev, + /* allows only supported channel on + * current reguatory + */ ++ if (n_nodfs >= num_chans) ++ break; ++ + if (channel == (dtoh32(list->element[j]))) + default_chan_list[n_nodfs++] = + channel; +@@ -9315,8 +9318,12 @@ wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + struct wiphy *wiphy = bcmcfg_to_wiphy(cfg); + #endif /* GSCAN_SUPPORT */ + +- WL_ERR((">>> PNO Event\n")); ++ if (!data) { ++ WL_ERR(("Data is NULL!\n")); ++ return 0; ++ } + ++ WL_DBG((">>> PNO Event\n")); + ndev = cfgdev_to_wlc_ndev(cfgdev, cfg); + + #ifdef GSCAN_SUPPORT diff --git a/Patches/Linux_CVEs/CVE-2017-0568/1.patch b/Patches/Linux_CVEs/CVE-2017-0568/1.patch new file mode 100644 index 00000000..599e4f30 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0568/1.patch @@ -0,0 +1,35 @@ +From a3f3e7ed54aaa4f5f6929f1ed460363fdc8964d6 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Fri, 13 Jan 2017 16:25:59 -0800 +Subject: [PATCH] net: wireless: bcmdhd: fix overrun in wl_run_escan + +prevent buffer overrun case where WLC_GET_VALID_CHANNELS IOCTL + overriden by attacker and its return manipulated. + +Signed-off-by: Insun Song +Change-Id: Ifbbaa3c2bdfd9bea7533d605303f18e17c8d85cc +Bug: 34197514 +--- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index 41d07d310a7b2..c635b1b8a79af 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -2268,6 +2268,15 @@ wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev, + if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) { + list = (wl_uint32_list_t *) chan_buf; + n_valid_chan = dtoh32(list->count); ++ ++ if (n_valid_chan > WL_NUMCHANNELS) { ++ WL_ERR(("wrong n_valid_chan:%d\n", ++ n_valid_chan)); ++ kfree(default_chan_list); ++ err = -EINVAL; ++ goto exit; ++ } ++ + for (i = 0; i < num_chans; i++) + { + _freq = request->channels[i]->center_freq; diff --git a/Patches/Linux_CVEs/CVE-2017-0569/0.patch b/Patches/Linux_CVEs/CVE-2017-0569/0.patch new file mode 100644 index 00000000..6cc32e48 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0569/0.patch @@ -0,0 +1,79 @@ +From b7fb46c77af4623291f53a5453df733b8fb1fe18 Mon Sep 17 00:00:00 2001 +From: Sudhir Kohalli +Date: Fri, 20 Jan 2017 17:32:53 -0800 +Subject: [PATCH] net: wireless: bcmdhd: Heap overflow in wl_run_escan. + +1) The default_chan_list buffer overflow is avoided by checking +n_nodfs index does not exceed num_chans, which is the length +of default_chan_list buffer. +2) The SSID length check 32(max limit) is done and then the SSID +name copied in extra buffer is null terminated. The extra buffer +is allocated a length of of 33 in wl_iw_ioctl.c. +3) Issue of chances of cumulative results->pkt_count length +exceeding allocated memory length of results->total_count is +avoided in this fix. change_array is the destination array +whose length is allocated to results->total_count. + +Signed-off-by: Sudhir Kohalli + +Bug: 34197514 +Bug: 34199963 +Bug: 34198729 + +Change-Id: I0cd268ab696daac938a99f451607a3f4b2cfaed3 +--- + drivers/net/wireless/bcmdhd/dhd_pno.c | 12 +++++++++++- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 9 ++++++++- + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index ec2c347ca6219..95bfe2729855f 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -3622,7 +3622,17 @@ void * dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_ + } + + change_array = ¶ms->change_array[params->results_rxed_so_far]; +- memcpy(change_array, results->list, sizeof(wl_pfn_significant_net_t) * results->pkt_count); ++ if ((params->results_rxed_so_far + results->pkt_count) > ++ results->total_count) { ++ DHD_ERROR(("Error: Invalid data reset the counters!!\n")); ++ *send_evt_bytes = 0; ++ kfree(params->change_array); ++ params->change_array = NULL; ++ return ptr; ++ } ++ ++ memcpy(change_array, results->list, ++ sizeof(wl_pfn_significant_net_t) * results->pkt_count); + params->results_rxed_so_far += results->pkt_count; + + if (params->results_rxed_so_far == results->total_count) { +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index 6cadcb56582be..063d49015e5a6 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -2288,6 +2288,9 @@ wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev, + /* allows only supported channel on + * current reguatory + */ ++ if (n_nodfs >= num_chans) ++ break; ++ + if (channel == (dtoh32(list->element[j]))) + default_chan_list[n_nodfs++] = + channel; +@@ -9315,8 +9318,12 @@ wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + struct wiphy *wiphy = bcmcfg_to_wiphy(cfg); + #endif /* GSCAN_SUPPORT */ + +- WL_ERR((">>> PNO Event\n")); ++ if (!data) { ++ WL_ERR(("Data is NULL!\n")); ++ return 0; ++ } + ++ WL_DBG((">>> PNO Event\n")); + ndev = cfgdev_to_wlc_ndev(cfgdev, cfg); + + #ifdef GSCAN_SUPPORT diff --git a/Patches/Linux_CVEs/CVE-2017-0570/0.patch b/Patches/Linux_CVEs/CVE-2017-0570/0.patch new file mode 100644 index 00000000..6cc32e48 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0570/0.patch @@ -0,0 +1,79 @@ +From b7fb46c77af4623291f53a5453df733b8fb1fe18 Mon Sep 17 00:00:00 2001 +From: Sudhir Kohalli +Date: Fri, 20 Jan 2017 17:32:53 -0800 +Subject: [PATCH] net: wireless: bcmdhd: Heap overflow in wl_run_escan. + +1) The default_chan_list buffer overflow is avoided by checking +n_nodfs index does not exceed num_chans, which is the length +of default_chan_list buffer. +2) The SSID length check 32(max limit) is done and then the SSID +name copied in extra buffer is null terminated. The extra buffer +is allocated a length of of 33 in wl_iw_ioctl.c. +3) Issue of chances of cumulative results->pkt_count length +exceeding allocated memory length of results->total_count is +avoided in this fix. change_array is the destination array +whose length is allocated to results->total_count. + +Signed-off-by: Sudhir Kohalli + +Bug: 34197514 +Bug: 34199963 +Bug: 34198729 + +Change-Id: I0cd268ab696daac938a99f451607a3f4b2cfaed3 +--- + drivers/net/wireless/bcmdhd/dhd_pno.c | 12 +++++++++++- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 9 ++++++++- + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index ec2c347ca6219..95bfe2729855f 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -3622,7 +3622,17 @@ void * dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_ + } + + change_array = ¶ms->change_array[params->results_rxed_so_far]; +- memcpy(change_array, results->list, sizeof(wl_pfn_significant_net_t) * results->pkt_count); ++ if ((params->results_rxed_so_far + results->pkt_count) > ++ results->total_count) { ++ DHD_ERROR(("Error: Invalid data reset the counters!!\n")); ++ *send_evt_bytes = 0; ++ kfree(params->change_array); ++ params->change_array = NULL; ++ return ptr; ++ } ++ ++ memcpy(change_array, results->list, ++ sizeof(wl_pfn_significant_net_t) * results->pkt_count); + params->results_rxed_so_far += results->pkt_count; + + if (params->results_rxed_so_far == results->total_count) { +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index 6cadcb56582be..063d49015e5a6 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -2288,6 +2288,9 @@ wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev, + /* allows only supported channel on + * current reguatory + */ ++ if (n_nodfs >= num_chans) ++ break; ++ + if (channel == (dtoh32(list->element[j]))) + default_chan_list[n_nodfs++] = + channel; +@@ -9315,8 +9318,12 @@ wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + struct wiphy *wiphy = bcmcfg_to_wiphy(cfg); + #endif /* GSCAN_SUPPORT */ + +- WL_ERR((">>> PNO Event\n")); ++ if (!data) { ++ WL_ERR(("Data is NULL!\n")); ++ return 0; ++ } + ++ WL_DBG((">>> PNO Event\n")); + ndev = cfgdev_to_wlc_ndev(cfgdev, cfg); + + #ifdef GSCAN_SUPPORT diff --git a/Patches/Linux_CVEs/CVE-2017-0571/0.patch b/Patches/Linux_CVEs/CVE-2017-0571/0.patch new file mode 100644 index 00000000..d1ac526c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0571/0.patch @@ -0,0 +1,27 @@ +From 4b29d0111186ebef75a9af7da8257697386ac4a4 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Wed, 25 Jan 2017 11:41:49 -0800 +Subject: [PATCH] net: wireless: bcmdhd: fix buffer overrun in wlfc reordering + +added boundary check not to override allocated buffer + +Signed-off-by: Insun Song +Change-Id: Iad44141ba4e4cd224eda292c05ffe525bf74227d +Bug: 34203305 +--- + drivers/net/wireless/bcmdhd/dhd_wlfc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.c b/drivers/net/wireless/bcmdhd/dhd_wlfc.c +index 741ebc8642275..3b9cfe85f7635 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_wlfc.c ++++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.c +@@ -2458,7 +2458,7 @@ static void + _dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len) + { + if (info_len) { +- if (info_buf) { ++ if (info_buf && (len <= WLHOST_REORDERDATA_TOTLEN)) { + bcopy(val, info_buf, len); + *info_len = len; + } diff --git a/Patches/Linux_CVEs/CVE-2017-0572/0.patch b/Patches/Linux_CVEs/CVE-2017-0572/0.patch new file mode 100644 index 00000000..bc7e20a9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0572/0.patch @@ -0,0 +1,60 @@ +From 3afb019c44d750086f8d5228f8c934da2910d8df Mon Sep 17 00:00:00 2001 +From: gwx419604 +Date: Mon, 20 Mar 2017 15:11:22 +0800 +Subject: [PATCH] net: wireless: bcmdhd: fix buffer overrun in + dhd_pno_process_anqpo_result + +CVE-2017-0572 + +added boundary check not to overflow buffer +especially when input parameters manipulated. + + +Bug: 34198931 +Change-Id: I39d7dc38a597a938d37dbd7bb267a7ff4df93e45 +Signed-off-by: Insun Song +Signed-off-by: gwx419604 +--- + drivers/net/wireless/bcmdhd/dhd_pno.c | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index f3f2a6f2e7aac..ab9bede10e30d 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -3631,8 +3631,8 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, int *size) + u32 bi_length = 0; + uint8 channel; + uint32 mem_needed; +- + struct timespec ts; ++ wl_event_gas_t *gas_data; + + *size = 0; + +@@ -3653,9 +3653,22 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, int *size) + DHD_ERROR(("Invalid bss_info length %d: ignoring\n", bi_length)); + goto exit; + } +- if (bi->SSID_len > DOT11_MAX_SSID_LEN) { +- DHD_ERROR(("Invalid SSID length %d: trimming it to max\n", bi->SSID_len)); +- bi->SSID_len = DOT11_MAX_SSID_LEN; ++ if ((bi->SSID_len > DOT11_MAX_SSID_LEN)|| ++ (bi->ie_length > (*size - sizeof(wl_bss_info_t))) || ++ (bi->ie_offset < sizeof(wl_bss_info_t)) || ++ (bi->ie_offset > (sizeof(wl_bss_info_t) + bi->ie_length))){ ++ DHD_ERROR(("%s: tot:%d,SSID:%d,ie_len:%d,ie_off:%d\n", ++ __FUNCTION__, *size, bi->SSID_len, ++ bi->ie_length, bi->ie_offset)); ++ return NULL; ++ } ++ ++ gas_data = (wl_event_gas_t *)((uint8 *)data + bi->ie_offset + bi->ie_length); ++ ++ if (gas_data->data_len > (*size - (bi->ie_offset + bi->ie_length))) { ++ DHD_ERROR(("%s: wrong gas_data_len:%d\n", ++ __FUNCTION__, gas_data->data_len)); ++ return NULL; + } + + mem_needed = OFFSETOF(wifi_gscan_result_t, ie_data) + bi->ie_length; diff --git a/Patches/Linux_CVEs/CVE-2017-0573/0.patch b/Patches/Linux_CVEs/CVE-2017-0573/0.patch new file mode 100644 index 00000000..cd084634 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0573/0.patch @@ -0,0 +1,53 @@ +From 3d9f2799fd13d1125ab4b3d74a523bd7f2e566f3 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Tue, 31 Jan 2017 16:18:40 -0800 +Subject: [PATCH] net: wireless: bcmdhd: fix buffer overrun in + wl_android_set_roampref + +added boundary check not to override allocated buffer. +Specially when user input corrupted or manipulated. + +Signed-off-by: Insun Song +Change-Id: Id6196da10111517696eda5f186b1e2dd19f66085 +Bug: 34469904 +--- + drivers/net/wireless/bcmdhd/wl_android.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c +index 46b00bd913835..c415bfcba0f6a 100644 +--- a/drivers/net/wireless/bcmdhd/wl_android.c ++++ b/drivers/net/wireless/bcmdhd/wl_android.c +@@ -936,8 +936,8 @@ wl_android_set_roampref(struct net_device *dev, char *command, int total_len) + uint8 buf[MAX_BUF_SIZE]; + uint8 *pref = buf; + char *pcmd; +- int num_ucipher_suites = 0; +- int num_akm_suites = 0; ++ uint num_ucipher_suites; ++ uint num_akm_suites; + wpa_suite_t ucipher_suites[MAX_NUM_SUITES]; + wpa_suite_t akm_suites[MAX_NUM_SUITES]; + int num_tuples = 0; +@@ -950,6 +950,10 @@ wl_android_set_roampref(struct net_device *dev, char *command, int total_len) + total_len_left = total_len - strlen(CMD_SET_ROAMPREF) + 1; + + num_akm_suites = simple_strtoul(pcmd, NULL, 16); ++ if (num_akm_suites > MAX_NUM_SUITES) { ++ WL_ERR(("wrong num_akm_suites:%d.\n", num_akm_suites)); ++ return BCME_ERROR; ++ } + /* Increment for number of AKM suites field + space */ + pcmd += 3; + total_len_left -= 3; +@@ -975,6 +979,10 @@ wl_android_set_roampref(struct net_device *dev, char *command, int total_len) + + total_len_left -= (num_akm_suites * WIDTH_AKM_SUITE); + num_ucipher_suites = simple_strtoul(pcmd, NULL, 16); ++ if (num_ucipher_suites > MAX_NUM_SUITES) { ++ WL_ERR(("wrong num_ucipher_suites:%d.\n", num_ucipher_suites)); ++ return BCME_ERROR; ++ } + /* Increment for number of cipher suites field + space */ + pcmd += 3; + total_len_left -= 3; diff --git a/Patches/Linux_CVEs/CVE-2017-0574/0.patch b/Patches/Linux_CVEs/CVE-2017-0574/0.patch new file mode 100644 index 00000000..cee6f2f8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0574/0.patch @@ -0,0 +1,69 @@ +From e55ddf68568a33288d76f5e00c93f8157cb9a632 Mon Sep 17 00:00:00 2001 +From: Sudhir Kohalli +Date: Fri, 27 Jan 2017 17:14:19 -0800 +Subject: [PATCH] net: wireless: bcmdhd: Fix for arbitrary memory free. + +Fix for arbitrary memory free in nexus6p's wifi driver +function wl_cfgvendor_dbg_get_mem_dump. Current fix +includes intialize mem_buf to NULL and check if the +len is valid or not. Also check if buf_len is valid +or not. If buf_len is not valid then mem_buf will be +set to NULL. + +Signed-off-by: Sudhir Kohalli + +Change-Id: Ia98ce18f0437d38d6f6d77033af7477ae12574e3 +Bug: 34624457 +--- + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 29 ++++++++++++++++++++++++++--- + 1 file changed, 26 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index 9a73de20f1298..1f5152f66ab36 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -2283,7 +2283,7 @@ static int wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy, + int buf_len = 0; + void __user *user_buf = NULL; + const struct nlattr *iter; +- char *mem_buf; ++ char *mem_buf = NULL; + struct sk_buff *skb; + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + +@@ -2291,10 +2291,33 @@ static int wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy, + type = nla_type(iter); + switch (type) { + case DEBUG_ATTRIBUTE_FW_DUMP_LEN: +- buf_len = nla_get_u32(iter); ++ /* Check if the iter is valid and ++ * buffer length is not already initialized. ++ */ ++ if ((nla_len(iter) == sizeof(uint32)) && ++ !buf_len) { ++ buf_len = nla_get_u32(iter); ++ if (buf_len <= 0) { ++ ret = BCME_ERROR; ++ goto exit; ++ } ++ } else { ++ ret = BCME_ERROR; ++ goto exit; ++ } + break; + case DEBUG_ATTRIBUTE_FW_DUMP_DATA: +- user_buf = (void __user *)(unsigned long) nla_get_u64(iter); ++ if (nla_len(iter) != sizeof(uint64)) { ++ WL_ERR(("Invalid len\n")); ++ ret = BCME_ERROR; ++ goto exit; ++ } ++ user_buf = ++ (void __user *)(unsigned long)nla_get_u64(iter); ++ if (!user_buf) { ++ ret = BCME_ERROR; ++ goto exit; ++ } + break; + default: + WL_ERR(("Unknown type: %d\n", type)); diff --git a/Patches/Linux_CVEs/CVE-2017-0575/0.patch b/Patches/Linux_CVEs/CVE-2017-0575/0.patch new file mode 100644 index 00000000..a0f7642f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0575/0.patch @@ -0,0 +1,84 @@ +From 0440277461826c6f2122ef3ffca51358cc823fd2 Mon Sep 17 00:00:00 2001 +From: Ashish Kumar Goswami +Date: Fri, 23 Dec 2016 13:20:45 +0530 +Subject: qcacld-2.0: Avoid integer overflow in wma_enable_arp_ns_offload + +In the function wma_enable_arp_ns_offload(), the len variable is +defined as signed 32 bit, whereas wmi_buf_alloc() takes unsigned +16 bit as input also there is no limit on input of +num_ns_offload_count. + +Fix is to define the len variable in wma_enable_arp_ns_offload() +as unsigned 32 bit. The length input for wmi_buf_alloc() is also +extended and re-defined as unsigned 32 bit. Add limit check before +using num_ns_offload_count. + +Change-Id: I5063df9551074e964eef67abeb8afcf104e50808 +CRs-Fixed: 1103099 +--- + CORE/SERVICES/COMMON/wmi_unified_api.h | 4 ++-- + CORE/SERVICES/WMA/wma.c | 7 ++++++- + CORE/SERVICES/WMI/wmi_unified.c | 2 +- + 3 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/CORE/SERVICES/COMMON/wmi_unified_api.h b/CORE/SERVICES/COMMON/wmi_unified_api.h +index cd9f923..2912d47 100644 +--- a/CORE/SERVICES/COMMON/wmi_unified_api.h ++++ b/CORE/SERVICES/COMMON/wmi_unified_api.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -69,7 +69,7 @@ wmi_unified_remove_work(struct wmi_unified* wmi_handle); + * @return wmi_buf_t. + */ + wmi_buf_t +-wmi_buf_alloc(wmi_unified_t wmi_handle, u_int16_t len); ++wmi_buf_alloc(wmi_unified_t wmi_handle, uint32_t len); + + + /** +diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c +index 6810329..243c2cc 100644 +--- a/CORE/SERVICES/WMA/wma.c ++++ b/CORE/SERVICES/WMA/wma.c +@@ -26726,7 +26726,7 @@ static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, + WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd; + A_UINT8* buf_ptr; + wmi_buf_t buf; +- int32_t len; ++ uint32_t len; + VOS_STATUS status = VOS_STATUS_SUCCESS; + u_int8_t vdev_id; + tpSirHostOffloadReq ns_offload_req; +@@ -26760,6 +26760,11 @@ static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, + count = hostoffloadreq->num_ns_offload_count; + } + ++ if (count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) { ++ status = VOS_STATUS_E_INVAL; ++ goto err_vdev; ++ } ++ + len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) + + WMI_TLV_HDR_SIZE + /* Add size for array of NS tuples */ + WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE) + +diff --git a/CORE/SERVICES/WMI/wmi_unified.c b/CORE/SERVICES/WMI/wmi_unified.c +index b0ace6c..150bd3e 100644 +--- a/CORE/SERVICES/WMI/wmi_unified.c ++++ b/CORE/SERVICES/WMI/wmi_unified.c +@@ -131,7 +131,7 @@ uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle) + } + + wmi_buf_t +-wmi_buf_alloc(wmi_unified_t wmi_handle, u_int16_t len) ++wmi_buf_alloc(wmi_unified_t wmi_handle, uint32_t len) + { + wmi_buf_t wmi_buf; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0575/1.patch b/Patches/Linux_CVEs/CVE-2017-0575/1.patch new file mode 100644 index 00000000..f0da5bab --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0575/1.patch @@ -0,0 +1,91 @@ +From ddc398c5d658b5b33c23dbca617e0d1d021a5c6d Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Tue, 31 Jan 2017 14:32:12 -0800 +Subject: [PATCH] qcacld-2.0: Avoid integer overflow in + wma_enable_arp_ns_offload + +In the function wma_enable_arp_ns_offload(), the len variable is +defined as signed 32 bit, whereas wmi_buf_alloc() takes unsigned +16 bit as input also there is no limit on input of +num_ns_offload_count. + +Fix is to define the len variable in wma_enable_arp_ns_offload() +as unsigned 32 bit. The length input for wmi_buf_alloc() is also +extended and re-defined as unsigned 32 bit. Add limit check before +using num_ns_offload_count. + +Change-Id: I5063df9551074e964eef67abeb8afcf104e50808 +CRs-Fixed: 1103099 +Bug: 32658595 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h | 4 ++-- + drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c | 7 ++++++- + drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c | 4 ++-- + 3 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h +index cd9f923beca83..2912d471158f7 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified_api.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -69,7 +69,7 @@ wmi_unified_remove_work(struct wmi_unified* wmi_handle); + * @return wmi_buf_t. + */ + wmi_buf_t +-wmi_buf_alloc(wmi_unified_t wmi_handle, u_int16_t len); ++wmi_buf_alloc(wmi_unified_t wmi_handle, uint32_t len); + + + /** +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +index 72564ac017ebe..9ca604952e03b 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c +@@ -24576,7 +24576,7 @@ static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, + WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd; + A_UINT8* buf_ptr; + wmi_buf_t buf; +- int32_t len; ++ uint32_t len; + VOS_STATUS status = VOS_STATUS_SUCCESS; + u_int8_t vdev_id; + tpSirHostOffloadReq ns_offload_req; +@@ -24610,6 +24610,11 @@ static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, + count = hostoffloadreq->num_ns_offload_count; + } + ++ if (count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) { ++ status = VOS_STATUS_E_INVAL; ++ goto err_vdev; ++ } ++ + len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) + + WMI_TLV_HDR_SIZE + /* Add size for array of NS tuples */ + WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE) + +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c +index fe72942417bbc..11107d6a5b6d8 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -131,7 +131,7 @@ uint16_t wmi_get_max_msg_len(wmi_unified_t wmi_handle) + } + + wmi_buf_t +-wmi_buf_alloc(wmi_unified_t wmi_handle, u_int16_t len) ++wmi_buf_alloc(wmi_unified_t wmi_handle, uint32_t len) + { + wmi_buf_t wmi_buf; + diff --git a/Patches/Linux_CVEs/CVE-2017-0576/0.patch b/Patches/Linux_CVEs/CVE-2017-0576/0.patch new file mode 100644 index 00000000..403119ec --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0576/0.patch @@ -0,0 +1,48 @@ +From 2b09507d78b25637df6879cd2ee2031b208b3532 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Thu, 19 Jan 2017 14:59:44 -0800 +Subject: crypto: msm: check integer overflow on total data len in qcedev.c + +qcedev_vbuf_ablk_cipher will calculate total data length. It starts +with the value of "areq->cipher_op_req.byteoffset", which is controlled +by the user. Make change to check if this total data length has integer +overflow issue in qcedev_check_cipher_params. + +Change-Id: Ice42dca6d47eb8febfe8a34e566c69e4799fab57 +Signed-off-by: Zhen Kong +--- + drivers/crypto/msm/qcedev.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c +index 9ab03209b..a629c62 100644 +--- a/drivers/crypto/msm/qcedev.c ++++ b/drivers/crypto/msm/qcedev.c +@@ -1445,6 +1445,15 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, + pr_err("%s: Invalid byte offset\n", __func__); + goto error; + } ++ total = req->byteoffset; ++ for (i = 0; i < req->entries; i++) { ++ if (total > U32_MAX - req->vbuf.src[i].len) { ++ pr_err("%s:Integer overflow on total src len\n", ++ __func__); ++ goto error; ++ } ++ total += req->vbuf.src[i].len; ++ } + } + + if (req->data_len < req->byteoffset) { +@@ -1480,7 +1489,7 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, + } + } + /* Check for sum of all dst length is equal to data_len */ +- for (i = 0; i < req->entries; i++) { ++ for (i = 0, total = 0; i < req->entries; i++) { + if (req->vbuf.dst[i].len >= U32_MAX - total) { + pr_err("%s: Integer overflow on total req dst vbuf length\n", + __func__); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0583/0.patch b/Patches/Linux_CVEs/CVE-2017-0583/0.patch new file mode 100644 index 00000000..e3799be1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0583/0.patch @@ -0,0 +1,45 @@ +From 452d2ad331d20b19e8a0768c4b6e7fe1b65abe8f Mon Sep 17 00:00:00 2001 +From: Bruce Levy +Date: Wed, 27 Jan 2016 17:37:33 -0800 +Subject: defconfig: msm: Disable CONFIG_CP_ACCESS64 + +Disable the cpaccess64 driver. +This driver allows user space access to cpu registers. +With this driver enabled, a CTS test causes the +system to crash. + +CRs-Fixed: 968777 +Change-Id: I3ebe7220c7ca68a25b781c2e836a735d11dcaf08 +Signed-off-by: Bruce Levy +--- + arch/arm64/configs/msm-perf_defconfig | 1 - + arch/arm64/configs/msm_defconfig | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig +index fad17d9..37158e6 100644 +--- a/arch/arm64/configs/msm-perf_defconfig ++++ b/arch/arm64/configs/msm-perf_defconfig +@@ -496,7 +496,6 @@ CONFIG_GPIO_USB_DETECT=y + CONFIG_MSM_SPMI=y + CONFIG_MSM_SPMI_PMIC_ARB=y + CONFIG_MSM_QPNP_INT=y +-CONFIG_CP_ACCESS64=y + CONFIG_MSM_ADSP_LOADER=y + CONFIG_MSM_MEMORY_DUMP_V2=y + CONFIG_MSM_BOOT_STATS=y +diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig +index 6f1e808..80ae314 100644 +--- a/arch/arm64/configs/msm_defconfig ++++ b/arch/arm64/configs/msm_defconfig +@@ -503,7 +503,6 @@ CONFIG_GPIO_USB_DETECT=y + CONFIG_MSM_SPMI=y + CONFIG_MSM_SPMI_PMIC_ARB=y + CONFIG_MSM_QPNP_INT=y +-CONFIG_CP_ACCESS64=y + CONFIG_MSM_ADSP_LOADER=y + CONFIG_MSM_MEMORY_DUMP_V2=y + CONFIG_MSM_BOOT_STATS=y +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0584/0.patch b/Patches/Linux_CVEs/CVE-2017-0584/0.patch new file mode 100644 index 00000000..cbd5fda6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0584/0.patch @@ -0,0 +1,54 @@ +From b83b9057d56c057d1dfca79ae197583a83766245 Mon Sep 17 00:00:00 2001 +From: Govind Singh +Date: Thu, 12 Jan 2017 10:30:25 +0530 +Subject: qcacld-2.0: Do not copy buffer to user-space if diag read fails + +ATH diag procfs read is copying read_buffer to user space +unconditionally, causing kernel heap information leak of +uninitialized read_buffer if hif diag read fails. + +Do not copy buffer to user space if diag read fails to +avoid information leak to user space. + +Change-Id: I5e07cad4f90e5e9b3c461268b8fa3635c3128b9f +CRs-Fixed: 1104731 +--- + CORE/SERVICES/HIF/ath_procfs.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/CORE/SERVICES/HIF/ath_procfs.c b/CORE/SERVICES/HIF/ath_procfs.c +index cfdf97a..d1a34dd 100644 +--- a/CORE/SERVICES/HIF/ath_procfs.c ++++ b/CORE/SERVICES/HIF/ath_procfs.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013, 2016 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013, 2016-2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -113,17 +113,16 @@ static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf, + (A_UINT8 *)read_buffer, count); + } + ++ if (rv) ++ return -EIO; ++ + if(copy_to_user(buf, read_buffer, count)) { + vos_mem_free(read_buffer); + return -EFAULT; + } else + vos_mem_free(read_buffer); + +- if (rv == 0) { +- return count; +- } else { +- return -EIO; +- } ++ return count; + } + + static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0584/1.patch b/Patches/Linux_CVEs/CVE-2017-0584/1.patch new file mode 100644 index 00000000..b3213554 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0584/1.patch @@ -0,0 +1,54 @@ +From 47918a436fa424a5eb81afc6a9eae6ad91b8b366 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Wed, 1 Feb 2017 11:49:43 -0800 +Subject: [PATCH] qcacld-2.0: Do not copy buffer to user-space if diag read + fails + +ATH diag procfs read is copying read_buffer to user space +unconditionally, causing kernel heap information leak of +uninitialized read_buffer if hif diag read fails. + +Do not copy buffer to user space if diag read fails to +avoid information leak to user space. + +Change-Id: I5e07cad4f90e5e9b3c461268b8fa3635c3128b9f +CRs-Fixed: 1104731 +Bug: 32074353 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c +index 7b653a1dd72c8..ed0cfd69d7228 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013, 2016-2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -110,17 +110,16 @@ static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf, + (A_UINT8 *)read_buffer, count); + } + ++ if (rv) ++ return -EIO; ++ + if(copy_to_user(buf, read_buffer, count)) { + vos_mem_free(read_buffer); + return -EFAULT; + } else + vos_mem_free(read_buffer); + +- if (rv == 0) { +- return count; +- } else { +- return -EIO; +- } ++ return count; + } + + static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, diff --git a/Patches/Linux_CVEs/CVE-2017-0586/0.patch b/Patches/Linux_CVEs/CVE-2017-0586/0.patch new file mode 100644 index 00000000..9da502d5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0586/0.patch @@ -0,0 +1,54 @@ +From 05bacdc0f9c16c58326a4be9e88afa870cf1024e Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Thu, 9 Feb 2017 16:04:21 -0800 +Subject: [PATCH] ASoC: msm: qdsp6v2: Fix out-of-bounds access in put functions + +Add out of bounds check in routing put functions +for the mux value before accessing the texts +pointer of soc_enum struct with mux as index. + +CRs-fixed: 1097569 +Bug: 33649808 +Change-Id: Ib9ef8d398f0765754b0f79666963fac043b66077 +Signed-off-by: Karthikeyan Mani +--- + sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + mode change 100755 => 100644 sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +old mode 100755 +new mode 100644 +index 97c914ac35a4a..adbeb77bcb912 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -2272,6 +2272,11 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol, + struct snd_soc_dapm_update *update = NULL; + int valid_port = true; + ++ if (mux >= e->items) { ++ pr_err("%s: Invalid mux value %d\n", __func__, mux); ++ return -EINVAL; ++ } ++ + mutex_lock(&routing_lock); + switch (ucontrol->value.integer.value[0]) { + case 0: +@@ -2439,6 +2444,11 @@ static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol, + uint16_t ext_ec_ref_port_id; + struct snd_soc_dapm_update *update = NULL; + ++ if (mux >= e->items) { ++ pr_err("%s: Invalid mux value %d\n", __func__, mux); ++ return -EINVAL; ++ } ++ + mutex_lock(&routing_lock); + msm_route_ext_ec_ref = ucontrol->value.integer.value[0]; + diff --git a/Patches/Linux_CVEs/CVE-2017-0604/0.patch b/Patches/Linux_CVEs/CVE-2017-0604/0.patch new file mode 100644 index 00000000..8e01dbee --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0604/0.patch @@ -0,0 +1,81 @@ +From 6975e2dd5f37de965093ba3a8a08635a77a960f7 Mon Sep 17 00:00:00 2001 +From: David Keitel +Date: Mon, 20 Apr 2015 15:51:33 -0700 +Subject: bcl: fix allocation for BCL attribute + +The size of the BCL attribute is incorrect due to a precedence bug: + +This was observed while booting with Kernel Address Sanitizer(KASan) enabled. + +============================================================================= +BUG kmalloc-64 (Tainted: G B ): kasan: bad access detected +----------------------------------------------------------------------------- + +INFO: Slab 0xffffffbc0661c6e0 objects=64 used=64 fp=0x (null) flags=0x0080 +INFO: Object 0xffffffc0a360bb00 @offset=2816 fp=0xffffffc0a3454728 + +Bytes b4 ffffffc0a360baf0: 3f 37 9c 1c 00 00 00 00 02 00 02 00 a9 4e ad de ?7...........N.. +Object ffffffc0a360bb00: 28 47 45 a3 c0 ff ff ff 48 47 45 a3 c0 ff ff ff (GE.....HGE..... +Object ffffffc0a360bb10: 68 47 45 a3 c0 ff ff ff 00 00 00 00 00 00 00 00 hGE............. +Object ffffffc0a360bb20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffffffc0a360bb30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +CPU: 0 PID: 1 Comm: swapper/0 Tainted: G B 3.10.49-g465b172-00133-gb931dc1 #134 +Call trace: +[] dump_backtrace+0x0/0x1d4 +[] show_stack+0x10/0x1c +[] dump_stack+0x1c/0x28 +[] print_trailer+0x144/0x158 +[] object_err+0x38/0x4c +[] kasan_report_error+0x210/0x3b0 +[] kasan_report+0x68/0x78 +[] __asan_load8+0x90/0x9c +[] internal_create_group+0x1a0/0x2f4 +[] sysfs_create_group+0x10/0x1c +[] msm_bcl_register_param+0x384/0x450 +[] bcl_probe+0x840/0xb84 +[] spmi_drv_probe+0x2c/0x3c +[] driver_probe_device+0x1f4/0x47c +[] __driver_attach+0x88/0xc0 +[] bus_for_each_dev+0xdc/0x11c +[] driver_attach+0x2c/0x3c +[] bus_add_driver+0x1bc/0x32c +[] driver_register+0x10c/0x1d8 +[] spmi_driver_register+0x98/0xa8 +[] bcl_perph_init+0x2c/0x38 +[] do_one_initcall+0xcc/0x188 +[] kernel_init_freeable+0x1c0/0x264 +[] kernel_init+0x10/0xcc +Memory state around the buggy address: + ffffffc0a360ba00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffffffc0a360ba80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffffffc0a360bb00: 00 00 00 01 fc fc fc fc fc fc fc fc fc fc fc fc + ^ + ffffffc0a360bb80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ffffffc0a360bc00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +================================================================== + +Fix this by adding parantheses to fix precedence. + +CRs-Fixed: 826589 +Change-Id: Ia58b6e52c491b89b10a2b8fe45445372bfe9fa20 +Signed-off-by: David Keitel +--- + drivers/power/msm_bcl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/power/msm_bcl.c b/drivers/power/msm_bcl.c +index d36dfd2..6b7cefd 100644 +--- a/drivers/power/msm_bcl.c ++++ b/drivers/power/msm_bcl.c +@@ -301,7 +301,7 @@ static int bcl_add_sysfs_nodes(enum bcl_param param_type) + return ret; + } + bcl[param_type]->bcl_attr_gp.attrs = kzalloc(sizeof(struct attribute *) +- * BCL_PARAM_MAX_ATTR + 1, GFP_KERNEL); ++ * (BCL_PARAM_MAX_ATTR + 1), GFP_KERNEL); + if (!bcl[param_type]->bcl_attr_gp.attrs) { + pr_err("Sysfs attribute create failed.\n"); + ret = -ENOMEM; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0606/0.patch b/Patches/Linux_CVEs/CVE-2017-0606/0.patch new file mode 100644 index 00000000..7ad60b22 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0606/0.patch @@ -0,0 +1,130 @@ +From d3237316314c3d6f75a58192971f66e3822cd250 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Thu, 26 Jan 2017 15:02:42 -0800 +Subject: drivers: soc: add mutex to prevent response being processed twice + +Add a mutex to prevent two threads from processing the same response +at the same time. This ensures responses are processed completely and +sequentially. + +CRs-Fixed: 1116015 +Change-Id: Id2ef32edb939f8af2850b54bd6f6f447939c0732 +Signed-off-by: Siena Richard +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index 50dd925..10f71b8 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The 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 +@@ -42,6 +42,12 @@ struct voice_svc_prvt { + struct list_head response_queue; + wait_queue_head_t response_wait; + spinlock_t response_lock; ++ /* ++ * This mutex ensures responses are processed in sequential order and ++ * that no two threads access and free the same response at the same ++ * time. ++ */ ++ struct mutex response_mutex_lock; + }; + + struct apr_data { +@@ -467,6 +473,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + goto done; + } + ++ mutex_lock(&prtd->response_mutex_lock); + spin_lock_irqsave(&prtd->response_lock, spin_flags); + + if (list_empty(&prtd->response_queue)) { +@@ -480,7 +487,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + pr_debug("%s: Read timeout\n", __func__); + + ret = -ETIMEDOUT; +- goto done; ++ goto unlock; + } else if (ret > 0 && !list_empty(&prtd->response_queue)) { + pr_debug("%s: Interrupt recieved for response\n", + __func__); +@@ -488,7 +495,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + pr_debug("%s: Interrupted by SIGNAL %d\n", + __func__, ret); + +- goto done; ++ goto unlock; + } + + spin_lock_irqsave(&prtd->response_lock, spin_flags); +@@ -507,7 +514,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + __func__, count, size); + + ret = -ENOMEM; +- goto done; ++ goto unlock; + } + + if (!access_ok(VERIFY_WRITE, arg, size)) { +@@ -515,7 +522,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + __func__); + + ret = -EPERM; +- goto done; ++ goto unlock; + } + + ret = copy_to_user(arg, &resp->resp, +@@ -525,7 +532,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + pr_err("%s: copy_to_user failed %d\n", __func__, ret); + + ret = -EPERM; +- goto done; ++ goto unlock; + } + + spin_lock_irqsave(&prtd->response_lock, spin_flags); +@@ -539,6 +546,8 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + + ret = count; + ++unlock: ++ mutex_unlock(&prtd->response_mutex_lock); + done: + return ret; + } +@@ -594,6 +603,7 @@ static int voice_svc_open(struct inode *inode, struct file *file) + INIT_LIST_HEAD(&prtd->response_queue); + init_waitqueue_head(&prtd->response_wait); + spin_lock_init(&prtd->response_lock); ++ mutex_init(&prtd->response_mutex_lock); + file->private_data = (void *)prtd; + + /* Current APR implementation doesn't support session based +@@ -644,6 +654,7 @@ static int voice_svc_release(struct inode *inode, struct file *file) + pr_err("%s: Failed to dereg MVM %d\n", __func__, ret); + } + ++ mutex_lock(&prtd->response_mutex_lock); + spin_lock_irqsave(&prtd->response_lock, spin_flags); + + while (!list_empty(&prtd->response_queue)) { +@@ -657,6 +668,9 @@ static int voice_svc_release(struct inode *inode, struct file *file) + } + + spin_unlock_irqrestore(&prtd->response_lock, spin_flags); ++ mutex_unlock(&prtd->response_mutex_lock); ++ ++ mutex_destroy(&prtd->response_mutex_lock); + + kfree(file->private_data); + file->private_data = NULL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0607/0.patch b/Patches/Linux_CVEs/CVE-2017-0607/0.patch new file mode 100644 index 00000000..1e82a147 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0607/0.patch @@ -0,0 +1,74 @@ +From b003c8d5407773d3aa28a48c9841e4c124da453d Mon Sep 17 00:00:00 2001 +From: Banajit Goswami +Date: Thu, 3 Nov 2016 19:18:07 -0700 +Subject: ASoC: msm: q6dspv2: use correct variable type to store ION buff size + +The size of the physical memory allocated for ION buffers +are of type size_t. Change updates the type of variables +sent to ION drivers to size_t to avoid any mismatch. + +Change-Id: I3d33ed922b979652c64027e6f1c6f0a8ed4850a3 +Signed-off-by: Banajit Goswami +--- + sound/soc/msm/qdsp6v2/q6asm.c | 10 ++++++---- + sound/soc/msm/qdsp6v2/q6voice.h | 2 +- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c +index 0ea94cb..ea57cda 100644 +--- a/sound/soc/msm/qdsp6v2/q6asm.c ++++ b/sound/soc/msm/qdsp6v2/q6asm.c +@@ -3013,7 +3013,8 @@ int q6asm_set_shared_circ_buff(struct audio_client *ac, + int dir) + { + struct audio_buffer *buf_circ; +- int bytes_to_alloc, rc, len; ++ int bytes_to_alloc, rc; ++ size_t len; + + buf_circ = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL); + +@@ -3032,7 +3033,7 @@ int q6asm_set_shared_circ_buff(struct audio_client *ac, + rc = msm_audio_ion_alloc("audio_client", &buf_circ->client, + &buf_circ->handle, bytes_to_alloc, + (ion_phys_addr_t *)&buf_circ->phys, +- (size_t *)&len, &buf_circ->data); ++ &len, &buf_circ->data); + + if (rc) { + pr_err("%s: Audio ION alloc is failed, rc = %d\n", __func__, +@@ -3074,7 +3075,8 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac, + int dir) + { + struct audio_buffer *buf_pos = &ac->shared_pos_buf; +- int len, rc; ++ int rc; ++ size_t len; + int bytes_to_alloc = sizeof(struct asm_shared_position_buffer); + + mutex_lock(&ac->cmd_lock); +@@ -3083,7 +3085,7 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac, + + rc = msm_audio_ion_alloc("audio_client", &buf_pos->client, + &buf_pos->handle, bytes_to_alloc, +- (ion_phys_addr_t *)&buf_pos->phys, (size_t *)&len, ++ (ion_phys_addr_t *)&buf_pos->phys, &len, + &buf_pos->data); + + if (rc) { +diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h +index 3b3e728..834fe7c 100644 +--- a/sound/soc/msm/qdsp6v2/q6voice.h ++++ b/sound/soc/msm/qdsp6v2/q6voice.h +@@ -142,7 +142,7 @@ struct share_mem_buf { + struct mem_map_table { + dma_addr_t phys; + void *data; +- uint32_t size; /* size of buffer */ ++ size_t size; /* size of buffer */ + struct ion_handle *handle; + struct ion_client *client; + }; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0608/0.patch b/Patches/Linux_CVEs/CVE-2017-0608/0.patch new file mode 100644 index 00000000..0b4299e7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0608/0.patch @@ -0,0 +1,52 @@ +From b66f442dd97c781e873e8f7b248e197f86fd2980 Mon Sep 17 00:00:00 2001 +From: Xiaoyu Ye +Date: Mon, 19 Dec 2016 18:38:53 -0800 +Subject: ASoC: msm: qdsp6v2: Add range checking in msm_dai_q6_set_channel_map + +Range checking is added to prevent buffer overflow that due to inputs +can be set by user space. + +CRs-Fixed: 1098363 +Change-Id: I057261291806240ee6d7b8106a5e83a7665e013d +Signed-off-by: Xiaoyu Ye +--- + sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +index 26cdd0f..fa21ec5 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -1889,6 +1889,11 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, + pr_err("%s: rx slot not found\n", __func__); + return -EINVAL; + } ++ if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) { ++ pr_err("%s: invalid rx num %d\n", __func__, rx_num); ++ return -EINVAL; ++ } ++ + for (i = 0; i < rx_num; i++) { + dai_data->port_config.slim_sch.shared_ch_mapping[i] = + rx_slot[i]; +@@ -1922,6 +1927,11 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, + pr_err("%s: tx slot not found\n", __func__); + return -EINVAL; + } ++ if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) { ++ pr_err("%s: invalid tx num %d\n", __func__, tx_num); ++ return -EINVAL; ++ } ++ + for (i = 0; i < tx_num; i++) { + dai_data->port_config.slim_sch.shared_ch_mapping[i] = + tx_slot[i]; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0609/0.patch b/Patches/Linux_CVEs/CVE-2017-0609/0.patch new file mode 100644 index 00000000..8ae0e3a5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0609/0.patch @@ -0,0 +1,137 @@ +From 38a83df036084c00e8c5a4599c8ee7880b4ee567 Mon Sep 17 00:00:00 2001 +From: Walter Yang +Date: Wed, 21 Dec 2016 14:43:46 +0800 +Subject: ASoC: msm-cpe-lsm: cleanup ioctl functions + +Some of the ioctl command handling is not properly using the +copy_from_user interface. Fix these issues and cleanup the ioctl +functions to make sure there is no illegal memory access. + +CRs-Fixed: 1090482 +Change-Id: Ib18e4b132d3487a3103335768aad5df2ebe13f2d +Signed-off-by: Walter Yang +--- + sound/soc/msm/msm-cpe-lsm.c | 51 +++++++++++++-------------------------------- + 1 file changed, 14 insertions(+), 37 deletions(-) + +diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c +index ef4c9b0..0b77e8c 100644 +--- a/sound/soc/msm/msm-cpe-lsm.c ++++ b/sound/soc/msm/msm-cpe-lsm.c +@@ -1179,13 +1179,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + dev_dbg(rtd->dev, + "%s: %s\n", + __func__, "SNDRV_LSM_REG_SND_MODEL_V2"); +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid argument to ioctl %s\n", +- __func__, +- "SNDRV_LSM_REG_SND_MODEL_V2"); +- return -EINVAL; +- } + + memcpy(&snd_model, arg, + sizeof(struct snd_lsm_sound_model_v2)); +@@ -1328,13 +1321,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + dev_dbg(rtd->dev, + "%s: %s\n", + __func__, "SNDRV_LSM_EVENT_STATUS"); +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid argument to ioctl %s\n", +- __func__, +- "SNDRV_LSM_EVENT_STATUS"); +- return -EINVAL; +- } + + user = arg; + +@@ -1437,12 +1423,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + break; + + case SNDRV_LSM_SET_PARAMS: +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s Invalid argument\n", +- __func__, "SNDRV_LSM_SET_PARAMS"); +- return -EINVAL; +- } + memcpy(&det_params, arg, + sizeof(det_params)); + if (det_params.num_confidence_levels <= 0) { +@@ -2289,12 +2269,6 @@ done: + } + + #ifdef CONFIG_COMPAT +-struct snd_lsm_event_status32 { +- u16 status; +- u16 payload_size; +- u8 payload[0]; +-}; +- + struct snd_lsm_sound_model_v2_32 { + compat_uptr_t data; + compat_uptr_t confidence_level; +@@ -2326,8 +2300,6 @@ struct snd_lsm_module_params_32 { + }; + + enum { +- SNDRV_LSM_EVENT_STATUS32 = +- _IOW('U', 0x02, struct snd_lsm_event_status32), + SNDRV_LSM_REG_SND_MODEL_V2_32 = + _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32), + SNDRV_LSM_SET_PARAMS32 = +@@ -2421,7 +2393,7 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, + err); + } + break; +- case SNDRV_LSM_EVENT_STATUS32: { ++ case SNDRV_LSM_EVENT_STATUS: { + struct snd_lsm_event_status *event_status = NULL; + struct snd_lsm_event_status u_event_status32; + struct snd_lsm_event_status *udata_32 = NULL; +@@ -2463,7 +2435,6 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, + } else { + event_status->payload_size = + u_event_status32.payload_size; +- cmd = SNDRV_LSM_EVENT_STATUS; + err = msm_cpe_lsm_ioctl_shared(substream, + cmd, event_status); + if (err) +@@ -2563,13 +2534,6 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s: No Param data to set\n", +- __func__, "SET_MODULE_PARAMS_32"); +- return -EINVAL; +- } +- + if (copy_from_user(&p_data_32, arg, + sizeof(p_data_32))) { + dev_err(rtd->dev, +@@ -2647,6 +2611,19 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, + kfree(params32); + break; + } ++ case SNDRV_LSM_REG_SND_MODEL_V2: ++ case SNDRV_LSM_SET_PARAMS: ++ case SNDRV_LSM_SET_MODULE_PARAMS: ++ /* ++ * In ideal cases, the compat_ioctl should never be called ++ * with the above unlocked ioctl commands. Print error ++ * and return error if it does. ++ */ ++ dev_err(rtd->dev, ++ "%s: Invalid cmd for compat_ioctl\n", ++ __func__); ++ err = -EINVAL; ++ break; + default: + err = msm_cpe_lsm_ioctl_shared(substream, cmd, arg); + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0610/0.patch b/Patches/Linux_CVEs/CVE-2017-0610/0.patch new file mode 100644 index 00000000..04de703c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0610/0.patch @@ -0,0 +1,34 @@ +From 65009746a6e649779f73d665934561ea983892fe Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Mon, 5 Dec 2016 12:26:52 -0800 +Subject: ASoC: msm: qdsp6v2: return error when copy from userspace fails + +A copy_from_user is not always expected to succeed. Therefore, check +for an error before operating on the buffer post copy. + +Change-Id: Ibba9a47c84e735d30e32eeac5b80d51044b7a9e8 +CRs-Fixed: 1094852 +Signed-off-by: Siena Richard +--- + sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +index 6570819..c444a27 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +@@ -823,6 +823,11 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, + (sizeof(buf_node->frame.frm_hdr) + + sizeof(buf_node->frame.pktlen)); + } ++ if (ret) { ++ pr_err("%s: copy from user failed %d\n", ++ __func__, ret); ++ return -EFAULT; ++ } + spin_lock_irqsave(&prtd->dsp_lock, dsp_flags); + list_add_tail(&buf_node->list, &prtd->in_queue); + spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0610/1.patch b/Patches/Linux_CVEs/CVE-2017-0610/1.patch new file mode 100644 index 00000000..88feecdf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0610/1.patch @@ -0,0 +1,59 @@ +From 2bf336ed7ff29768b63fcf0d9528dd129f516643 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Tue, 31 Jan 2017 12:21:38 -0800 +Subject: ASoC: msm: qdsp6v2: return error when copy from userspace fails + +A copy_from_user is not always expected to succeed. Therefore, check +for an error before operating on the buffer post copy. + +CRs-Fixed: 1116070 +Change-Id: I21032719e6e85f280ca0cda875c84ac8dee8916b +Signed-off-by: Siena Richard +--- + sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +index c444a27..b2387a7 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -814,20 +814,25 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, + if (prtd->mode == MODE_PCM) { + ret = copy_from_user(&buf_node->frame.voc_pkt, + buf, count); ++ if (ret) { ++ pr_err("%s: copy from user failed %d\n", ++ __func__, ret); ++ return -EFAULT; ++ } + buf_node->frame.pktlen = count; + } else { + ret = copy_from_user(&buf_node->frame, + buf, count); ++ if (ret) { ++ pr_err("%s: copy from user failed %d\n", ++ __func__, ret); ++ return -EFAULT; ++ } + if (buf_node->frame.pktlen >= count) + buf_node->frame.pktlen = count - + (sizeof(buf_node->frame.frm_hdr) + + sizeof(buf_node->frame.pktlen)); + } +- if (ret) { +- pr_err("%s: copy from user failed %d\n", +- __func__, ret); +- return -EFAULT; +- } + spin_lock_irqsave(&prtd->dsp_lock, dsp_flags); + list_add_tail(&buf_node->list, &prtd->in_queue); + spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0611/0.patch b/Patches/Linux_CVEs/CVE-2017-0611/0.patch new file mode 100644 index 00000000..8b91f89a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0611/0.patch @@ -0,0 +1,59 @@ +From 1aa5df9246557a98181f03e98530ffd509b954c8 Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Fri, 4 Nov 2016 14:35:58 +0800 +Subject: ASoC: soc: prevent risk of buffer overflow + +In case of large value for bufcnt_t or bufcnt, +cmd_size may overflow. Buffer size allocated by cmd_size might +be not as expected. +Possible buffer overflow could happen. + +CRs-Fixed: 1084210 +Change-Id: I9556f18dd6a9fdf3f76c133ae75c04ecce171f08 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/qdsp6v2/q6asm.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c +index 0ea94cb..fe34f92f 100644 +--- a/sound/soc/msm/qdsp6v2/q6asm.c ++++ b/sound/soc/msm/qdsp6v2/q6asm.c +@@ -5846,7 +5846,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, + struct asm_buffer_node *buffer_node = NULL; + int rc = 0; + int i = 0; +- int cmd_size = 0; ++ uint32_t cmd_size = 0; + uint32_t bufcnt_t; + uint32_t bufsz_t; + +@@ -5868,10 +5868,25 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, + bufsz_t = PAGE_ALIGN(bufsz_t); + } + ++ if (bufcnt_t > (UINT_MAX ++ - sizeof(struct avs_cmd_shared_mem_map_regions)) ++ / sizeof(struct avs_shared_map_region_payload)) { ++ pr_err("%s: Unsigned Integer Overflow. bufcnt_t = %u\n", ++ __func__, bufcnt_t); ++ return -EINVAL; ++ } ++ + cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions) + + (sizeof(struct avs_shared_map_region_payload) + * bufcnt_t); + ++ ++ if (bufcnt > (UINT_MAX / sizeof(struct asm_buffer_node))) { ++ pr_err("%s: Unsigned Integer Overflow. bufcnt = %u\n", ++ __func__, bufcnt); ++ return -EINVAL; ++ } ++ + buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt, + GFP_KERNEL); + if (!buffer_node) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0612/0.patch b/Patches/Linux_CVEs/CVE-2017-0612/0.patch new file mode 100644 index 00000000..208568f4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0612/0.patch @@ -0,0 +1,43 @@ +From 05efafc998dc86c3b75af9803ca71255ddd7a8eb Mon Sep 17 00:00:00 2001 +From: Brahmaji K +Date: Tue, 13 Dec 2016 20:32:24 +0530 +Subject: msm-3.18: drivers : added validation of input/output buffer sizes + +This change fixes issues reagrding the ioctl +QSEECOM_IOCTL_MDTP_CIPHER_DIP_REQ uncovered by fuzzy tests. +Modified handler of above ioctl, not to allow input/output +buffer sizes greater than a fixed defined size. + +Change-Id: I69f94a29d939341564f6f3ebfda48fceaa934542 +Signed-off-by: Brahmaji K +--- + drivers/misc/qseecom.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index baea36b..34b70fd 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -80,6 +80,9 @@ + /* Encrypt/Decrypt Data Integrity Partition (DIP) for MDTP */ + #define SCM_MDTP_CIPHER_DIP 0x01 + ++/* Maximum Allowed Size (128K) of Data Integrity Partition (DIP) for MDTP */ ++#define MAX_DIP 0x20000 ++ + #define RPMB_SERVICE 0x2000 + #define SSD_SERVICE 0x3000 + +@@ -6029,7 +6032,8 @@ static int qseecom_mdtp_cipher_dip(void __user *argp) + } + + if (req.in_buf == NULL || req.out_buf == NULL || +- req.in_buf_size == 0 || req.out_buf_size == 0 || ++ req.in_buf_size == 0 || req.in_buf_size > MAX_DIP || ++ req.out_buf_size == 0 || req.out_buf_size > MAX_DIP || + req.direction > 1) { + pr_err("invalid parameters\n"); + ret = -EINVAL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0613/0.patch b/Patches/Linux_CVEs/CVE-2017-0613/0.patch new file mode 100644 index 00000000..2ceef3d9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0613/0.patch @@ -0,0 +1,217 @@ +From b108c651cae9913da1ab163cb4e5f7f2db87b747 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Wed, 11 Jan 2017 12:12:31 -0800 +Subject: qseecom: improve input validatation for qseecom_send_service_cmd + +Make change to improve input validation on request and response +buffers' address and length for qseecom_send_service_cmd. + +Change-Id: I047e3264333d767541e43b7dadd1727232fd48ef +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 152 ++++++++++++++++++++++++++++--------------------- + 1 file changed, 88 insertions(+), 64 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 20949487..5e37cd6 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -1,6 +1,6 @@ + /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver + * +- * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012-2017, The 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 +@@ -2634,11 +2634,6 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, + return -EINVAL; + } + +- if ((!req_ptr->cmd_req_buf) || (!req_ptr->resp_buf)) { +- pr_err("Invalid req/resp buffer, exiting\n"); +- return -EINVAL; +- } +- + /* Clients need to ensure req_buf is at base offset of shared buffer */ + if ((uintptr_t)req_ptr->cmd_req_buf != + data_ptr->client.user_virt_sb_base) { +@@ -2646,15 +2641,11 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, + return -EINVAL; + } + +- if (((uintptr_t)req_ptr->resp_buf < +- data_ptr->client.user_virt_sb_base) || +- ((uintptr_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"); ++ if (data_ptr->client.sb_length < ++ sizeof(struct qseecom_rpmb_provision_key)) { ++ pr_err("shared buffer is too small to hold key type\n"); + return -EINVAL; + } +- + req_buf = data_ptr->client.sb_virt; + + send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id; +@@ -2681,36 +2672,6 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, + return -EINVAL; + } + +- if (((uintptr_t)req_ptr->cmd_req_buf < +- data_ptr->client.user_virt_sb_base) || +- ((uintptr_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 (((uintptr_t)req_ptr->resp_buf < +- data_ptr->client.user_virt_sb_base) || +- ((uintptr_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; +- } +- +- if ((req_ptr->cmd_req_len == 0) || (req_ptr->resp_len == 0) || +- req_ptr->cmd_req_len > data_ptr->client.sb_length || +- req_ptr->resp_len > data_ptr->client.sb_length) { +- pr_err("cmd buffer length or response buffer length not valid\n"); +- return -EINVAL; +- } +- +- if (req_ptr->cmd_req_len > UINT_MAX - req_ptr->resp_len) { +- pr_err("Integer overflow detected in req_len & rsp_len, exiting now\n"); +- return -EINVAL; +- } +- + reqd_len_sb_in = req_ptr->cmd_req_len + req_ptr->resp_len; + if (reqd_len_sb_in > data_ptr->client.sb_length) { + pr_err("Not enough memory to fit cmd_buf and resp_buf. "); +@@ -2732,28 +2693,11 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, + return ret; + } + +-static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, +- void __user *argp) ++static int __validate_send_service_cmd_inputs(struct qseecom_dev_handle *data, ++ struct qseecom_send_svc_cmd_req *req) + { +- int ret = 0; +- struct qseecom_client_send_service_ireq send_svc_ireq; +- struct qseecom_client_send_fsm_key_req send_fsm_key_svc_ireq; +- struct qseecom_command_scm_resp resp; +- struct qseecom_send_svc_cmd_req req; +- void *send_req_ptr; +- size_t req_buf_size; +- +- /*struct qseecom_command_scm_resp resp;*/ +- +- if (copy_from_user(&req, +- (void __user *)argp, +- sizeof(req))) { +- pr_err("copy_from_user failed\n"); +- return -EFAULT; +- } +- +- if ((req.resp_buf == NULL) || (req.cmd_req_buf == NULL)) { +- pr_err("cmd buffer or response buffer is null\n"); ++ if (!req || !req->resp_buf || !req->cmd_req_buf) { ++ pr_err("req or cmd buffer or response buffer is null\n"); + return -EINVAL; + } + +@@ -2777,6 +2721,86 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, + return -EINVAL; + } + ++ if (((uintptr_t)req->cmd_req_buf < ++ data->client.user_virt_sb_base) || ++ ((uintptr_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 (((uintptr_t)req->resp_buf < ++ data->client.user_virt_sb_base) || ++ ((uintptr_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; ++ } ++ if ((req->cmd_req_len == 0) || (req->resp_len == 0) || ++ (req->cmd_req_len > data->client.sb_length) || ++ (req->resp_len > data->client.sb_length)) { ++ pr_err("cmd buf length or response buf length not valid\n"); ++ return -EINVAL; ++ } ++ if (req->cmd_req_len > UINT_MAX - req->resp_len) { ++ pr_err("Integer overflow detected in req_len & rsp_len\n"); ++ return -EINVAL; ++ } ++ ++ if ((req->cmd_req_len + req->resp_len) > data->client.sb_length) { ++ pr_debug("Not enough memory to fit cmd_buf.\n"); ++ pr_debug("resp_buf. Required: %u, Available: %zu\n", ++ (req->cmd_req_len + req->resp_len), ++ data->client.sb_length); ++ return -ENOMEM; ++ } ++ if ((uintptr_t)req->cmd_req_buf > (ULONG_MAX - req->cmd_req_len)) { ++ pr_err("Integer overflow in req_len & cmd_req_buf\n"); ++ return -EINVAL; ++ } ++ if ((uintptr_t)req->resp_buf > (ULONG_MAX - req->resp_len)) { ++ pr_err("Integer overflow in resp_len & resp_buf\n"); ++ return -EINVAL; ++ } ++ if (data->client.user_virt_sb_base > ++ (ULONG_MAX - data->client.sb_length)) { ++ pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); ++ return -EINVAL; ++ } ++ if ((((uintptr_t)req->cmd_req_buf + req->cmd_req_len) > ++ ((uintptr_t)data->client.user_virt_sb_base + ++ data->client.sb_length)) || ++ (((uintptr_t)req->resp_buf + req->resp_len) > ++ ((uintptr_t)data->client.user_virt_sb_base + ++ data->client.sb_length))) { ++ pr_err("cmd buf or resp buf is out of shared buffer region\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, ++ void __user *argp) ++{ ++ int ret = 0; ++ struct qseecom_client_send_service_ireq send_svc_ireq; ++ struct qseecom_client_send_fsm_key_req send_fsm_key_svc_ireq; ++ struct qseecom_command_scm_resp resp; ++ struct qseecom_send_svc_cmd_req req; ++ void *send_req_ptr; ++ size_t req_buf_size; ++ ++ /*struct qseecom_command_scm_resp resp;*/ ++ ++ if (copy_from_user(&req, ++ (void __user *)argp, ++ sizeof(req))) { ++ pr_err("copy_from_user failed\n"); ++ return -EFAULT; ++ } ++ ++ if (__validate_send_service_cmd_inputs(data, &req)) ++ return -EINVAL; ++ + data->type = QSEECOM_SECURE_SERVICE; + + switch (req.cmd_id) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0614/0.patch b/Patches/Linux_CVEs/CVE-2017-0614/0.patch new file mode 100644 index 00000000..d301f854 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0614/0.patch @@ -0,0 +1,122 @@ +From fc2ae27eb9721a0ce050c2062734fec545cda604 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Thu, 20 Oct 2016 17:34:20 -0700 +Subject: qseecom: check buffer size when loading firmware images + +Make change in __qseecom_load_fw() and qseecom_load_commonlib_image() +to check buffer size before copying img to buffer. + +CRs-fixed: 1080290 +Change-Id: I0f48666ac948a9571e249598ae7cc19df9036b1d +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 32 +++++++++++++++++++++++++++----- + 1 file changed, 27 insertions(+), 5 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 061bc99..dc20841 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -3590,7 +3590,7 @@ static bool __qseecom_is_fw_image_valid(const struct firmware *fw_entry) + return true; + } + +-static int __qseecom_get_fw_size(char *appname, uint32_t *fw_size, ++static int __qseecom_get_fw_size(const char *appname, uint32_t *fw_size, + uint32_t *app_arch) + { + int ret = -1; +@@ -3628,14 +3628,21 @@ static int __qseecom_get_fw_size(char *appname, uint32_t *fw_size, + } + pr_debug("QSEE %s app, arch %u\n", appname, *app_arch); + release_firmware(fw_entry); ++ fw_entry = NULL; + for (i = 0; i < num_images; i++) { + memset(fw_name, 0, sizeof(fw_name)); + snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i); + ret = request_firmware(&fw_entry, fw_name, qseecom.pdev); + if (ret) + goto err; ++ if (*fw_size > U32_MAX - fw_entry->size) { ++ pr_err("QSEE %s app file size overflow\n", appname); ++ ret = -EINVAL; ++ goto err; ++ } + *fw_size += fw_entry->size; + release_firmware(fw_entry); ++ fw_entry = NULL; + } + + return ret; +@@ -3646,8 +3653,9 @@ err: + return ret; + } + +-static int __qseecom_get_fw_data(char *appname, u8 *img_data, +- struct qseecom_load_app_ireq *load_req) ++static int __qseecom_get_fw_data(const char *appname, u8 *img_data, ++ uint32_t fw_size, ++ struct qseecom_load_app_ireq *load_req) + { + int ret = -1; + int i = 0, rc = 0; +@@ -3667,6 +3675,12 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, + } + + load_req->img_len = fw_entry->size; ++ if (load_req->img_len > fw_size) { ++ pr_err("app %s size %zu is larger than buf size %u\n", ++ appname, fw_entry->size, fw_size); ++ ret = -EINVAL; ++ goto err; ++ } + memcpy(img_data_ptr, fw_entry->data, fw_entry->size); + img_data_ptr = img_data_ptr + fw_entry->size; + load_req->mdt_len = fw_entry->size; /*Get MDT LEN*/ +@@ -3685,6 +3699,7 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, + goto err; + } + release_firmware(fw_entry); ++ fw_entry = NULL; + for (i = 0; i < num_images; i++) { + snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d", appname, i); + ret = request_firmware(&fw_entry, fw_name, qseecom.pdev); +@@ -3692,10 +3707,17 @@ static int __qseecom_get_fw_data(char *appname, u8 *img_data, + pr_err("Failed to locate blob %s\n", fw_name); + goto err; + } ++ if ((fw_entry->size > U32_MAX - load_req->img_len) || ++ (fw_entry->size + load_req->img_len > fw_size)) { ++ pr_err("Invalid file size for %s\n", fw_name); ++ ret = -EINVAL; ++ goto err; ++ } + memcpy(img_data_ptr, fw_entry->data, fw_entry->size); + img_data_ptr = img_data_ptr + fw_entry->size; + load_req->img_len += fw_entry->size; + release_firmware(fw_entry); ++ fw_entry = NULL; + } + return ret; + err: +@@ -3800,7 +3822,7 @@ static int __qseecom_load_fw(struct qseecom_dev_handle *data, char *appname) + if (ret) + return ret; + +- ret = __qseecom_get_fw_data(appname, img_data, &load_req); ++ ret = __qseecom_get_fw_data(appname, img_data, fw_size, &load_req); + if (ret) { + ret = -EIO; + goto exit_free_img_data; +@@ -3921,7 +3943,7 @@ static int qseecom_load_commonlib_image(struct qseecom_dev_handle *data, + if (ret) + return -EIO; + +- ret = __qseecom_get_fw_data(cmnlib_name, img_data, &load_req); ++ ret = __qseecom_get_fw_data(cmnlib_name, img_data, fw_size, &load_req); + if (ret) { + ret = -EIO; + goto exit_free_img_data; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0619/0.patch b/Patches/Linux_CVEs/CVE-2017-0619/0.patch new file mode 100644 index 00000000..3fa4fcc0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0619/0.patch @@ -0,0 +1,113 @@ +From 72f67b29a9c5e6e8d3c34751600c749c5f5e13e1 Mon Sep 17 00:00:00 2001 +From: David Keitel +Date: Thu, 16 Apr 2015 16:26:28 -0700 +Subject: pinctrl: msm: fix function name allocation length + +Currently pinctrl driver allocates with the length +following calculation: + + length = strlen(grp_name) + strlen("-func"). + +However, this does not take into account for the string +terminating character which is used in the subsequent +snprintf and causes KASan to trigger a bug report: + +============================================================================= +BUG kmalloc-64 (Tainted: G B ): kasan: bad access detected +----------------------------------------------------------------------------- + +INFO: Slab 0xffffffbc065fb940 objects=64 used=64 fp=0x (null) flags=0x0080 +INFO: Object 0xffffffc0a32c24c0 @offset=1216 fp=0x6365632d696d6468 + +Bytes b4 ffffffc0a32c24b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffffffc0a32c24c0: 68 64 6d 69 2d 63 65 63 2d 70 69 6e 73 2d 66 75 hdmi-cec-pins-fu +Object ffffffc0a32c24d0: 6e 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 nc.............. +Object ffffffc0a32c24e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +Object ffffffc0a32c24f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +CPU: 0 PID: 1 Comm: swapper/0 Tainted: G B 3.10.49-g465b172-00127-g2b70c1d-dirty #119 +Call trace: +[] dump_backtrace+0x0/0x1d4 +[] show_stack+0x10/0x1c +[] dump_stack+0x1c/0x28 +[] print_trailer+0x144/0x158 +[] object_err+0x38/0x4c +[] kasan_report_error+0x210/0x3b0 +[] kasan_report+0x5c/0x68 +[] __asan_store1+0x70/0x7c +[] vsnprintf+0x644/0x69c +[] snprintf+0x94/0xb0 +[] msm_dt_node_to_map+0x2cc/0x378 +[] pinctrl_dt_to_map+0x32c/0x424 +[] pinctrl_get+0x1b0/0x53c +[] devm_pinctrl_get+0x34/0x80 +[] pinctrl_bind_pins+0x44/0x1b4 +[] driver_probe_device+0x188/0x47c +[] __driver_attach+0x88/0xc0 +[] bus_for_each_dev+0xdc/0x11c +[] driver_attach+0x2c/0x3c +[] bus_add_driver+0x1bc/0x32c +[] driver_register+0x10c/0x1d8 +[] platform_driver_register+0x98/0xa8 +[] hdmi_tx_drv_init+0x18/0x4c +[] do_one_initcall+0xcc/0x188 +[] kernel_init_freeable+0x1c0/0x264 +[] kernel_init+0x10/0xcc +Memory state around the buggy address: + ffffffc0a32c2380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffffffc0a32c2400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +>ffffffc0a32c2480: fb fb fb fb fb fb fb fb 00 00 02 fc fc fc fc fc + ^ + ffffffc0a32c2500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffffffc0a32c2580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +================================================================== + +Fix this by increasing the allocation to length + 1 + +CRs-Fixed: 826566 +Change-Id: Ied04500e6b0c0187b2bea0cfaa9adb4080c2f614 +Signed-off-by: David Keitel +Signed-off-by: Stepan Moskovchenko +--- + drivers/pinctrl/msm/pinctrl-msm.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/pinctrl/msm/pinctrl-msm.c b/drivers/pinctrl/msm/pinctrl-msm.c +index b3b97a8..07f7b43 100644 +--- a/drivers/pinctrl/msm/pinctrl-msm.c ++++ b/drivers/pinctrl/msm/pinctrl-msm.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2015, The 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 +@@ -293,6 +293,7 @@ static int msm_dt_node_to_map(struct pinctrl_dev *pctldev, + char *fn_name; + u32 val; + unsigned long *cfg; ++ unsigned int fn_name_len = 0; + int cfg_cnt = 0, map_cnt = 0, func_cnt = 0, ret = 0; + + dd = pinctrl_dev_get_drvdata(pctldev); +@@ -338,14 +339,14 @@ static int msm_dt_node_to_map(struct pinctrl_dev *pctldev, + } + /* Get function mapping */ + of_property_read_u32(parent, "qcom,pin-func", &val); +- fn_name = kzalloc(strlen(grp_name) + strlen("-func"), +- GFP_KERNEL); ++ ++ fn_name_len = strlen(grp_name) + strlen("-func") + 1; ++ fn_name = kzalloc(fn_name_len, GFP_KERNEL); + if (!fn_name) { + ret = -ENOMEM; + goto func_err; + } +- snprintf(fn_name, strlen(grp_name) + strlen("-func") + 1, "%s%s", +- grp_name, "-func"); ++ snprintf(fn_name, fn_name_len, "%s-func", grp_name); + map[*nmaps].data.mux.group = grp_name; + map[*nmaps].data.mux.function = fn_name; + map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0620/0.patch b/Patches/Linux_CVEs/CVE-2017-0620/0.patch new file mode 100644 index 00000000..01ce7bb0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0620/0.patch @@ -0,0 +1,60 @@ +From 01b2c9a5d728ff6f2f1f28a5d4e927aaeabf56ed Mon Sep 17 00:00:00 2001 +From: Satya Durga Srinivasu Prabhala +Date: Tue, 25 Oct 2016 16:35:23 -0700 +Subject: soc: qcom: scm: add check to avoid buffer overflow + +There is a posibility of a buffer overflow in scm_call, +add check to avoid the same. + +Change-Id: Iee908c56ec530569b35dafa060139e0428efc781 +Signed-off-by: Satya Durga Srinivasu Prabhala +--- + drivers/soc/qcom/scm.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c +index 714c848..b4713ac 100644 +--- a/drivers/soc/qcom/scm.c ++++ b/drivers/soc/qcom/scm.c +@@ -56,9 +56,16 @@ DEFINE_MUTEX(scm_lmh_lock); + #define SMC_ATOMIC_MASK 0x80000000 + #define IS_CALL_AVAIL_CMD 1 + +-#define SCM_BUF_LEN(__cmd_size, __resp_size) \ +- (sizeof(struct scm_command) + sizeof(struct scm_response) + \ +- __cmd_size + __resp_size) ++#define SCM_BUF_LEN(__cmd_size, __resp_size) ({ \ ++ size_t x = __cmd_size + __resp_size; \ ++ size_t y = sizeof(struct scm_command) + sizeof(struct scm_response); \ ++ size_t result; \ ++ if (x < __cmd_size || (x + y) < x) \ ++ result = 0; \ ++ else \ ++ result = x + y; \ ++ result; \ ++ }) + /** + * struct scm_command - one SCM command buffer + * @len: total available memory for command and response +@@ -356,8 +363,7 @@ int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf, + int ret; + size_t len = SCM_BUF_LEN(cmd_len, resp_len); + +- if (cmd_len > scm_buf_len || resp_len > scm_buf_len || +- len > scm_buf_len) ++ if (len == 0) + return -EINVAL; + + if (!IS_ALIGNED((unsigned long)scm_buf, PAGE_SIZE)) +@@ -780,7 +786,7 @@ int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, + int ret; + size_t len = SCM_BUF_LEN(cmd_len, resp_len); + +- if (cmd_len > len || resp_len > len) ++ if (len == 0 || PAGE_ALIGN(len) < len) + return -EINVAL; + + cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0621/0.patch b/Patches/Linux_CVEs/CVE-2017-0621/0.patch new file mode 100644 index 00000000..996392f2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0621/0.patch @@ -0,0 +1,33 @@ +From 9656e2c2b3523af20502bf1e933e35a397f5e82f Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Mon, 4 May 2015 12:05:20 -0700 +Subject: msm: camera: sensor: Fix the improper pointer dereference + +Pass flash_ctrl to msm_torch_create_classdev +instead of &flash_ctrl. +This change will fix the improper pointer +dereference issue. msm_torch_create_classdev needs +flash_ctrl pointer to retrieve torch informaiton. + +Change-Id: I05bf130b2161336e93122d7e918a4c48a6b381e2 +Signed-off-by: Rajesh Bondugula +--- + drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +index 864bf63..0faec90 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +@@ -1192,7 +1192,7 @@ static int32_t msm_flash_platform_probe(struct platform_device *pdev) + flash_ctrl->msm_sd.sd.devnode->fops = &msm_flash_v4l2_subdev_fops; + + if (flash_ctrl->flash_driver_type == FLASH_DRIVER_PMIC) +- rc = msm_torch_create_classdev(pdev, &flash_ctrl); ++ rc = msm_torch_create_classdev(pdev, flash_ctrl); + + CDBG("probe success\n"); + return rc; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0622/0.patch b/Patches/Linux_CVEs/CVE-2017-0622/0.patch new file mode 100644 index 00000000..b9a3fed4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0622/0.patch @@ -0,0 +1,51 @@ +From 40efa25345003a96db34effbd23ed39530b3ac10 Mon Sep 17 00:00:00 2001 +From: Vevek Venkatesan +Date: Mon, 23 Jan 2017 18:04:53 +0530 +Subject: input: touchscreen: gt9xx: fix memory corruption in Goodix driver + +Fix memory corruption in Goodix touchscreen driver, by resetting +the global structure cmd_head to zero (except *data and wr flag) +in goodix_tool_write handler on error case. + +Change-Id: I4f7f8f464b93571627b922b10c10a65826228e42 +Signed-off-by: Vevek Venkatesan +--- + drivers/input/touchscreen/gt9xx/goodix_tool.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c +index 762efc9..7ca154a 100644 +--- a/drivers/input/touchscreen/gt9xx/goodix_tool.c ++++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c +@@ -1,7 +1,7 @@ + /* drivers/input/touchscreen/goodix_tool.c + * + * 2010 - 2012 Goodix Technology. +- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2017, The 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 as published by +@@ -309,6 +309,7 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf, + size_t count, loff_t *ppos) + { + s32 ret = 0; ++ u8 *dataptr = NULL; + + mutex_lock(&lock); + ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH); +@@ -468,6 +469,11 @@ static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf, + ret = CMD_HEAD_LENGTH; + + exit: ++ dataptr = cmd_head.data; ++ memset(&cmd_head, 0, sizeof(cmd_head)); ++ cmd_head.wr = 0xFF; ++ cmd_head.data = dataptr; ++ + mutex_unlock(&lock); + return ret; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0626/0.patch b/Patches/Linux_CVEs/CVE-2017-0626/0.patch new file mode 100644 index 00000000..1b33dd65 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0626/0.patch @@ -0,0 +1,159 @@ +From 64551bccab9b5b933757f6256b58f9ca0544f004 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Wed, 9 Nov 2016 16:25:24 -0800 +Subject: msm: crypto: set CLR_CNTXT bit for crypto operations + +HLOS Crypto driver needs to set CLR_CNTXT bit for operations with +legacy software key registers + +Change-Id: Iff482f726d106e99a4006f7077a171da3c7ca9c3 +Signed-off-by: Zhen Kong +--- + drivers/crypto/msm/qce50.c | 47 +++++++++++++++++++++++++--------------------- + 1 file changed, 26 insertions(+), 21 deletions(-) + +diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c +index 3562de7..a8521fd 100644 +--- a/drivers/crypto/msm/qce50.c ++++ b/drivers/crypto/msm/qce50.c +@@ -1347,7 +1347,8 @@ go_proc: + CRYPTO_CONFIG_REG)); + /* issue go to crypto */ + if (use_hw_key == false) { +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + } else { + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +@@ -1528,7 +1529,8 @@ static int _ce_setup_aead_direct(struct qce_device *pce_dev, + + CRYPTO_CONFIG_REG)); + /* issue go to crypto */ +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + /* + * Ensure previous instructions (setting the GO register) +@@ -1847,7 +1849,8 @@ static int _ce_setup_cipher_direct(struct qce_device *pce_dev, + CRYPTO_CONFIG_REG)); + /* issue go to crypto */ + if (use_hw_key == false) { +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + } else { + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +@@ -1935,7 +1938,8 @@ static int _ce_f9_setup_direct(struct qce_device *pce_dev, + QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + + CRYPTO_CONFIG_REG)); + /* write go */ +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + /* + * Ensure previous instructions (setting the GO register) +@@ -2012,7 +2016,8 @@ static int _ce_f8_setup_direct(struct qce_device *pce_dev, + QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + + CRYPTO_CONFIG_REG)); + /* write go */ +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + /* + * Ensure previous instructions (setting the GO register) +@@ -3323,8 +3328,8 @@ static int _setup_cipher_aes_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -3437,8 +3442,8 @@ static int _setup_cipher_des_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -3481,8 +3486,8 @@ static int _setup_cipher_null_cmdlistptrs(struct qce_device *pdev, + NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -3659,8 +3664,8 @@ static int _setup_auth_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -3876,8 +3881,8 @@ static int _setup_aead_cmdlistptrs(struct qce_device *pdev, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -4009,8 +4014,8 @@ static int _setup_aead_ccm_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -4095,8 +4100,8 @@ static int _setup_f8_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -4177,8 +4182,8 @@ static int _setup_f9_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0627/0.patch b/Patches/Linux_CVEs/CVE-2017-0627/0.patch new file mode 100644 index 00000000..16dcf793 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0627/0.patch @@ -0,0 +1,37 @@ +From fcca203d8e6aa0ef22fa41d72a06dea393d6d148 Mon Sep 17 00:00:00 2001 +From: Robb Glasser +Date: Tue, 14 Feb 2017 13:25:46 -0800 +Subject: Prevent heap overflow in uvc driver + +The size of uvc_control_mapping is user controlled leading to a +potential heap overflow in the uvc driver. This adds a check to verify +the user provided size fits within the bounds of the defined buffer +size. + +Bug: 33300353 +Change-Id: If29c1b396633b6137966a12e38f6fd1841b045bd +Signed-off-by: Robb Glasser +Git-repo: https://android.googlesource.com/kernel/msm +Git-commit: 8bc3ec72a02052187397d0de1a7b8bbe7340451c +Signed-off-by: Dennis Cagle +--- + drivers/media/usb/uvc/uvc_ctrl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c +index a2f4501..f61d1d7 100644 +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -1939,6 +1939,9 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, + if (!found) + return -ENOENT; + ++ if (ctrl->info.size < mapping->size) ++ return -EINVAL; ++ + if (mutex_lock_interruptible(&chain->ctrl_mutex)) + return -ERESTARTSYS; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0628/0.patch b/Patches/Linux_CVEs/CVE-2017-0628/0.patch new file mode 100644 index 00000000..2635e7bc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0628/0.patch @@ -0,0 +1,56 @@ +From 012e37bf91490c5b59ba2ab68a4d214b632b613f Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Tue, 8 Nov 2016 11:52:55 -0800 +Subject: msm: camera: sensor: Validate i2c_frq_mode in msm_cci_get_clk_rates + +i2c_freq_mode in msm_cci_get_clk_rates is populated from userspace. +Validate to make sure it has valid values. If a large number is sent +from userspace to avoid a buffer over read. + +Crs-Fixed: 1086833 +Change-Id: I237f60dca3e3dbad4e6188bf047cf7ec5163d159 +Signed-off-by: Rajesh Bondugula +--- + drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c | 12 ++++++++++-- + 1 file changed, 10 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 b1c2382..f113bdc 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 +@@ -115,15 +115,16 @@ static int32_t msm_cci_set_clk_param(struct cci_device *cci_dev, + enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; + enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; + +- clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; +- + if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { + pr_err("%s:%d invalid i2c_freq_mode = %d", + __func__, __LINE__, i2c_freq_mode); + return -EINVAL; + } ++ + if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode) + return 0; ++ ++ clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; + if (MASTER_0 == master) { + msm_camera_io_w_mb(clk_params->hw_thigh << 16 | + clk_params->hw_tlow, +@@ -1196,6 +1197,13 @@ static uint32_t *msm_cci_get_clk_rates(struct cci_device *cci_dev, + struct msm_cci_clk_params_t *clk_params = NULL; + enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; + struct device_node *of_node = cci_dev->pdev->dev.of_node; ++ ++ if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { ++ pr_err("%s:%d invalid i2c_freq_mode %d\n", ++ __func__, __LINE__, i2c_freq_mode); ++ return NULL; ++ } ++ + clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; + cci_clk_src = clk_params->cci_clk_src; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0629/0.patch b/Patches/Linux_CVEs/CVE-2017-0629/0.patch new file mode 100644 index 00000000..2635e7bc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0629/0.patch @@ -0,0 +1,56 @@ +From 012e37bf91490c5b59ba2ab68a4d214b632b613f Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Tue, 8 Nov 2016 11:52:55 -0800 +Subject: msm: camera: sensor: Validate i2c_frq_mode in msm_cci_get_clk_rates + +i2c_freq_mode in msm_cci_get_clk_rates is populated from userspace. +Validate to make sure it has valid values. If a large number is sent +from userspace to avoid a buffer over read. + +Crs-Fixed: 1086833 +Change-Id: I237f60dca3e3dbad4e6188bf047cf7ec5163d159 +Signed-off-by: Rajesh Bondugula +--- + drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c | 12 ++++++++++-- + 1 file changed, 10 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 b1c2382..f113bdc 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 +@@ -115,15 +115,16 @@ static int32_t msm_cci_set_clk_param(struct cci_device *cci_dev, + enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; + enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; + +- clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; +- + if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { + pr_err("%s:%d invalid i2c_freq_mode = %d", + __func__, __LINE__, i2c_freq_mode); + return -EINVAL; + } ++ + if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode) + return 0; ++ ++ clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; + if (MASTER_0 == master) { + msm_camera_io_w_mb(clk_params->hw_thigh << 16 | + clk_params->hw_tlow, +@@ -1196,6 +1197,13 @@ static uint32_t *msm_cci_get_clk_rates(struct cci_device *cci_dev, + struct msm_cci_clk_params_t *clk_params = NULL; + enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; + struct device_node *of_node = cci_dev->pdev->dev.of_node; ++ ++ if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) { ++ pr_err("%s:%d invalid i2c_freq_mode %d\n", ++ __func__, __LINE__, i2c_freq_mode); ++ return NULL; ++ } ++ + clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; + cci_clk_src = clk_params->cci_clk_src; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0631/0.patch b/Patches/Linux_CVEs/CVE-2017-0631/0.patch new file mode 100644 index 00000000..67cf9630 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0631/0.patch @@ -0,0 +1,41 @@ +From 8236d6ebc7e26361ca7078cbeba01509f10941d8 Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Tue, 22 Nov 2016 11:04:04 -0800 +Subject: msm: camera: flash: Validate the power setting size + +Validate the power setting size before copying. +If userspace sends a value which is greater than +MAX_POWER_CONFIG, then the driver accesses unintended memory. +This change will fix the issue. + +CRs-Fixed: 1093232 +Signed-off-by: Rajesh Bondugula +Change-Id: Ia49963248a94765baa19695294b197ea6f3bb8e2 +--- + drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +index 5f749bd..6c8826b 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +@@ -269,6 +269,16 @@ static int32_t msm_flash_i2c_init( + flash_ctrl->power_info.power_down_setting_size = + flash_ctrl->power_setting_array.size_down; + ++ if ((flash_ctrl->power_info.power_setting_size > MAX_POWER_CONFIG) || ++ (flash_ctrl->power_info.power_down_setting_size > MAX_POWER_CONFIG)) { ++ pr_err("%s:%d invalid power setting size=%d size_down=%d\n", ++ __func__, __LINE__, ++ flash_ctrl->power_info.power_setting_size, ++ flash_ctrl->power_info.power_down_setting_size); ++ rc = -EINVAL; ++ goto msm_flash_i2c_init_fail; ++ } ++ + rc = msm_camera_power_up(&flash_ctrl->power_info, + flash_ctrl->flash_device_type, + &flash_ctrl->flash_i2c_client); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0632/0.patch b/Patches/Linux_CVEs/CVE-2017-0632/0.patch new file mode 100644 index 00000000..e2e26330 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0632/0.patch @@ -0,0 +1,85 @@ +From 970d6933e53c1f7ca8c8b67f49147b18505c3b8f Mon Sep 17 00:00:00 2001 +From: Aravind Kumar +Date: Mon, 11 May 2015 18:19:11 +0530 +Subject: ASoC: msm8x16-wcd: prevent out of bounds access + +Hardcoding the third argument in strnstr function +is resulting in out of bounds access. Set the third argument +to sizeof the character string passed as the first argument +to prevent out of bounds access. + +CRs-Fixed: 832915 +Change-Id: I61be88701340e271fd866e0e1801722dbe7d63ac +Signed-off-by: Aravind Kumar +--- + sound/soc/codecs/msm8x16-wcd.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c +index 296f7d3..9a193c67 100644 +--- a/sound/soc/codecs/msm8x16-wcd.c ++++ b/sound/soc/codecs/msm8x16-wcd.c +@@ -2603,19 +2603,19 @@ static int msm8x16_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w, + micbias2 = (snd_soc_read(codec, MSM8X16_WCD_A_ANALOG_MICB_2_EN) & 0x80); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: +- if (strnstr(w->name, internal1_text, 30)) { ++ if (strnstr(w->name, internal1_text, strlen(w->name))) { + if (get_codec_version(msm8x16_wcd) == CAJON) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_TX_1_2_ATEST_CTL_2, + 0x02, 0x02); + snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x80); +- } else if (strnstr(w->name, internal2_text, 30)) { ++ } else if (strnstr(w->name, internal2_text, strlen(w->name))) { + snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x10); + snd_soc_update_bits(codec, w->reg, 0x60, 0x00); +- } else if (strnstr(w->name, internal3_text, 30)) { ++ } else if (strnstr(w->name, internal3_text, strlen(w->name))) { + snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x2); + } +- if (!strnstr(w->name, external_text, 30)) ++ if (!strnstr(w->name, external_text, strlen(w->name))) + snd_soc_update_bits(codec, + MSM8X16_WCD_A_ANALOG_MICB_1_EN, 0x05, 0x04); + if (w->reg == MSM8X16_WCD_A_ANALOG_MICB_1_EN) +@@ -2624,28 +2624,28 @@ static int msm8x16_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w, + break; + case SND_SOC_DAPM_POST_PMU: + usleep_range(20000, 20100); +- if (strnstr(w->name, internal1_text, 30)) { ++ if (strnstr(w->name, internal1_text, strlen(w->name))) { + snd_soc_update_bits(codec, micb_int_reg, 0x40, 0x40); +- } else if (strnstr(w->name, internal2_text, 30)) { ++ } else if (strnstr(w->name, internal2_text, strlen(w->name))) { + snd_soc_update_bits(codec, micb_int_reg, 0x08, 0x08); + msm8x16_notifier_call(codec, + WCD_EVENT_PRE_MICBIAS_2_ON); +- } else if (strnstr(w->name, internal3_text, 30)) { ++ } else if (strnstr(w->name, internal3_text, strlen(w->name))) { + snd_soc_update_bits(codec, micb_int_reg, 0x01, 0x01); +- } else if (strnstr(w->name, external2_text, 30)) { ++ } else if (strnstr(w->name, external2_text, strlen(w->name))) { + msm8x16_notifier_call(codec, + WCD_EVENT_PRE_MICBIAS_2_ON); + } + break; + case SND_SOC_DAPM_POST_PMD: +- if (strnstr(w->name, internal1_text, 30)) { ++ if (strnstr(w->name, internal1_text, strlen(w->name))) { + snd_soc_update_bits(codec, micb_int_reg, 0xC0, 0x40); +- } else if (strnstr(w->name, internal2_text, 30)) { ++ } else if (strnstr(w->name, internal2_text, strlen(w->name))) { + msm8x16_notifier_call(codec, + WCD_EVENT_PRE_MICBIAS_2_OFF); +- } else if (strnstr(w->name, internal3_text, 30)) { ++ } else if (strnstr(w->name, internal3_text, strlen(w->name))) { + snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0); +- } else if (strnstr(w->name, external2_text, 30)) { ++ } else if (strnstr(w->name, external2_text, strlen(w->name))) { + /* + * send micbias turn off event to mbhc driver and then + * break, as no need to set MICB_1_EN register. +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0633/0.patch b/Patches/Linux_CVEs/CVE-2017-0633/0.patch new file mode 100644 index 00000000..2a04b066 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0633/0.patch @@ -0,0 +1,128 @@ +From 4e38c573e81eb76f09bae425f035be392fbab370 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Fri, 24 Mar 2017 14:04:03 -0700 +Subject: [PATCH] net: wireless: bcmdhd: fix for IOVAR GET failed + +found some case that IOVAR callers set response buffer not enough to +contain input command string + argument. so it finally fail in IOVAR +transaction by its shorter buffer length. + +proposed fix is taking care this case by providing enough local +buffer inside dhd_iovar, which enough to input/output. + +Signed-off-by: Insun Song +Bug: 36000515 +Change-Id: I0afedcc29b05b12f42ebc619e6feeaa868fc00de +--- + drivers/net/wireless/bcmdhd/dhd_linux.c | 81 ++++++++++++++++++++++++--------- + 1 file changed, 59 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c +index 17e503c6d6b35..0b66e914c15a0 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_linux.c ++++ b/drivers/net/wireless/bcmdhd/dhd_linux.c +@@ -6257,45 +6257,82 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *param_buf, + return BCME_BADARG; + + input_len = strlen(name) + 1 + param_len; ++ if (input_len > WLC_IOCTL_MAXLEN) ++ return BCME_BADARG; ++ buf = NULL; + if (set) { + if (res_buf || res_len != 0) { + DHD_ERROR(("%s: SET wrong arguemnet\n", __FUNCTION__)); + return BCME_BADARG; + } +- buf = kzalloc(input_len, GFP_ATOMIC); ++ buf = kzalloc(input_len, GFP_KERNEL); + if (!buf) { + DHD_ERROR(("%s: mem alloc failed\n", __FUNCTION__)); + return BCME_NOMEM; + } + ret = bcm_mkiovar(name, param_buf, param_len, buf, input_len); ++ if (!ret) { ++ ret = BCME_NOMEM; ++ goto exit; ++ } ++ ++ ioc.cmd = WLC_SET_VAR; ++ ioc.buf = buf; ++ ioc.len = input_len; ++ ioc.set = set; ++ ++ ret = dhd_wl_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len); ++ + } else { +- if (!res_buf) { +- DHD_ERROR(("%s: GET failed. resp_buf NULL\n", ++ if (!res_buf || res_len == 0) { ++ DHD_ERROR(("%s: GET failed. resp_buf NULL or len:0\n", + __FUNCTION__)); + return BCME_NOMEM; + } + if (res_len < input_len) { +- DHD_ERROR(("%s: res_len(%d) < input_len(%d)\n", +- __FUNCTION__, res_len, input_len)); +- return BCME_NOMEM; +- } +- memset(res_buf, 0, res_len); +- ret = bcm_mkiovar(name, param_buf, param_len, res_buf, res_len); +- } +- if (ret == 0) { +- if (set) +- kfree(buf); +- return BCME_NOMEM; +- } ++ DHD_INFO(("%s: res_len(%d) < input_len(%d)\n", ++ __FUNCTION__, res_len, input_len)); ++ buf = kzalloc(input_len, GFP_KERNEL); ++ if (!buf) { ++ DHD_ERROR(("%s: mem alloc failed\n", ++ __FUNCTION__)); ++ return BCME_NOMEM; ++ } ++ ret = bcm_mkiovar(name, param_buf, param_len, buf, ++ input_len); ++ if (!ret) { ++ ret = BCME_NOMEM; ++ goto exit; ++ } + +- ioc.cmd = set ? WLC_SET_VAR : WLC_GET_VAR; +- ioc.buf = set ? buf : res_buf; +- ioc.len = set ? ret : res_len; +- ioc.set = set; ++ ioc.cmd = WLC_GET_VAR; ++ ioc.buf = buf; ++ ioc.len = input_len; ++ ioc.set = set; + +- ret = dhd_wl_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len); +- if (set) +- kfree(buf); ++ ret = dhd_wl_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len); ++ ++ if (ret == BCME_OK) ++ memcpy(res_buf, buf, res_len); ++ } else { ++ memset(res_buf, 0, res_len); ++ ret = bcm_mkiovar(name, param_buf, param_len, res_buf, ++ res_len); ++ if (!ret) { ++ ret = BCME_NOMEM; ++ goto exit; ++ } ++ ++ ioc.cmd = WLC_GET_VAR; ++ ioc.buf = res_buf; ++ ioc.len = res_len; ++ ioc.set = set; ++ ++ ret = dhd_wl_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len); ++ } ++ } ++exit: ++ kfree(buf); + return ret; + } + diff --git a/Patches/Linux_CVEs/CVE-2017-0650/0.patch b/Patches/Linux_CVEs/CVE-2017-0650/0.patch new file mode 100644 index 00000000..e2c32ab0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0650/0.patch @@ -0,0 +1,154 @@ +From c6d874fd2c515406bc33ab78d60df70a47bddae2 Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Fri, 7 Apr 2017 10:42:31 -0700 +Subject: [PATCH] input: synaptics_dsx: valid bounds of intr_reg_num + +Validate the intr_reg_num value returned by touchscreen +to ensure no out of bounds access can occur. + +Bug: 35472278 +Change-Id: If98e7091bf938061ac1b473ec652a620f118dbf0 +Signed-off-by: Andrew Chant +--- + .../synaptics_dsx_htc_2.6/synaptics_dsx_core.c | 50 ++++++++++++++++------ + 1 file changed, 38 insertions(+), 12 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c +index 90b6fc37284b7..dbe242808841b 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c ++++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c +@@ -2460,14 +2460,20 @@ static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data, + return retval; + } + +-static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, +- struct synaptics_rmi4_fn_desc *fd, +- unsigned int intr_count) ++static int synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, ++ struct synaptics_rmi4_fn_desc *fd, ++ unsigned int intr_count) + { + unsigned char ii; + unsigned char intr_offset; + + fhandler->intr_reg_num = (intr_count + 7) / 8; ++ if (fhandler->intr_reg_num >= MAX_INTR_REGISTERS) { ++ fhandler->intr_reg_num = 0; ++ fhandler->num_of_data_sources = 0; ++ fhandler->intr_mask = 0; ++ return -EINVAL; ++ } + if (fhandler->intr_reg_num != 0) + fhandler->intr_reg_num -= 1; + +@@ -2479,7 +2485,7 @@ static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, + ii++) + fhandler->intr_mask |= 1 << ii; + +- return; ++ return 0; + } + + static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data, +@@ -2487,12 +2493,16 @@ static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) + { ++ int retval; ++ + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->data = NULL; + fhandler->extra = NULL; + +- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ if (retval < 0) ++ return retval; + + rmi4_data->f01_query_base_addr = fd->query_base_addr; + rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr; +@@ -2578,7 +2588,9 @@ static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data, + rmi4_data->sensor_max_y = temp; + } + +- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ if (retval < 0) ++ return retval; + + fhandler->data = NULL; + +@@ -3362,7 +3374,9 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data, + return retval; + } + +- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ if (retval < 0) ++ return retval; + + /* Allocate memory for finger data storage space */ + fhandler->data_size = num_of_fingers * size_of_2d_data; +@@ -3569,7 +3583,9 @@ static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data, + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + +- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ if (retval < 0) ++ return retval; + + retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler); + if (retval < 0) +@@ -3596,12 +3612,16 @@ static int synaptics_rmi4_f34_init(struct synaptics_rmi4_data *rmi4_data, + unsigned int intr_count, + unsigned int page_number) + { ++ int retval; ++ + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->data = NULL; + fhandler->extra = NULL; + +- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ if (retval < 0) ++ return retval; + + rmi4_data->f34_query_base_addr = + (fd->query_base_addr | (page_number << 8)); +@@ -3634,7 +3654,9 @@ static int synaptics_rmi4_f54_init(struct synaptics_rmi4_data *rmi4_data, + fhandler->data = NULL; + fhandler->extra = NULL; + +- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); ++ if (retval < 0) ++ return retval; + + rmi4_data->f54_query_base_addr = + (fd->query_base_addr | (page_number << 8)); +@@ -4127,8 +4149,10 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data) + fhandler->fn_number = rmi_fd.fn_number; + fhandler->num_of_data_sources = + rmi_fd.intr_src_count; +- synaptics_rmi4_set_intr_mask(fhandler, &rmi_fd, +- intr_count); ++ retval = synaptics_rmi4_set_intr_mask( ++ fhandler, &rmi_fd, intr_count); ++ if (retval < 0) ++ return retval; + #endif + + #ifdef F51_DISCRETE_FORCE +@@ -4171,6 +4195,8 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data) + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Number of interrupt registers = %d\n", + __func__, rmi4_data->num_of_intr_regs); ++ if (rmi4_data->num_of_intr_regs > MAX_INTR_REGISTERS) ++ return -EINVAL; + + f01_query = kmalloc(F01_STD_QUERY_LEN, GFP_KERNEL); + if (!f01_query) { diff --git a/Patches/Linux_CVEs/CVE-2017-0705/0.patch b/Patches/Linux_CVEs/CVE-2017-0705/0.patch new file mode 100644 index 00000000..9b38b46d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0705/0.patch @@ -0,0 +1,84 @@ +From e58dd312d3d28331b2e28674c6a49f815a55d4bc Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Fri, 21 Apr 2017 14:38:21 -0700 +Subject: [PATCH] net: wireless: bcmdhd: adding boundary check in SWC gscan + config + +Since there's no boundary checking while looping NL structures, it could +corrupt kernel memory heap and leave room for security vulnerability +issue. +The proposed fix is adding a new NL attribute indicating how many SWC +bssids included. and it bounds NL iteration not to overwrite the +buffer. + +Signed-off-by: Insun Song +Bug: 34973477 +Change-Id: I03e079b6054b930487230ca313bb96a7f9e63e64 +--- + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 34 +++++++++++++++++++++++++++--- + 1 file changed, 31 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index 1f5152f66ab36..4e5fee09b5f33 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -1168,11 +1168,15 @@ static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy, + const struct nlattr *outer, *inner, *iter; + bool flush = FALSE; + wl_pfn_significant_bssid_t *pbssid; ++ uint16 num_bssid = 0; ++ uint16 max_buf_size = sizeof(gscan_swc_params_t) + ++ sizeof(wl_pfn_significant_bssid_t) * (PFN_SWC_MAX_NUM_APS - 1); ++ ++ significant_params = kzalloc(max_buf_size, GFP_KERNEL); + +- significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL); + if (!significant_params) { +- WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len)); +- return -1; ++ WL_ERR(("Cannot Malloc mem size:%d\n", len)); ++ return BCME_NOMEM; + } + + +@@ -1192,9 +1196,27 @@ static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy, + case GSCAN_ATTRIBUTE_MIN_BREACHING: + significant_params->swc_threshold = nla_get_u16(iter); + break; ++ case GSCAN_ATTRIBUTE_NUM_BSSID: ++ num_bssid = nla_get_u16(iter); ++ if (num_bssid > PFN_SWC_MAX_NUM_APS) { ++ WL_ERR(("ovar max SWC bssids:%d\n", ++ num_bssid)); ++ err = BCME_BADARG; ++ goto exit; ++ } ++ break; + case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS: ++ if (num_bssid == 0) { ++ WL_ERR(("num_bssid : 0\n")); ++ err = BCME_BADARG; ++ goto exit; ++ } + pbssid = significant_params->bssid_elem_list; + nla_for_each_nested(outer, iter, tmp) { ++ if (j >= num_bssid) { ++ j++; ++ break; ++ } + nla_for_each_nested(inner, outer, tmp1) { + switch (nla_type(inner)) { + case GSCAN_ATTRIBUTE_BSSID: +@@ -1217,6 +1239,12 @@ static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy, + break; + } + } ++ if (j != num_bssid) { ++ WL_ERR(("swc bssids count:%d not matched to num_bssid:%d\n", ++ j, num_bssid)); ++ err = BCME_BADARG; ++ goto exit; ++ } + significant_params->nbssid = j; + + if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg), diff --git a/Patches/Linux_CVEs/CVE-2017-0740/0.patch b/Patches/Linux_CVEs/CVE-2017-0740/0.patch new file mode 100644 index 00000000..a379087a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0740/0.patch @@ -0,0 +1,110 @@ +From e7fdc1ca00f1e589df8542af7e7acaaa87370625 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Fri, 7 Apr 2017 16:27:49 -0700 +Subject: [PATCH] net: wireless: bcmdhd: additional length check for BRCM EVENT + frame. + +This is just for exceptional case where user has updated kernel to the +latest, but still used non-patched firmware. The non-patched firmware +could deliver ETHER_TYPE_BRCM packet to host. + +If attacker inject packet with its header length forged, it could bypass +current host driver's length check routine and cause memory corruption. + +Proposed fix is enhancing length check to validate its header length. + +Change-Id: I90fc5101bddfd1d427e0a52758ddf8bc16577555 +Bug: 37168488 +Signed-off-by: Insun Song +--- + drivers/net/wireless/bcmdhd/bcmevent.c | 27 ++++++++++++++-------- + drivers/net/wireless/bcmdhd/include/proto/bcmeth.h | 1 + + 2 files changed, 18 insertions(+), 10 deletions(-) + mode change 100755 => 100644 drivers/net/wireless/bcmdhd/include/proto/bcmeth.h + +diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c +index b85f111bce180..7ed9739c0eddf 100644 +--- a/drivers/net/wireless/bcmdhd/bcmevent.c ++++ b/drivers/net/wireless/bcmdhd/bcmevent.c +@@ -209,12 +209,14 @@ int + is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype, + bcm_event_msg_u_t *out_event) + { +- uint16 len; ++ uint16 evlen; + uint16 subtype; + uint16 usr_subtype; + bcm_event_t *bcm_event; + uint8 *pktend; ++ uint8 *evend; + int err = BCME_OK; ++ uint32 data_len; + + pktend = (uint8 *)pktdata + pktlen; + bcm_event = (bcm_event_t *)pktdata; +@@ -235,8 +237,9 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype, + } + + /* check length in bcmeth_hdr */ +- len = ntoh16_ua((void *)&bcm_event->bcm_hdr.length); +- if (((uint8 *)&bcm_event->bcm_hdr.version + len) > pktend) { ++ evlen = ntoh16_ua((void *)&bcm_event->bcm_hdr.length); ++ evend = (uint8 *)&bcm_event->bcm_hdr.version + evlen; ++ if (evend != pktend) { + err = BCME_BADLEN; + goto done; + } +@@ -257,13 +260,15 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype, + usr_subtype = ntoh16_ua((void *)&bcm_event->bcm_hdr.usr_subtype); + switch (usr_subtype) { + case BCMILCP_BCM_SUBTYPE_EVENT: +- if (pktlen < sizeof(bcm_event_t)) { ++ if ((pktlen < sizeof(bcm_event_t)) || ++ (evend < ((uint8 *)bcm_event + sizeof(bcm_event_t)))) { + err = BCME_BADLEN; + goto done; + } + +- len = sizeof(bcm_event_t) + ntoh32_ua((void *)&bcm_event->event.datalen); +- if ((uint8 *)pktdata + len > pktend) { ++ data_len = ntoh32_ua((void *)&bcm_event->event.datalen); ++ if ((sizeof(bcm_event_t) + data_len + ++ BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD) != pktlen) { + err = BCME_BADLEN; + goto done; + } +@@ -280,14 +285,16 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype, + + break; + case BCMILCP_BCM_SUBTYPE_DNGLEVENT: +- if (pktlen < sizeof(bcm_dngl_event_t)) { ++ if (pktlen < sizeof(bcm_dngl_event_t) || ++ (evend < ((uint8 *)bcm_event + sizeof(bcm_dngl_event_t)))) { + err = BCME_BADLEN; + goto done; + } + +- len = sizeof(bcm_dngl_event_t) + +- ntoh16_ua((void *)&((bcm_dngl_event_t *)pktdata)->dngl_event.datalen); +- if ((uint8 *)pktdata + len > pktend) { ++ data_len = ntoh16_ua((void *)&((bcm_dngl_event_t *)pktdata) ++ ->dngl_event.datalen); ++ if ((sizeof(bcm_dngl_event_t) + data_len + ++ BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD) != pktlen) { + err = BCME_BADLEN; + goto done; + } +diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h +old mode 100755 +new mode 100644 +index 41c1b57443c77..756f594bc61db +--- a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h ++++ b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h +@@ -93,6 +93,7 @@ + #define BCMILCP_BCM_SUBTYPE_DNGLEVENT 5 + #define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 + #define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 ++#define BCMILCP_BCM_SUBTYPE_EVENT_DATA_PAD 2 + + /* These fields are stored in network order */ + typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr diff --git a/Patches/Linux_CVEs/CVE-2017-0746/0.patch b/Patches/Linux_CVEs/CVE-2017-0746/0.patch new file mode 100644 index 00000000..91e061a0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0746/0.patch @@ -0,0 +1,43 @@ +From a793531b751d8c3609e2bf1a5dc2c0f10e003632 Mon Sep 17 00:00:00 2001 +From: Utkarsh Saxena +Date: Tue, 25 Apr 2017 17:39:41 +0530 +Subject: [PATCH] msm: ipa: Fix for missing int overflow check in the refcount + library + +Overflow of reference counter can lead to memory leak. + +Before incrementing the reference count, check with +U32_MAX and return for error check. + +Bug: 35467471 +Change-Id: Ib96d36574ee086ec73c9836110cb2c98e8ae3d66 +Acked-by: Mohammed Javid +Signed-off-by: Utkarsh Saxena +--- + drivers/platform/msm/ipa/ipa_rt.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c +index 47767cdafa70f..81c6331da8a54 100644 +--- a/drivers/platform/msm/ipa/ipa_rt.c ++++ b/drivers/platform/msm/ipa/ipa_rt.c +@@ -1289,6 +1289,10 @@ int ipa_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) + mutex_lock(&ipa_ctx->lock); + entry = __ipa_find_rt_tbl(lookup->ip, lookup->name); + if (entry && entry->cookie == IPA_COOKIE) { ++ if (entry->ref_cnt == ((u32)~0U)) { ++ IPAERR("fail: ref count crossed limit\n"); ++ goto ret; ++ } + entry->ref_cnt++; + lookup->hdl = entry->id; + +@@ -1298,6 +1302,8 @@ int ipa_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) + + result = 0; + } ++ ++ret: + mutex_unlock(&ipa_ctx->lock); + + return result; diff --git a/Patches/Linux_CVEs/CVE-2017-0748/0.patch b/Patches/Linux_CVEs/CVE-2017-0748/0.patch new file mode 100644 index 00000000..0bb69f99 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0748/0.patch @@ -0,0 +1,41 @@ +From 43ff88a8336310e665941dea6ffec77cc8314706 Mon Sep 17 00:00:00 2001 +From: kunleiz +Date: Fri, 14 Apr 2017 10:28:42 +0800 +Subject: [PATCH] ASoC: msm: qdspv2: add result check when audio process fail + +A audio_process_event_req is not always to success. Therefore, +check the return value for audio_process_event_req, and +initializ usr_evt before using it. + +CRs-Fixed: 2029798 +Bug: 35764875 +Change-Id: I4adf682575f5f9233a1a1a533f9c6361af8a5bcf +Signed-off-by: kunleiz +--- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index ea1cb510a97fa..59f40806ee2be 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -842,6 +842,7 @@ static long audio_aio_process_event_req_compat(struct q6audio_aio *audio, + long rc; + struct msm_audio_event32 usr_evt_32; + struct msm_audio_event usr_evt; ++ memset(&usr_evt, 0, sizeof(struct msm_audio_event)); + + if (copy_from_user(&usr_evt_32, arg, + sizeof(struct msm_audio_event32))) { +@@ -851,6 +852,11 @@ static long audio_aio_process_event_req_compat(struct q6audio_aio *audio, + usr_evt.timeout_ms = usr_evt_32.timeout_ms; + + rc = audio_aio_process_event_req_common(audio, &usr_evt); ++ if (rc < 0) { ++ pr_err("%s: audio process event failed, rc = %ld", ++ __func__, rc); ++ return rc; ++ } + + usr_evt_32.event_type = usr_evt.event_type; + switch (usr_evt_32.event_type) { diff --git a/Patches/Linux_CVEs/CVE-2017-0750/0.patch b/Patches/Linux_CVEs/CVE-2017-0750/0.patch new file mode 100644 index 00000000..68f42d9f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0750/0.patch @@ -0,0 +1,44 @@ +From 3f0531e5775303091a1ff975cdd572cc6a935321 Mon Sep 17 00:00:00 2001 +From: Jin Qian +Date: Mon, 24 Apr 2017 18:20:52 -0700 +Subject: [PATCH] BACKPORT: f2fs: sanity check log_blocks_per_seg + +f2fs currently only supports 4KB block size and 2MB segment size. +Sanity check log_blocks_per_seg == 9, i.e. 2MB/4KB = (1 << 9) + +Partially +(cherry-picked from commit 9a59b62fd88196844cee5fff851bee2cfd7afb6e) + +f2fs: do more integrity verification for superblock + +Do more sanity check for superblock during ->mount. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim + +Bug: 36817013 +Change-Id: I0be52e54fba82083068337ceb9f7ad985a87319f +Signed-off-by: Jin Qian +--- + fs/f2fs/super.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 3a65e01323528..98a77b0a365d9 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -947,6 +947,14 @@ static int sanity_check_raw_super(struct super_block *sb, + return 1; + } + ++ /* check log blocks per segment */ ++ if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) { ++ f2fs_msg(sb, KERN_INFO, ++ "Invalid log blocks per segment (%u)\n", ++ le32_to_cpu(raw_super->log_blocks_per_seg)); ++ return 1; ++ } ++ + /* Currently, support 512/1024/2048/4096 bytes sector size */ + if (le32_to_cpu(raw_super->log_sectorsize) > + F2FS_MAX_LOG_SECTOR_SIZE || diff --git a/Patches/Linux_CVEs/CVE-2017-0751/0.patch b/Patches/Linux_CVEs/CVE-2017-0751/0.patch new file mode 100644 index 00000000..1bc956f1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0751/0.patch @@ -0,0 +1,47 @@ +From ee4aa31b9f24c28064e509e22c1f9013df768f5f Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Wed, 31 May 2017 16:28:01 -0700 +Subject: [PATCH] qcdev: Check the digest length during the SHA operations + +Check the digest length to avoid buffer overflow while +doing the SHA operations. + +Bug: 36591162 +CRs-Fixed: 2045061 +Change-Id: I4d3fb20723f59e905a672edaf84ee5d0865905b1 +Signed-off-by: Brahmaji K +Signed-off-by: Dennis Cagle +--- + drivers/crypto/msm/qcedev.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c +index ef4b5e15b4fad..f42d19a5cf59e 100644 +--- a/drivers/crypto/msm/qcedev.c ++++ b/drivers/crypto/msm/qcedev.c +@@ -1709,6 +1709,12 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + err = qcedev_hash_final(&qcedev_areq, handle); + if (err) + return err; ++ ++ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) { ++ pr_err("Invalid sha_ctxt.diglen %d\n", ++ handle->sha_ctxt.diglen); ++ return -EINVAL; ++ } + qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen; + memcpy(&qcedev_areq.sha_op_req.digest[0], + &handle->sha_ctxt.digest[0], +@@ -1737,6 +1743,12 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + err = qcedev_hash_final(&qcedev_areq, handle); + if (err) + return err; ++ ++ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) { ++ pr_err("Invalid sha_ctxt.diglen %d\n", ++ handle->sha_ctxt.diglen); ++ return -EINVAL; ++ } + qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen; + memcpy(&qcedev_areq.sha_op_req.digest[0], + &handle->sha_ctxt.digest[0], diff --git a/Patches/Linux_CVEs/CVE-2017-0786/0.patch b/Patches/Linux_CVEs/CVE-2017-0786/0.patch new file mode 100644 index 00000000..6051a676 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0786/0.patch @@ -0,0 +1,41 @@ +From 68acc6ab1474e9dde68880a7856e8a74ff86aa19 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Mon, 5 Jun 2017 10:21:10 -0700 +Subject: net: wireless: bcmdhd: adding boudary check in wl_escan_handler + +WLC_E_ESCAN_RESULT event could be manipulated especially two length field +inside, one is for escan_result buffer length and another one is +bss_info length, the forged fields may bypass current length check and +corrupt kernel heap memory. + +so added checking validation for two length fields in WLC_E_ESCAN_RESULT +event. + +Signed-off-by: Insun Song +Bug: 37351060 +Change-Id: I31e9fccc48fc06278fb3a87a76ef7337296c2b0d +--- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index 021f69f7..d8c748d 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -10513,6 +10513,13 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + WL_ERR(("Invalid escan result (NULL pointer)\n")); + goto exit; + } ++ if ((dtoh32(escan_result->buflen) > ESCAN_BUF_SIZE) || ++ (dtoh32(escan_result->buflen) < ++ sizeof(wl_escan_result_t))) { ++ WL_ERR(("Invalid escan buffer len:%d\n", ++ dtoh32(escan_result->buflen))); ++ goto exit; ++ } + if (dtoh16(escan_result->bss_count) != 1) { + WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count)); + goto exit; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0787/0.patch b/Patches/Linux_CVEs/CVE-2017-0787/0.patch new file mode 100644 index 00000000..8acfe027 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0787/0.patch @@ -0,0 +1,60 @@ +From 08ccf853c567bf02f4a5c9f9aef19a40ecdf57d1 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Mon, 5 Jun 2017 14:39:26 -0700 +Subject: net: wireless: bcmdhd: adding boundary check for pfn events + +adding boundary check for bssid count in dhd_pno_process_epno_result +and dhd_handle_hotlist_scan_evt function to prevent heap overflow. + +Signed-off-by: Insun Song +Bug: 37722328 +Bug: 37722970 +Change-Id: I1f0bc25ef4e7f5ba8f1aa9d9271919ee84d780a1 +--- + drivers/net/wireless/bcmdhd/dhd_pno.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index 8ebdf53..1a8e4ee 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -92,6 +92,11 @@ + #define ENTRY_OVERHEAD strlen("bssid=\nssid=\nfreq=\nlevel=\nage=\ndist=\ndistSd=\n====") + #define TIME_MIN_DIFF 5 + ++#define EVENT_DATABUF_MAXLEN (512 - sizeof(bcm_event_t)) ++#define EVENT_MAX_NETCNT \ ++ ((EVENT_DATABUF_MAXLEN - sizeof(wl_pfn_scanresults_t)) \ ++ / sizeof(wl_pfn_net_info_t) + 1) ++ + #ifdef GSCAN_SUPPORT + static int _dhd_pno_flush_ssid(dhd_pub_t *dhd); + static wl_pfn_gscan_ch_bucket_cfg_t * +@@ -3575,7 +3580,12 @@ dhd_pno_process_epno_result(dhd_pub_t *dhd, const void *data, uint32 event, int + if (event == WLC_E_PFN_NET_FOUND || event == WLC_E_PFN_NET_LOST) { + wl_pfn_scanresults_t *pfn_result = (wl_pfn_scanresults_t *)data; + wl_pfn_net_info_t *net; +- ++ if ((pfn_result->count == 0) || ++ (pfn_result->count > EVENT_MAX_NETCNT)) { ++ DHD_ERROR(("%s event %d: incorrect results count:%d\n", ++ __FUNCTION__, event, pfn_result->count)); ++ return NULL; ++ } + if (pfn_result->version != PFN_SCANRESULT_VERSION) { + DHD_ERROR(("%s event %d: Incorrect version %d %d\n", __FUNCTION__, event, + pfn_result->version, PFN_SCANRESULT_VERSION)); +@@ -3690,7 +3700,9 @@ void *dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, int *s + + gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan); + +- if (!results->count) { ++ if ((results->count == 0) || (results->count > EVENT_MAX_NETCNT)) { ++ DHD_ERROR(("%s: wrong count:%d\n", __FUNCTION__, ++ results->count)); + *send_evt_bytes = 0; + return ptr; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0788/0.patch b/Patches/Linux_CVEs/CVE-2017-0788/0.patch new file mode 100644 index 00000000..8acfe027 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0788/0.patch @@ -0,0 +1,60 @@ +From 08ccf853c567bf02f4a5c9f9aef19a40ecdf57d1 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Mon, 5 Jun 2017 14:39:26 -0700 +Subject: net: wireless: bcmdhd: adding boundary check for pfn events + +adding boundary check for bssid count in dhd_pno_process_epno_result +and dhd_handle_hotlist_scan_evt function to prevent heap overflow. + +Signed-off-by: Insun Song +Bug: 37722328 +Bug: 37722970 +Change-Id: I1f0bc25ef4e7f5ba8f1aa9d9271919ee84d780a1 +--- + drivers/net/wireless/bcmdhd/dhd_pno.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index 8ebdf53..1a8e4ee 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -92,6 +92,11 @@ + #define ENTRY_OVERHEAD strlen("bssid=\nssid=\nfreq=\nlevel=\nage=\ndist=\ndistSd=\n====") + #define TIME_MIN_DIFF 5 + ++#define EVENT_DATABUF_MAXLEN (512 - sizeof(bcm_event_t)) ++#define EVENT_MAX_NETCNT \ ++ ((EVENT_DATABUF_MAXLEN - sizeof(wl_pfn_scanresults_t)) \ ++ / sizeof(wl_pfn_net_info_t) + 1) ++ + #ifdef GSCAN_SUPPORT + static int _dhd_pno_flush_ssid(dhd_pub_t *dhd); + static wl_pfn_gscan_ch_bucket_cfg_t * +@@ -3575,7 +3580,12 @@ dhd_pno_process_epno_result(dhd_pub_t *dhd, const void *data, uint32 event, int + if (event == WLC_E_PFN_NET_FOUND || event == WLC_E_PFN_NET_LOST) { + wl_pfn_scanresults_t *pfn_result = (wl_pfn_scanresults_t *)data; + wl_pfn_net_info_t *net; +- ++ if ((pfn_result->count == 0) || ++ (pfn_result->count > EVENT_MAX_NETCNT)) { ++ DHD_ERROR(("%s event %d: incorrect results count:%d\n", ++ __FUNCTION__, event, pfn_result->count)); ++ return NULL; ++ } + if (pfn_result->version != PFN_SCANRESULT_VERSION) { + DHD_ERROR(("%s event %d: Incorrect version %d %d\n", __FUNCTION__, event, + pfn_result->version, PFN_SCANRESULT_VERSION)); +@@ -3690,7 +3700,9 @@ void *dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, int *s + + gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan); + +- if (!results->count) { ++ if ((results->count == 0) || (results->count > EVENT_MAX_NETCNT)) { ++ DHD_ERROR(("%s: wrong count:%d\n", __FUNCTION__, ++ results->count)); + *send_evt_bytes = 0; + return ptr; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0789/0.patch b/Patches/Linux_CVEs/CVE-2017-0789/0.patch new file mode 100644 index 00000000..4ff22daf --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0789/0.patch @@ -0,0 +1,661 @@ +From 58168423faa39f5062047eb1d16d294902f0f48b Mon Sep 17 00:00:00 2001 +From: Sudhir Kohalli +Date: Thu, 22 Jun 2017 11:48:53 -0700 +Subject: net: wireless: bcmdhd: Remove "dhd_handle_swc_evt" from dhd. + +Remove SWC(siginificant wifi change) from the host. Since current +feature is no longer being used. If needed will get the feature +back. Due to this there will not any heap overflow in +"dhd_handle_swc_evt" will be observed. + +Signed-off-by: Sudhir Kohalli +Bug: 37685267 +Change-Id: Ib03a39626223e27079f2b3f91564eb21025e57cf +--- + drivers/net/wireless/bcmdhd/bcmevent.c | 1 - + drivers/net/wireless/bcmdhd/dhd_common.c | 1 - + drivers/net/wireless/bcmdhd/dhd_linux.c | 9 - + drivers/net/wireless/bcmdhd/dhd_pno.c | 240 +-------------------- + drivers/net/wireless/bcmdhd/dhd_pno.h | 45 ++-- + .../net/wireless/bcmdhd/include/proto/bcmevent.h | 2 +- + drivers/net/wireless/bcmdhd/include/wlioctl.h | 6 - + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 9 - + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 108 ---------- + 9 files changed, 22 insertions(+), 399 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c +index 7ed9739..30e10d9 100644 +--- a/drivers/net/wireless/bcmdhd/bcmevent.c ++++ b/drivers/net/wireless/bcmdhd/bcmevent.c +@@ -157,7 +157,6 @@ static const bcmevent_name_str_t bcmevent_names[] = { + BCMEVENT_NAME(WLC_E_TXFAIL_THRESH), + #ifdef GSCAN_SUPPORT + BCMEVENT_NAME(WLC_E_PFN_GSCAN_FULL_RESULT), +- BCMEVENT_NAME(WLC_E_PFN_SWC), + #endif /* GSCAN_SUPPORT */ + #ifdef WLBSSLOAD_REPORT + BCMEVENT_NAME(WLC_E_BSS_LOAD), +diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c +index 1fbb5c4..d3f04a7 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_common.c ++++ b/drivers/net/wireless/bcmdhd/dhd_common.c +@@ -1325,7 +1325,6 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, + case WLC_E_PFN_SCAN_NONE: + case WLC_E_PFN_SCAN_ALLGONE: + case WLC_E_PFN_GSCAN_FULL_RESULT: +- case WLC_E_PFN_SWC: + case WLC_E_PFN_SSID_EXT: + DHD_EVENT(("PNOEVENT: %s\n", event_name)); + break; +diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c +index abc4331..101b03a 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_linux.c ++++ b/drivers/net/wireless/bcmdhd/dhd_linux.c +@@ -6066,7 +6066,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + #ifdef GSCAN_SUPPORT + setbit(eventmask_msg->mask, WLC_E_PFN_GSCAN_FULL_RESULT); + setbit(eventmask_msg->mask, WLC_E_PFN_SCAN_COMPLETE); +- setbit(eventmask_msg->mask, WLC_E_PFN_SWC); + setbit(eventmask_msg->mask, WLC_E_PFN_SSID_EXT); + setbit(eventmask_msg->mask, WLC_E_ROAM_EXP_EVENT); + #endif /* GSCAN_SUPPORT */ +@@ -8401,14 +8400,6 @@ int dhd_dev_pno_enable_full_scan_result(struct net_device *dev, bool real_time_f + return (dhd_pno_enable_full_scan_result(&dhd->pub, real_time_flag)); + } + +-/* Linux wrapper to call common dhd_handle_swc_evt */ +-void * dhd_dev_swc_scan_event(struct net_device *dev, const void *data, int *send_evt_bytes) +-{ +- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +- +- return (dhd_handle_swc_evt(&dhd->pub, data, send_evt_bytes)); +-} +- + /* Linux wrapper to call common dhd_handle_hotlist_scan_evt */ + void * dhd_dev_hotlist_scan_event(struct net_device *dev, + const void *data, int *send_evt_bytes, hotlist_type_t type) +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index 3103f89..8ebdf53 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -1028,34 +1028,6 @@ exit: + return err; + } + +-#ifdef GSCAN_SUPPORT +-static int +-_dhd_pno_add_significant_bssid(dhd_pub_t *dhd, +- wl_pfn_significant_bssid_t *p_pfn_significant_bssid, int nbssid) +-{ +- int err = BCME_OK; +- NULL_CHECK(dhd, "dhd is NULL", err); +- +- if (!nbssid) { +- err = BCME_ERROR; +- goto exit; +- } +- +- NULL_CHECK(p_pfn_significant_bssid, "bssid list is NULL", err); +- +- err = dhd_iovar(dhd, 0, "pfn_add_swc_bssid", +- (char *)p_pfn_significant_bssid, +- sizeof(wl_pfn_significant_bssid_t) * nbssid, NULL, 0, +- TRUE); +- if (err < 0) { +- DHD_ERROR(("%s : failed to execute pfn_significant_bssid %d\n", __FUNCTION__, err)); +- goto exit; +- } +-exit: +- return err; +-} +-#endif /* GSCAN_SUPPORT */ +- + int + dhd_pno_stop_for_ssid(dhd_pub_t *dhd) + { +@@ -1654,19 +1626,6 @@ static void dhd_pno_reset_cfg_gscan(dhd_pno_params_t *_params, + _params->params_gscan.nbssid_hotlist = 0; + DHD_PNO(("Flush Hotlist Config\n")); + } +- if (flags & GSCAN_FLUSH_SIGNIFICANT_CFG) { +- dhd_pno_significant_bssid_t *iter, *next; +- +- if (_params->params_gscan.nbssid_significant_change > 0) { +- list_for_each_entry_safe(iter, next, +- &_params->params_gscan.significant_bssid_list, list) { +- list_del(&iter->list); +- kfree(iter); +- } +- } +- _params->params_gscan.nbssid_significant_change = 0; +- DHD_PNO(("Flush Significant Change Config\n")); +- } + if (flags & GSCAN_FLUSH_EPNO_CFG) { + dhd_pno_ssid_t *iter, *next; + dhd_epno_ssid_cfg_t *epno_cfg = &_params->params_gscan.epno_cfg; +@@ -1808,8 +1767,10 @@ void * dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, + ptr->max_ap_cache_per_scan = GSCAN_MAX_AP_CACHE_PER_SCAN; + ptr->max_rssi_sample_size = PFN_SWC_RSSI_WINDOW_MAX; + ptr->max_scan_reporting_threshold = 100; +- ptr->max_hotlist_aps = PFN_HOTLIST_MAX_NUM_APS; +- ptr->max_significant_wifi_change_aps = PFN_SWC_MAX_NUM_APS; ++ ptr->max_hotlist_bssids = PFN_HOTLIST_MAX_NUM_APS; ++ ptr->max_hotlist_ssids = 0; ++ ptr->max_significant_wifi_change_aps = 0; ++ ptr->max_bssid_history_entries = 0; + ptr->max_epno_ssid_crc32 = MAX_EPNO_SSID_NUM; + ptr->max_epno_hidden_ssid = MAX_EPNO_HIDDEN_SSID; + ptr->max_white_list_ssid = MAX_WHITELIST_SSID; +@@ -1943,10 +1904,10 @@ int dhd_pno_set_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, + INIT_LIST_HEAD(&_params->params_gscan.hotlist_bssid_list); + + if ((_params->params_gscan.nbssid_hotlist + +- ptr->nbssid) > PFN_SWC_MAX_NUM_APS) { ++ ptr->nbssid) > PFN_SWC_MAX_NUM_APS) { + DHD_ERROR(("Excessive number of hotlist APs programmed %d\n", +- (_params->params_gscan.nbssid_hotlist + +- ptr->nbssid))); ++ (_params->params_gscan.nbssid_hotlist + ++ ptr->nbssid))); + err = BCME_RANGE; + goto exit; + } +@@ -1972,61 +1933,6 @@ int dhd_pno_set_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, + _params->params_gscan.lost_ap_window = ptr->lost_ap_window; + } + break; +- case DHD_PNO_SIGNIFICANT_SCAN_CFG_ID: +- { +- gscan_swc_params_t *ptr = (gscan_swc_params_t *)buf; +- dhd_pno_significant_bssid_t *_pno_significant_change_bssid; +- wl_pfn_significant_bssid_t *significant_bssid_ptr; +- +- if (flush) { +- dhd_pno_reset_cfg_gscan(_params, _pno_state, +- GSCAN_FLUSH_SIGNIFICANT_CFG); +- } +- +- if (!ptr->nbssid) +- break; +- +- if (!_params->params_gscan.nbssid_significant_change) +- INIT_LIST_HEAD(&_params->params_gscan.significant_bssid_list); +- +- if ((_params->params_gscan.nbssid_significant_change + +- ptr->nbssid) > PFN_SWC_MAX_NUM_APS) { +- DHD_ERROR(("Excessive number of SWC APs programmed %d\n", +- (_params->params_gscan.nbssid_significant_change + +- ptr->nbssid))); +- err = BCME_RANGE; +- goto exit; +- } +- +- for (i = 0, significant_bssid_ptr = ptr->bssid_elem_list; +- i < ptr->nbssid; i++, significant_bssid_ptr++) { +- _pno_significant_change_bssid = +- kzalloc(sizeof(dhd_pno_significant_bssid_t), +- GFP_KERNEL); +- +- if (!_pno_significant_change_bssid) { +- DHD_ERROR(("SWC bssidptr is NULL, cannot kalloc %zd bytes", +- sizeof(dhd_pno_significant_bssid_t))); +- err = BCME_NOMEM; +- goto exit; +- } +- memcpy(&_pno_significant_change_bssid->BSSID, +- &significant_bssid_ptr->macaddr, ETHER_ADDR_LEN); +- _pno_significant_change_bssid->rssi_low_threshold = +- significant_bssid_ptr->rssi_low_threshold; +- _pno_significant_change_bssid->rssi_high_threshold = +- significant_bssid_ptr->rssi_high_threshold; +- list_add_tail(&_pno_significant_change_bssid->list, +- &_params->params_gscan.significant_bssid_list); +- } +- +- _params->params_gscan.swc_nbssid_threshold = ptr->swc_threshold; +- _params->params_gscan.swc_rssi_window_size = ptr->rssi_window; +- _params->params_gscan.lost_ap_window = ptr->lost_ap_window; +- _params->params_gscan.nbssid_significant_change += ptr->nbssid; +- +- } +- break; + case DHD_PNO_SCAN_CFG_ID: + { + int i, k; +@@ -2145,7 +2051,6 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) + dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd); + wl_pfn_gscan_ch_bucket_cfg_t *ch_bucket = NULL; + wl_pfn_gscan_cfg_t *pfn_gscan_cfg_t = NULL; +- wl_pfn_significant_bssid_t *p_pfn_significant_bssid = NULL; + wl_pfn_bssid_t *p_pfn_bssid = NULL; + dhd_pno_params_t *params_legacy; + dhd_pno_params_t *_params; +@@ -2219,7 +2124,8 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) + + gscan_param_size = sizeof(wl_pfn_gscan_cfg_t) + + (num_buckets_to_fw - 1) * sizeof(wl_pfn_gscan_ch_bucket_cfg_t); +- pfn_gscan_cfg_t = (wl_pfn_gscan_cfg_t *) MALLOC(dhd->osh, gscan_param_size); ++ pfn_gscan_cfg_t = (wl_pfn_gscan_cfg_t *) ++ MALLOCZ(dhd->osh, gscan_param_size); + + if (!pfn_gscan_cfg_t) { + DHD_ERROR(("%s: failed to malloc memory of size %d\n", +@@ -2234,16 +2140,6 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) + else + pfn_gscan_cfg_t->buffer_threshold = GSCAN_BATCH_NO_THR_SET; + +- if (gscan_params->nbssid_significant_change) { +- pfn_gscan_cfg_t->swc_nbssid_threshold = gscan_params->swc_nbssid_threshold; +- pfn_gscan_cfg_t->swc_rssi_window_size = gscan_params->swc_rssi_window_size; +- pfn_gscan_cfg_t->lost_ap_window = gscan_params->lost_ap_window; +- } else { +- pfn_gscan_cfg_t->swc_nbssid_threshold = 0; +- pfn_gscan_cfg_t->swc_rssi_window_size = 0; +- pfn_gscan_cfg_t->lost_ap_window = 0; +- } +- + pfn_gscan_cfg_t->flags = + (gscan_params->send_all_results_flag & GSCAN_SEND_ALL_RESULTS_MASK); + pfn_gscan_cfg_t->count_of_channel_buckets = num_buckets_to_fw; +@@ -2277,38 +2173,6 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) + __FUNCTION__, err)); + goto exit; + } +- if (gscan_params->nbssid_significant_change) { +- dhd_pno_significant_bssid_t *iter, *next; +- +- p_pfn_significant_bssid = kzalloc(sizeof(wl_pfn_significant_bssid_t) * +- gscan_params->nbssid_significant_change, GFP_KERNEL); +- if (p_pfn_significant_bssid == NULL) { +- DHD_ERROR(("%s : failed to allocate memory %zd\n", +- __FUNCTION__, +- sizeof(wl_pfn_significant_bssid_t) * +- gscan_params->nbssid_significant_change)); +- err = BCME_NOMEM; +- goto exit; +- } +- i = 0; +- /* convert dhd_pno_significant_bssid_t to wl_pfn_significant_bssid_t */ +- list_for_each_entry_safe(iter, next, &gscan_params->significant_bssid_list, list) { +- p_pfn_significant_bssid[i].rssi_low_threshold = iter->rssi_low_threshold; +- p_pfn_significant_bssid[i].rssi_high_threshold = iter->rssi_high_threshold; +- memcpy(&p_pfn_significant_bssid[i].macaddr, &iter->BSSID, ETHER_ADDR_LEN); +- i++; +- } +- +- DHD_PNO(("nbssid_significant_change %d \n", +- gscan_params->nbssid_significant_change)); +- err = _dhd_pno_add_significant_bssid(dhd, p_pfn_significant_bssid, +- gscan_params->nbssid_significant_change); +- if (err < 0) { +- DHD_ERROR(("%s : failed to call _dhd_pno_add_significant_bssid(err :%d)\n", +- __FUNCTION__, err)); +- goto exit; +- } +- } + /* Reprogram ePNO cfg from dhd cache if FW has been flushed */ + if (fw_flushed) { + dhd_pno_set_epno(dhd); +@@ -2362,7 +2226,6 @@ exit: + _pno_state->pno_mode &= ~DHD_PNO_GSCAN_MODE; + } + } +- kfree(p_pfn_significant_bssid); + kfree(p_pfn_bssid); + if (pfn_gscan_cfg_t) + MFREE(dhd->osh, pfn_gscan_cfg_t, gscan_param_size); +@@ -3581,91 +3444,6 @@ int dhd_retreive_batch_scan_results(dhd_pub_t *dhd) + return err; + } + +-/* Handle Significant WiFi Change (SWC) event from FW +- * Send event to HAL when all results arrive from FW +- */ +-void * dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes) +-{ +- void *ptr = NULL; +- dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd); +- struct dhd_pno_gscan_params *gscan_params; +- struct dhd_pno_swc_evt_param *params; +- wl_pfn_swc_results_t *results = (wl_pfn_swc_results_t *)event_data; +- wl_pfn_significant_net_t *change_array; +- int i; +- +- gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan); +- params = &(gscan_params->param_significant); +- +- if (!results->total_count) { +- *send_evt_bytes = 0; +- return ptr; +- } +- +- if (!params->results_rxed_so_far) { +- if (!params->change_array) { +- params->change_array = (wl_pfn_significant_net_t *) +- kmalloc(sizeof(wl_pfn_significant_net_t) * results->total_count, +- GFP_KERNEL); +- +- if (!params->change_array) { +- DHD_ERROR(("%s Cannot Malloc %zd bytes!!\n", __FUNCTION__, +- sizeof(wl_pfn_significant_net_t) * results->total_count)); +- *send_evt_bytes = 0; +- return ptr; +- } +- } else { +- DHD_ERROR(("RX'ed WLC_E_PFN_SWC evt from FW, previous evt not complete!!")); +- *send_evt_bytes = 0; +- return ptr; +- } +- +- } +- +- DHD_PNO(("%s: pkt_count %d total_count %d\n", __FUNCTION__, +- results->pkt_count, results->total_count)); +- +- for (i = 0; i < results->pkt_count; i++) { +- DHD_PNO(("\t %02x:%02x:%02x:%02x:%02x:%02x\n", +- results->list[i].BSSID.octet[0], +- results->list[i].BSSID.octet[1], +- results->list[i].BSSID.octet[2], +- results->list[i].BSSID.octet[3], +- results->list[i].BSSID.octet[4], +- results->list[i].BSSID.octet[5])); +- } +- +- change_array = ¶ms->change_array[params->results_rxed_so_far]; +- if ((params->results_rxed_so_far + results->pkt_count) > +- results->total_count) { +- DHD_ERROR(("Error: Invalid data reset the counters!!\n")); +- *send_evt_bytes = 0; +- kfree(params->change_array); +- params->change_array = NULL; +- return ptr; +- } +- +- memcpy(change_array, results->list, +- sizeof(wl_pfn_significant_net_t) * results->pkt_count); +- params->results_rxed_so_far += results->pkt_count; +- +- if (params->results_rxed_so_far == results->total_count) { +- params->results_rxed_so_far = 0; +- *send_evt_bytes = sizeof(wl_pfn_significant_net_t) * results->total_count; +- /* Pack up change buffer to send up and reset +- * results_rxed_so_far, after its done. +- */ +- ptr = (void *) params->change_array; +- /* expecting the callee to free this mem chunk */ +- params->change_array = NULL; +- } +- else { +- *send_evt_bytes = 0; +- } +- +- return ptr; +-} +- + void dhd_gscan_hotlist_cache_cleanup(dhd_pub_t *dhd, hotlist_type_t type) + { + dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd); +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h +index 3398752..9a348f9 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.h ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.h +@@ -359,16 +359,18 @@ typedef struct { + } wifi_passpoint_network; + + typedef struct dhd_pno_gscan_capabilities { +- int max_scan_cache_size; +- int max_scan_buckets; +- int max_ap_cache_per_scan; +- int max_rssi_sample_size; +- int max_scan_reporting_threshold; +- int max_hotlist_aps; +- int max_significant_wifi_change_aps; +- int max_epno_ssid_crc32; +- int max_epno_hidden_ssid; +- int max_white_list_ssid; ++ int max_scan_cache_size; ++ int max_scan_buckets; ++ int max_ap_cache_per_scan; ++ int max_rssi_sample_size; ++ int max_scan_reporting_threshold; ++ int max_hotlist_bssids; ++ int max_hotlist_ssids; ++ int max_significant_wifi_change_aps; ++ int max_bssid_history_entries; ++ int max_epno_ssid_crc32; ++ int max_epno_hidden_ssid; ++ int max_white_list_ssid; + } dhd_pno_gscan_capabilities_t; + + typedef struct dhd_epno_ssid_cfg { +@@ -426,26 +428,6 @@ typedef struct gscan_hotlist_scan_params { + struct bssid_t bssid[1]; /* n bssids to follow */ + } gscan_hotlist_scan_params_t; + +-/* SWC (Significant WiFi Change) params */ +-typedef struct gscan_swc_params { +- /* Rssi averaging window size */ +- uint8 rssi_window; +- /* Number of scans that the AP has to be absent before +- * being declared LOST +- */ +- uint8 lost_ap_window; +- /* if x Aps have a significant change generate an event. */ +- uint8 swc_threshold; +- uint8 nbssid; +- wl_pfn_significant_bssid_t bssid_elem_list[1]; +-} gscan_swc_params_t; +- +-typedef struct dhd_pno_significant_bssid { +- struct ether_addr BSSID; +- int8 rssi_low_threshold; +- int8 rssi_high_threshold; +- struct list_head list; +-} dhd_pno_significant_bssid_t; + #endif /* GSCAN_SUPPORT */ + typedef union dhd_pno_params { + struct dhd_pno_legacy_params params_legacy; +@@ -506,8 +488,6 @@ int dhd_dev_pno_lock_access_batch_results(struct net_device *dev); + void dhd_dev_pno_unlock_access_batch_results(struct net_device *dev); + extern int dhd_dev_pno_run_gscan(struct net_device *dev, bool run, bool flush); + extern int dhd_dev_pno_enable_full_scan_result(struct net_device *dev, bool real_time); +-extern void * dhd_dev_swc_scan_event(struct net_device *dev, const void *data, +- int *send_evt_bytes); + int dhd_retreive_batch_scan_results(dhd_pub_t *dhd); + extern void * dhd_dev_hotlist_scan_event(struct net_device *dev, + const void *data, int *send_evt_bytes, hotlist_type_t type); +@@ -560,7 +540,6 @@ extern int dhd_pno_initiate_gscan_request(dhd_pub_t *dhd, bool run, bool flush); + extern int dhd_pno_enable_full_scan_result(dhd_pub_t *dhd, bool real_time_flag); + extern int dhd_pno_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, void *buf); + extern int dhd_dev_retrieve_batch_scan(struct net_device *dev); +-extern void *dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes); + extern void *dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, + int *send_evt_bytes, hotlist_type_t type); + extern void * +diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h +index 098da15..d6f7cd4 100644 +--- a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h ++++ b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h +@@ -236,7 +236,7 @@ typedef union bcm_event_msg_u { + #define WLC_E_FBT_AUTH_REQ_IND 132 /* FBT Authentication Request Indication */ + #define WLC_E_RSSI_LQM 133 /* Enhancement addition for WLC_E_RSSI */ + #define WLC_E_PFN_GSCAN_FULL_RESULT 134 /* Full probe/beacon (IEs etc) results */ +-#define WLC_E_PFN_SWC 135 /* Significant change in rssi of bssids being tracked */ ++/* 135 was legacy entry for WLC_E_PFN_SWC can be reused */ + #define WLC_E_PFN_SCAN_COMPLETE 138 /* PFN completed scan of network list */ + #define WLC_E_RMC_EVENT 139 /* RMC event */ + #define WLC_E_PFN_SSID_EXT 142 /* SSID EXT event */ +diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h +index 808a0bf..b89c4be 100644 +--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h ++++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h +@@ -2705,12 +2705,6 @@ typedef struct wl_pfn_bssid { + uint16 flags; + } wl_pfn_bssid_t; + +-typedef struct wl_pfn_significant_bssid { +- struct ether_addr macaddr; +- int8 rssi_low_threshold; +- int8 rssi_high_threshold; +-} wl_pfn_significant_bssid_t; +- + #define WL_PFN_SUPPRESSFOUND_MASK 0x08 + #define WL_PFN_SUPPRESSLOST_MASK 0x10 + #define WL_PFN_RSSI_MASK 0xff00 +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index 1d1e2a8..e7ababd 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -9397,14 +9397,6 @@ wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + u32 len = ntoh32(e->datalen); + + switch (event) { +- case WLC_E_PFN_SWC: +- ptr = dhd_dev_swc_scan_event(ndev, data, &send_evt_bytes); +- if (send_evt_bytes) { +- wl_cfgvendor_send_async_event(wiphy, ndev, +- GOOGLE_GSCAN_SIGNIFICANT_EVENT, ptr, send_evt_bytes); +- kfree(ptr); +- } +- break; + case WLC_E_PFN_BEST_BATCHING: + err = dhd_dev_retrieve_batch_scan(ndev); + if (err < 0) { +@@ -10094,7 +10086,6 @@ static void wl_init_event_handler(struct bcm_cfg80211 *cfg) + cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event; + cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event; + cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event; +- 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; +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index 4e5fee0..140a20d 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -1158,106 +1158,6 @@ static int wl_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy, + return err; + } + +-static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy, +- struct wireless_dev *wdev, const void *data, int len) +-{ +- int err = 0; +- struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); +- gscan_swc_params_t *significant_params; +- int tmp, tmp1, tmp2, type, j = 0; +- const struct nlattr *outer, *inner, *iter; +- bool flush = FALSE; +- wl_pfn_significant_bssid_t *pbssid; +- uint16 num_bssid = 0; +- uint16 max_buf_size = sizeof(gscan_swc_params_t) + +- sizeof(wl_pfn_significant_bssid_t) * (PFN_SWC_MAX_NUM_APS - 1); +- +- significant_params = kzalloc(max_buf_size, GFP_KERNEL); +- +- if (!significant_params) { +- WL_ERR(("Cannot Malloc mem size:%d\n", len)); +- return BCME_NOMEM; +- } +- +- +- nla_for_each_attr(iter, data, len, tmp2) { +- type = nla_type(iter); +- +- switch (type) { +- case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH: +- flush = (bool) nla_get_u8(iter); +- break; +- case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE: +- significant_params->rssi_window = nla_get_u16(iter); +- break; +- case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: +- significant_params->lost_ap_window = nla_get_u16(iter); +- break; +- case GSCAN_ATTRIBUTE_MIN_BREACHING: +- significant_params->swc_threshold = nla_get_u16(iter); +- break; +- case GSCAN_ATTRIBUTE_NUM_BSSID: +- num_bssid = nla_get_u16(iter); +- if (num_bssid > PFN_SWC_MAX_NUM_APS) { +- WL_ERR(("ovar max SWC bssids:%d\n", +- num_bssid)); +- err = BCME_BADARG; +- goto exit; +- } +- break; +- case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS: +- if (num_bssid == 0) { +- WL_ERR(("num_bssid : 0\n")); +- err = BCME_BADARG; +- goto exit; +- } +- pbssid = significant_params->bssid_elem_list; +- nla_for_each_nested(outer, iter, tmp) { +- if (j >= num_bssid) { +- j++; +- break; +- } +- nla_for_each_nested(inner, outer, tmp1) { +- switch (nla_type(inner)) { +- case GSCAN_ATTRIBUTE_BSSID: +- memcpy(&(pbssid[j].macaddr), +- nla_data(inner), +- ETHER_ADDR_LEN); +- break; +- case GSCAN_ATTRIBUTE_RSSI_HIGH: +- pbssid[j].rssi_high_threshold = +- (int8) nla_get_u8(inner); +- break; +- case GSCAN_ATTRIBUTE_RSSI_LOW: +- pbssid[j].rssi_low_threshold = +- (int8) nla_get_u8(inner); +- break; +- } +- } +- j++; +- } +- break; +- } +- } +- if (j != num_bssid) { +- WL_ERR(("swc bssids count:%d not matched to num_bssid:%d\n", +- j, num_bssid)); +- err = BCME_BADARG; +- goto exit; +- } +- significant_params->nbssid = j; +- +- if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg), +- DHD_PNO_SIGNIFICANT_SCAN_CFG_ID, significant_params, flush) < 0) { +- WL_ERR(("Could not set GSCAN significant cfg\n")); +- err = -EINVAL; +- goto exit; +- } +-exit: +- kfree(significant_params); +- return err; +-} +- + static int wl_cfgvendor_enable_lazy_roam(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int len) + { +@@ -3013,14 +2913,6 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { + { + { + .vendor_id = OUI_GOOGLE, +- .subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG +- }, +- .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +- .doit = wl_cfgvendor_significant_change_cfg +- }, +- { +- { +- .vendor_id = OUI_GOOGLE, + .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0790/0.patch b/Patches/Linux_CVEs/CVE-2017-0790/0.patch new file mode 100644 index 00000000..b155460d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0790/0.patch @@ -0,0 +1,173 @@ +From 5575ff40a53a954ec942ff0c17b193433e72c132 Mon Sep 17 00:00:00 2001 +From: Sudhir Kohalli +Date: Wed, 14 Jun 2017 11:36:22 -0700 +Subject: net: wireless: bcmdhd: add boundary check in GSCAN full result + handler + +validtating each length fields before not to overflow allocated +data type. it prevent possiblity heap memory corrupted. + +Signed-off-by: Sudhir Kohalli +Bug: 37357704 +Change-Id: I7c04b93f3843c8100bd932fb9b7c67ef76b93050 +--- + drivers/net/wireless/bcmdhd/dhd_linux.c | 5 +++-- + drivers/net/wireless/bcmdhd/dhd_pno.c | 37 ++++++++++++++++++++++++------- + drivers/net/wireless/bcmdhd/dhd_pno.h | 7 +++--- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 7 ++++-- + 4 files changed, 41 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c +index 0b66e91..abc4331 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_linux.c ++++ b/drivers/net/wireless/bcmdhd/dhd_linux.c +@@ -8420,11 +8420,12 @@ void * dhd_dev_hotlist_scan_event(struct net_device *dev, + + /* Linux wrapper to call common dhd_process_full_gscan_result */ + void * dhd_dev_process_full_gscan_result(struct net_device *dev, +-const void *data, int *send_evt_bytes) ++const void *data, uint32 len, int *send_evt_bytes) + { + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + +- return (dhd_process_full_gscan_result(&dhd->pub, data, send_evt_bytes)); ++ return dhd_process_full_gscan_result(&dhd->pub, data, len, ++ send_evt_bytes); + } + + void dhd_dev_gscan_hotlist_cache_cleanup(struct net_device *dev, hotlist_type_t type) +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index c80adec..3103f89 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -47,6 +47,7 @@ + #ifdef GSCAN_SUPPORT + #include + #endif /* GSCAN_SUPPORT */ ++#include + + #ifdef __BIG_ENDIAN + #include +@@ -3693,7 +3694,8 @@ void dhd_gscan_hotlist_cache_cleanup(dhd_pub_t *dhd, hotlist_type_t type) + } + + void * +-dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, int *size) ++dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, uint32 len, ++ int *size) + { + wl_bss_info_t *bi = NULL; + wl_gscan_result_t *gscan_result; +@@ -3702,15 +3704,25 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, int *size) + uint8 channel; + uint32 mem_needed; + struct timespec ts; ++ u32 bi_ie_length = 0; ++ u32 bi_ie_offset = 0; + + *size = 0; +- + gscan_result = (wl_gscan_result_t *)data; +- + if (!gscan_result) { + DHD_ERROR(("Invalid gscan result (NULL pointer)\n")); + goto exit; + } ++ ++ if ((len < sizeof(*gscan_result)) || ++ (len < dtoh32(gscan_result->buflen)) || ++ (dtoh32(gscan_result->buflen) > ++ (sizeof(*gscan_result) + WL_SCAN_IE_LEN_MAX))) { ++ DHD_ERROR(("%s: invalid gscan buflen:%u\n", __func__, ++ dtoh32(gscan_result->buflen))); ++ goto exit; ++ } ++ + if (!gscan_result->bss_info) { + DHD_ERROR(("Invalid gscan bss info (NULL pointer)\n")); + goto exit; +@@ -3722,12 +3734,21 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, int *size) + DHD_ERROR(("Invalid bss_info length %d: ignoring\n", bi_length)); + goto exit; + } ++ ++ bi_ie_offset = dtoh32(bi->ie_offset); ++ bi_ie_length = dtoh32(bi->ie_length); ++ if ((bi_ie_offset + bi_ie_length) > bi_length) { ++ DHD_ERROR(("%s: Invalid ie_length:%u or ie_offset:%u\n", ++ __func__, bi_ie_length, bi_ie_offset)); ++ goto exit; ++ } + if (bi->SSID_len > DOT11_MAX_SSID_LEN) { +- DHD_ERROR(("Invalid SSID length %d: trimming it to max\n", bi->SSID_len)); +- bi->SSID_len = DOT11_MAX_SSID_LEN; ++ DHD_ERROR(("%s: Invalid SSID length %u\n", ++ __func__, bi->SSID_len)); ++ goto exit; + } + +- mem_needed = OFFSETOF(wifi_gscan_full_result_t, ie_data) + bi->ie_length; ++ mem_needed = OFFSETOF(wifi_gscan_full_result_t, ie_data) + bi_ie_length; + result = (wifi_gscan_full_result_t *) kmalloc(mem_needed, GFP_KERNEL); + + if (!result) { +@@ -3749,9 +3770,9 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, int *size) + result->fixed.ts = (uint64) TIMESPEC_TO_US(ts); + result->fixed.beacon_period = dtoh16(bi->beacon_period); + result->fixed.capability = dtoh16(bi->capability); +- result->ie_length = dtoh32(bi->ie_length); ++ result->ie_length = bi_ie_length; + memcpy(&result->fixed.macaddr, &bi->BSSID, ETHER_ADDR_LEN); +- memcpy(result->ie_data, ((uint8 *)bi + bi->ie_offset), bi->ie_length); ++ memcpy(result->ie_data, ((uint8 *)bi + bi_ie_offset), bi_ie_length); + *size = mem_needed; + exit: + return result; +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h +index a0edf54..3398752 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.h ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.h +@@ -512,7 +512,7 @@ int dhd_retreive_batch_scan_results(dhd_pub_t *dhd); + extern void * dhd_dev_hotlist_scan_event(struct net_device *dev, + const void *data, int *send_evt_bytes, hotlist_type_t type); + void * dhd_dev_process_full_gscan_result(struct net_device *dev, +- const void *data, int *send_evt_bytes); ++ const void *data, uint32 len, int *send_evt_bytes); + extern int dhd_dev_gscan_batch_cache_cleanup(struct net_device *dev); + extern void dhd_dev_gscan_hotlist_cache_cleanup(struct net_device *dev, hotlist_type_t type); + extern int dhd_dev_wait_batch_results_complete(struct net_device *dev); +@@ -563,8 +563,9 @@ extern int dhd_dev_retrieve_batch_scan(struct net_device *dev); + extern void *dhd_handle_swc_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes); + extern void *dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, + int *send_evt_bytes, hotlist_type_t type); +-extern void *dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *event_data, +- int *send_evt_bytes); ++extern void * ++dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *event_data, ++ uint32 len, int *send_evt_bytes); + extern int dhd_gscan_batch_cache_cleanup(dhd_pub_t *dhd); + 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); +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index d8c748d..1d1e2a8 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -9452,10 +9452,13 @@ wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + err = -EINVAL; + break; + case WLC_E_PFN_GSCAN_FULL_RESULT: +- ptr = dhd_dev_process_full_gscan_result(ndev, data, &send_evt_bytes); ++ ptr = ++ dhd_dev_process_full_gscan_result(ndev, data, len, ++ &send_evt_bytes); + if (ptr) { + wl_cfgvendor_send_async_event(wiphy, ndev, +- GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes); ++ GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, ++ send_evt_bytes); + kfree(ptr); + } else + err = -ENOMEM; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0791/0.patch b/Patches/Linux_CVEs/CVE-2017-0791/0.patch new file mode 100644 index 00000000..437310a9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0791/0.patch @@ -0,0 +1,53 @@ +From 2935fde98001eca0f8dafad827933ce60d44ffba Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Wed, 24 May 2017 09:21:02 -0700 +Subject: net: wireless: bcmdhd: adding boundary check in + wl_notify_rx_mgmt_frame + +added boundary check for input parameters not to corrupt kernel heap in +case user injected malformed input + +Signed-off-by: Insun Song +Bug: 37306719 +Change-Id: I6dc12e9bcfce8f3b43ecf14bfd6976bf87afeaa5 +--- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index 842091f..021f69f7 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -9657,9 +9657,15 @@ wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + u32 event = ntoh32(e->event_type); + u8 *mgmt_frame; + u8 bsscfgidx = e->bsscfgidx; +- u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t); ++ u32 mgmt_frame_len = ntoh32(e->datalen); + u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK)); + ++ if (mgmt_frame_len < sizeof(wl_event_rx_frame_data_t)) { ++ WL_ERR(("wrong datalen:%d\n", mgmt_frame_len)); ++ return -EINVAL; ++ } ++ mgmt_frame_len -= sizeof(wl_event_rx_frame_data_t); ++ + memset(&bssid, 0, ETHER_ADDR_LEN); + + ndev = cfgdev_to_wlc_ndev(cfgdev, cfg); +@@ -9781,7 +9787,11 @@ wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + WL_DBG((" Event WLC_E_PROBREQ_MSG received\n")); + mgmt_frame = (u8 *)(data); + mgmt_frame_len = ntoh32(e->datalen); +- ++ if (mgmt_frame_len < DOT11_MGMT_HDR_LEN) { ++ WL_ERR(("WLC_E_PROBREQ_MSG - wrong datalen:%d\n", ++ mgmt_frame_len)); ++ return -EINVAL; ++ } + prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN; + + /* Parse prob_req IEs */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0792/0.patch b/Patches/Linux_CVEs/CVE-2017-0792/0.patch new file mode 100644 index 00000000..839c4b1d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0792/0.patch @@ -0,0 +1,45 @@ +From f35ce58f516c15c022745d687bb1c59ffab63293 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Wed, 24 May 2017 10:11:27 -0700 +Subject: net: wireless: bcmdhd: add boundary check in dhd_rtt_event_handler + +added boundary check for input parameters not to corrupt kernel heap in +case user injected malformed input + +Signed-off-by: Insun Song +Bug: 37305578 +Change-Id: I92114d7166fb68d8d97b33ea214f80e8917794d1 +--- + drivers/net/wireless/bcmdhd/dhd_rtt.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_rtt.c b/drivers/net/wireless/bcmdhd/dhd_rtt.c +index 371328a..34b05be 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_rtt.c ++++ b/drivers/net/wireless/bcmdhd/dhd_rtt.c +@@ -1696,6 +1696,10 @@ dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) + return ret; + } + } ++ if (!event_data) { ++ DHD_ERROR(("%s: event_data:NULL\n", __FUNCTION__)); ++ return -EINVAL; ++ } + p_event = (wl_proxd_event_t *) event_data; + version = ltoh16(p_event->version); + if (version < WL_PROXD_API_VERSION) { +@@ -1718,6 +1722,11 @@ dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) + goto exit; /* ignore this event */ + } + /* get TLVs len, skip over event header */ ++ if (ltoh16(p_event->len) < OFFSETOF(wl_proxd_event_t, tlvs)) { ++ DHD_ERROR(("invalid FTM event length:%d\n", ltoh16(p_event->len))); ++ ret = -EINVAL; ++ goto exit; ++ } + tlvs_len = ltoh16(p_event->len) - OFFSETOF(wl_proxd_event_t, tlvs); + DHD_RTT(("receive '%s' event: version=0x%x len=%d method=%d sid=%d tlvs_len=%d\n", + p_loginfo->text, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0794/0.patch b/Patches/Linux_CVEs/CVE-2017-0794/0.patch new file mode 100644 index 00000000..2857497f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0794/0.patch @@ -0,0 +1,164 @@ +From 47b3a105cc4cec0d912345d27d9743b97691b21c Mon Sep 17 00:00:00 2001 +From: Robb Glasser +Date: Fri, 24 Mar 2017 16:23:37 -0700 +Subject: [PATCH] Prevent potential double frees in sg driver + +sg_ioctl could be spammed by requests, leading to a double free in +__free_pages. This protects the entry points of sg_ioctl where the +memory could be corrupted by a double call to __free_pages if multiple +requests are happening concurrently. + +Bug:35644812 + +Change-Id: Ie13f65beb6974430f90292e2742841b26aecb8b1 +Signed-off-by: Robb Glasser +--- + drivers/scsi/sg.c | 34 ++++++++++++++++++++-------------- + 1 file changed, 20 insertions(+), 14 deletions(-) + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 721d839d6c543..9a600f05ab57a 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -486,7 +486,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) + old_hdr->result = EIO; + break; + case DID_ERROR: +- old_hdr->result = (srp->sense_b[0] == 0 && ++ old_hdr->result = (srp->sense_b[0] == 0 && + hp->masked_status == GOOD) ? 0 : EIO; + break; + default: +@@ -832,8 +832,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + return -ENXIO; + if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR)) + return -EFAULT; ++ mutex_lock(&sfp->parentdp->open_rel_lock); + result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR, + 1, read_only, 1, &srp); ++ mutex_unlock(&sfp->parentdp->open_rel_lock); + if (result < 0) + return result; + result = wait_event_interruptible(sfp->read_wait, +@@ -873,8 +875,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + sfp->low_dma = 1; + if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) { + val = (int) sfp->reserve.bufflen; ++ mutex_lock(&sfp->parentdp->open_rel_lock); + sg_remove_scat(&sfp->reserve); + sg_build_reserve(sfp, val); ++ mutex_unlock(&sfp->parentdp->open_rel_lock); + } + } else { + if (sdp->detached) +@@ -942,15 +946,17 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + result = get_user(val, ip); + if (result) + return result; +- if (val < 0) +- return -EINVAL; ++ if (val < 0) ++ return -EINVAL; + val = min_t(int, val, + queue_max_sectors(sdp->device->request_queue) * 512); + if (val != sfp->reserve.bufflen) { + if (sg_res_in_use(sfp) || sfp->mmap_called) + return -EBUSY; ++ mutex_lock(&sfp->parentdp->open_rel_lock); + sg_remove_scat(&sfp->reserve); + sg_build_reserve(sfp, val); ++ mutex_unlock(&sfp->parentdp->open_rel_lock); + } + return 0; + case SG_GET_RESERVED_SIZE: +@@ -1003,8 +1009,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + if (srp) { + rinfo[val].req_state = srp->done + 1; + rinfo[val].problem = +- srp->header.masked_status & +- srp->header.host_status & ++ srp->header.masked_status & ++ srp->header.host_status & + srp->header.driver_status; + if (srp->done) + rinfo[val].duration = +@@ -1025,7 +1031,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + } + } + read_unlock_irqrestore(&sfp->rq_list_lock, iflags); +- result = __copy_to_user(p, rinfo, ++ result = __copy_to_user(p, rinfo, + SZ_SG_REQ_INFO * SG_MAX_QUEUE); + result = result ? -EFAULT : 0; + kfree(rinfo); +@@ -1127,14 +1133,14 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon + return -ENXIO; + + sdev = sdp->device; +- if (sdev->host->hostt->compat_ioctl) { ++ if (sdev->host->hostt->compat_ioctl) { + int ret; + + ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); + + return ret; + } +- ++ + return -ENOIOCTLCMD; + } + #endif +@@ -1594,7 +1600,7 @@ init_sg(void) + else + def_reserved_size = sg_big_buff; + +- rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), ++ rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), + SG_MAX_DEVS, "sg"); + if (rc) + return rc; +@@ -2234,7 +2240,7 @@ static const struct file_operations adio_fops = { + }; + + static int sg_proc_single_open_dressz(struct inode *inode, struct file *file); +-static ssize_t sg_proc_write_dressz(struct file *filp, ++static ssize_t sg_proc_write_dressz(struct file *filp, + const char __user *buffer, size_t count, loff_t *off); + static const struct file_operations dressz_fops = { + .owner = THIS_MODULE, +@@ -2374,7 +2380,7 @@ static int sg_proc_single_open_adio(struct inode *inode, struct file *file) + return single_open(file, sg_proc_seq_show_int, &sg_allow_dio); + } + +-static ssize_t ++static ssize_t + sg_proc_write_adio(struct file *filp, const char __user *buffer, + size_t count, loff_t *off) + { +@@ -2395,7 +2401,7 @@ static int sg_proc_single_open_dressz(struct inode *inode, struct file *file) + return single_open(file, sg_proc_seq_show_int, &sg_big_buff); + } + +-static ssize_t ++static ssize_t + sg_proc_write_dressz(struct file *filp, const char __user *buffer, + size_t count, loff_t *off) + { +@@ -2552,7 +2558,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) + hp = &srp->header; + new_interface = (hp->interface_id == '\0') ? 0 : 1; + if (srp->res_used) { +- if (new_interface && ++ if (new_interface && + (SG_FLAG_MMAP_IO & hp->flags)) + cp = " mmap>> "; + else +@@ -2566,7 +2572,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) + seq_printf(s, cp); + blen = srp->data.bufflen; + usg = srp->data.k_use_sg; +- seq_printf(s, srp->done ? ++ seq_printf(s, srp->done ? + ((1 == srp->done) ? "rcv:" : "fin:") + : "act:"); + seq_printf(s, " id=%d blen=%d", diff --git a/Patches/Linux_CVEs/CVE-2017-0824/0.patch b/Patches/Linux_CVEs/CVE-2017-0824/0.patch new file mode 100644 index 00000000..02283a8b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0824/0.patch @@ -0,0 +1,105 @@ +From 3d6c7b39db34369e28b0581be26f57e9467f8408 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Fri, 7 Jul 2017 14:53:03 -0700 +Subject: net: wireless: bcmdhd: remove SDIO debug IOVARs causing out of bounds + +"sd_devreg" IOVAR can cause out of bounds access when user input +manipulated. Proposed fix is removing debug oriented IOVARs completely. + +Signed-off-by: Insun Song +Bug: 37622847 +Change-Id: I8fc5111fe9d8d2c5d7ae5b1c24ae8e531113beae +--- + drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c | 69 ------------------------------ + 1 file changed, 69 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +index 427298f..a440998 100644 +--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c ++++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +@@ -406,8 +406,6 @@ const bcm_iovar_t sdioh_iovars[] = { + {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 }, + {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 }, + {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 }, +- {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, +- {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, + {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 }, + {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 }, + {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 }, +@@ -608,73 +606,6 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, + bcopy(&int_val, arg, sizeof(int_val)); + break; + +- case IOV_GVAL(IOV_HOSTREG): +- { +- sdreg_t *sd_ptr = (sdreg_t *)params; +- +- if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) { +- sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset)); +- bcmerror = BCME_BADARG; +- break; +- } +- +- sd_trace(("%s: rreg%d at offset %d\n", __FUNCTION__, +- (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32), +- sd_ptr->offset)); +- if (sd_ptr->offset & 1) +- int_val = 8; /* sdioh_sdmmc_rreg8(si, sd_ptr->offset); */ +- else if (sd_ptr->offset & 2) +- int_val = 16; /* sdioh_sdmmc_rreg16(si, sd_ptr->offset); */ +- else +- int_val = 32; /* sdioh_sdmmc_rreg(si, sd_ptr->offset); */ +- +- bcopy(&int_val, arg, sizeof(int_val)); +- break; +- } +- +- case IOV_SVAL(IOV_HOSTREG): +- { +- sdreg_t *sd_ptr = (sdreg_t *)params; +- +- if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) { +- sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset)); +- bcmerror = BCME_BADARG; +- break; +- } +- +- sd_trace(("%s: wreg%d value 0x%08x at offset %d\n", __FUNCTION__, sd_ptr->value, +- (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32), +- sd_ptr->offset)); +- break; +- } +- +- case IOV_GVAL(IOV_DEVREG): +- { +- sdreg_t *sd_ptr = (sdreg_t *)params; +- uint8 data = 0; +- +- if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) { +- bcmerror = BCME_SDIO_ERROR; +- break; +- } +- +- int_val = (int)data; +- bcopy(&int_val, arg, sizeof(int_val)); +- break; +- } +- +- case IOV_SVAL(IOV_DEVREG): +- { +- sdreg_t *sd_ptr = (sdreg_t *)params; +- uint8 data = (uint8)sd_ptr->value; +- +- if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) { +- bcmerror = BCME_SDIO_ERROR; +- break; +- } +- break; +- } +- + default: + bcmerror = BCME_UNSUPPORTED; + break; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-0825/0.patch b/Patches/Linux_CVEs/CVE-2017-0825/0.patch new file mode 100644 index 00000000..c058b66f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-0825/0.patch @@ -0,0 +1,129 @@ +From 83366dd9ddb9337450f704ceef750a06c69df9ff Mon Sep 17 00:00:00 2001 +From: Franky Lin +Date: Wed, 5 Jul 2017 18:04:55 -0700 +Subject: [PATCH] net: wireless: bcmdhd: add log trace event length check + +In log trace event parsing routine, add appropriate length check before +accessing event data to prevent out of boundary memory access + +Bug: 37305633 +Signed-off-by: Franky Lin +Change-Id: I267369957f9b8788f254d9433eb7787b75fb04bc +--- + drivers/net/wireless/bcmdhd/dhd_debug.c | 52 +++++++++++++++++-------- + drivers/net/wireless/bcmdhd/include/event_log.h | 1 + + 2 files changed, 37 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_debug.c b/drivers/net/wireless/bcmdhd/dhd_debug.c +index 3c45ced1ddc4f..70f4e2df3b752 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_debug.c ++++ b/drivers/net/wireless/bcmdhd/dhd_debug.c +@@ -394,6 +394,12 @@ dhd_dbg_custom_evnt_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) + wl_log_id.t = *data; + if (wl_log_id.version != DIAG_VERSION) return BCME_VERSION; + ++ /* custom event log should at least contain a wl_event_log_id_ver_t ++ * header and an arm cycle count ++ */ ++ if (hdr->count < 2) ++ return BCME_BADLEN; ++ + ts_hdr = (void *)data - sizeof(event_log_hdr_t); + if (ts_hdr->tag == EVENT_LOG_TAG_TS) { + ts_data = (uint32 *)ts_hdr - ts_hdr->count; +@@ -624,7 +630,8 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, + msgtrace_hdr_t *hdr; + char *data; + int id; +- uint32 hdrlen = sizeof(event_log_hdr_t); ++ const uint32 log_hdr_len = sizeof(event_log_hdr_t); ++ uint32 log_pyld_len; + static uint32 seqnum_prev = 0; + event_log_hdr_t *log_hdr; + bool event_type = FALSE; +@@ -632,6 +639,13 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, + dll_t list_head, *cur; + loglist_item_t *log_item; + ++ /* log trace event consists of ++ * msgtrace header ++ * event log block header ++ * event log payload ++ */ ++ if (datalen <= MSGTRACE_HDRLEN + EVENT_LOG_BLOCK_HDRLEN) ++ return; + hdr = (msgtrace_hdr_t *)event_data; + data = (char *)event_data + MSGTRACE_HDRLEN; + datalen -= MSGTRACE_HDRLEN; +@@ -640,30 +654,36 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, + return; + + /* XXX: skip the meaningless pktlen/count and timestamp */ +- data += 8; +- datalen -= 8; ++ data += EVENT_LOG_BLOCK_HDRLEN; ++ datalen -= EVENT_LOG_BLOCK_HDRLEN; + + /* start from the end and walk through the packet */ + dll_init(&list_head); +- while (datalen > 0) { +- log_hdr = (event_log_hdr_t *)(data + datalen - hdrlen); +- /* pratially overwritten entries */ +- if ((uint32 *)log_hdr - (uint32 *)data < log_hdr->count) +- break; +- /* end of frame? */ ++ while (datalen > log_hdr_len) { ++ log_hdr = (event_log_hdr_t *)(data + datalen - log_hdr_len); ++ /* skip zero padding at end of frame */ + if (log_hdr->tag == EVENT_LOG_TAG_NULL) { +- log_hdr--; +- datalen -= hdrlen; ++ datalen -= log_hdr_len; + continue; + } ++ ++ /* Check argument count, any event log should contain at least ++ * one argument (4 bytes) for arm cycle count and up to 16 ++ * arguments ++ */ ++ if ((log_hdr->count == 0) || (log_hdr->count > MAX_NO_OF_ARG)) ++ break; ++ ++ log_pyld_len = log_hdr->count * DATA_UNIT_FOR_LOG_CNT; ++ /* log data should not cross event data boundary */ ++ if (((char *)log_hdr - data) < log_pyld_len) ++ break; ++ + /* skip 4 bytes time stamp packet */ + if (log_hdr->tag == EVENT_LOG_TAG_TS) { +- datalen -= log_hdr->count * 4 + hdrlen; +- log_hdr -= log_hdr->count + hdrlen / 4; ++ datalen -= log_pyld_len + log_hdr_len; + continue; + } +- if (log_hdr->count > MAX_NO_OF_ARG) +- break; + if (!(log_item = MALLOC(dhdp->osh, sizeof(*log_item)))) { + DHD_ERROR(("%s allocating log list item failed\n", + __FUNCTION__)); +@@ -671,7 +691,7 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, + } + log_item->hdr = log_hdr; + dll_insert(&log_item->list, &list_head); +- datalen -= (log_hdr->count * 4 + hdrlen); ++ datalen -= (log_pyld_len + log_hdr_len); + } + + while (!dll_empty(&list_head)) { +diff --git a/drivers/net/wireless/bcmdhd/include/event_log.h b/drivers/net/wireless/bcmdhd/include/event_log.h +index 6f0bbc4e40ec1..3964d203d2fb9 100644 +--- a/drivers/net/wireless/bcmdhd/include/event_log.h ++++ b/drivers/net/wireless/bcmdhd/include/event_log.h +@@ -141,6 +141,7 @@ + #define LOGSTRS_MAGIC 0x4C4F4753 + #define LOGSTRS_VERSION 0x1 + ++#define EVENT_LOG_BLOCK_HDRLEN 8 + + /* + * There are multiple levels of objects define here: diff --git a/Patches/Linux_CVEs/CVE-2017-1000251/0.patch b/Patches/Linux_CVEs/CVE-2017-1000251/0.patch new file mode 100644 index 00000000..c6bfdf71 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-1000251/0.patch @@ -0,0 +1,357 @@ +From e860d2c904d1a9f38a24eb44c9f34b8f915a6ea3 Mon Sep 17 00:00:00 2001 +From: Ben Seri +Date: Sat, 9 Sep 2017 23:15:59 +0200 +Subject: Bluetooth: Properly check L2CAP config option output buffer length + +Validate the output buffer length for L2CAP config requests and responses +to avoid overflowing the stack buffer used for building the option blocks. + +Cc: stable@vger.kernel.org +Signed-off-by: Ben Seri +Signed-off-by: Marcel Holtmann +Signed-off-by: Linus Torvalds +--- + net/bluetooth/l2cap_core.c | 80 +++++++++++++++++++++++++--------------------- + 1 file changed, 43 insertions(+), 37 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 303c779..43ba91c 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -58,7 +58,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, + u8 code, u8 ident, u16 dlen, void *data); + static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, + void *data); +-static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); ++static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size); + static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); + + static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, +@@ -1473,7 +1473,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) + + set_bit(CONF_REQ_SENT, &chan->conf_state); + l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, +- l2cap_build_conf_req(chan, buf), buf); ++ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + chan->num_conf_req++; + } + +@@ -2987,12 +2987,15 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, + return len; + } + +-static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) ++static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size) + { + struct l2cap_conf_opt *opt = *ptr; + + BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val); + ++ if (size < L2CAP_CONF_OPT_SIZE + len) ++ return; ++ + opt->type = type; + opt->len = len; + +@@ -3017,7 +3020,7 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val) + *ptr += L2CAP_CONF_OPT_SIZE + len; + } + +-static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) ++static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size) + { + struct l2cap_conf_efs efs; + +@@ -3045,7 +3048,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) + } + + l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), +- (unsigned long) &efs); ++ (unsigned long) &efs, size); + } + + static void l2cap_ack_timeout(struct work_struct *work) +@@ -3191,11 +3194,12 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan) + chan->ack_win = chan->tx_win; + } + +-static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) ++static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) + { + struct l2cap_conf_req *req = data; + struct l2cap_conf_rfc rfc = { .mode = chan->mode }; + void *ptr = req->data; ++ void *endptr = data + data_size; + u16 size; + + BT_DBG("chan %p", chan); +@@ -3220,7 +3224,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data) + + done: + if (chan->imtu != L2CAP_DEFAULT_MTU) +- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); ++ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr); + + switch (chan->mode) { + case L2CAP_MODE_BASIC: +@@ -3239,7 +3243,7 @@ done: + rfc.max_pdu_size = 0; + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), +- (unsigned long) &rfc); ++ (unsigned long) &rfc, endptr - ptr); + break; + + case L2CAP_MODE_ERTM: +@@ -3259,21 +3263,21 @@ done: + L2CAP_DEFAULT_TX_WINDOW); + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), +- (unsigned long) &rfc); ++ (unsigned long) &rfc, endptr - ptr); + + if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) +- l2cap_add_opt_efs(&ptr, chan); ++ l2cap_add_opt_efs(&ptr, chan, endptr - ptr); + + if (test_bit(FLAG_EXT_CTRL, &chan->flags)) + l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, +- chan->tx_win); ++ chan->tx_win, endptr - ptr); + + if (chan->conn->feat_mask & L2CAP_FEAT_FCS) + if (chan->fcs == L2CAP_FCS_NONE || + test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { + chan->fcs = L2CAP_FCS_NONE; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, +- chan->fcs); ++ chan->fcs, endptr - ptr); + } + break; + +@@ -3291,17 +3295,17 @@ done: + rfc.max_pdu_size = cpu_to_le16(size); + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), +- (unsigned long) &rfc); ++ (unsigned long) &rfc, endptr - ptr); + + if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) +- l2cap_add_opt_efs(&ptr, chan); ++ l2cap_add_opt_efs(&ptr, chan, endptr - ptr); + + if (chan->conn->feat_mask & L2CAP_FEAT_FCS) + if (chan->fcs == L2CAP_FCS_NONE || + test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) { + chan->fcs = L2CAP_FCS_NONE; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, +- chan->fcs); ++ chan->fcs, endptr - ptr); + } + break; + } +@@ -3312,10 +3316,11 @@ done: + return ptr - data; + } + +-static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) ++static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size) + { + struct l2cap_conf_rsp *rsp = data; + void *ptr = rsp->data; ++ void *endptr = data + data_size; + void *req = chan->conf_req; + int len = chan->conf_len; + int type, hint, olen; +@@ -3417,7 +3422,7 @@ done: + return -ECONNREFUSED; + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), +- (unsigned long) &rfc); ++ (unsigned long) &rfc, endptr - ptr); + } + + if (result == L2CAP_CONF_SUCCESS) { +@@ -3430,7 +3435,7 @@ done: + chan->omtu = mtu; + set_bit(CONF_MTU_DONE, &chan->conf_state); + } +- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); ++ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr); + + if (remote_efs) { + if (chan->local_stype != L2CAP_SERV_NOTRAFIC && +@@ -3444,7 +3449,7 @@ done: + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, + sizeof(efs), +- (unsigned long) &efs); ++ (unsigned long) &efs, endptr - ptr); + } else { + /* Send PENDING Conf Rsp */ + result = L2CAP_CONF_PENDING; +@@ -3477,7 +3482,7 @@ done: + set_bit(CONF_MODE_DONE, &chan->conf_state); + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, +- sizeof(rfc), (unsigned long) &rfc); ++ sizeof(rfc), (unsigned long) &rfc, endptr - ptr); + + if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { + chan->remote_id = efs.id; +@@ -3491,7 +3496,7 @@ done: + le32_to_cpu(efs.sdu_itime); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, + sizeof(efs), +- (unsigned long) &efs); ++ (unsigned long) &efs, endptr - ptr); + } + break; + +@@ -3505,7 +3510,7 @@ done: + set_bit(CONF_MODE_DONE, &chan->conf_state); + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), +- (unsigned long) &rfc); ++ (unsigned long) &rfc, endptr - ptr); + + break; + +@@ -3527,10 +3532,11 @@ done: + } + + static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, +- void *data, u16 *result) ++ void *data, size_t size, u16 *result) + { + struct l2cap_conf_req *req = data; + void *ptr = req->data; ++ void *endptr = data + size; + int type, olen; + unsigned long val; + struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; +@@ -3548,13 +3554,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, + chan->imtu = L2CAP_DEFAULT_MIN_MTU; + } else + chan->imtu = val; +- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu); ++ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr); + break; + + case L2CAP_CONF_FLUSH_TO: + chan->flush_to = val; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, +- 2, chan->flush_to); ++ 2, chan->flush_to, endptr - ptr); + break; + + case L2CAP_CONF_RFC: +@@ -3568,13 +3574,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, + chan->fcs = 0; + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, +- sizeof(rfc), (unsigned long) &rfc); ++ sizeof(rfc), (unsigned long) &rfc, endptr - ptr); + break; + + case L2CAP_CONF_EWS: + chan->ack_win = min_t(u16, val, chan->ack_win); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, +- chan->tx_win); ++ chan->tx_win, endptr - ptr); + break; + + case L2CAP_CONF_EFS: +@@ -3587,7 +3593,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, + return -ECONNREFUSED; + + l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), +- (unsigned long) &efs); ++ (unsigned long) &efs, endptr - ptr); + break; + + case L2CAP_CONF_FCS: +@@ -3692,7 +3698,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) + return; + + l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, +- l2cap_build_conf_req(chan, buf), buf); ++ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + chan->num_conf_req++; + } + +@@ -3900,7 +3906,7 @@ sendresp: + u8 buf[128]; + set_bit(CONF_REQ_SENT, &chan->conf_state); + l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, +- l2cap_build_conf_req(chan, buf), buf); ++ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + chan->num_conf_req++; + } + +@@ -3978,7 +3984,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, + break; + + l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, +- l2cap_build_conf_req(chan, req), req); ++ l2cap_build_conf_req(chan, req, sizeof(req)), req); + chan->num_conf_req++; + break; + +@@ -4090,7 +4096,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + } + + /* Complete config. */ +- len = l2cap_parse_conf_req(chan, rsp); ++ len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp)); + if (len < 0) { + l2cap_send_disconn_req(chan, ECONNRESET); + goto unlock; +@@ -4124,7 +4130,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, + if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { + u8 buf[64]; + l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, +- l2cap_build_conf_req(chan, buf), buf); ++ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + chan->num_conf_req++; + } + +@@ -4184,7 +4190,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, + char buf[64]; + + len = l2cap_parse_conf_rsp(chan, rsp->data, len, +- buf, &result); ++ buf, sizeof(buf), &result); + if (len < 0) { + l2cap_send_disconn_req(chan, ECONNRESET); + goto done; +@@ -4214,7 +4220,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, + /* throw out any old stored conf requests */ + result = L2CAP_CONF_SUCCESS; + len = l2cap_parse_conf_rsp(chan, rsp->data, len, +- req, &result); ++ req, sizeof(req), &result); + if (len < 0) { + l2cap_send_disconn_req(chan, ECONNRESET); + goto done; +@@ -4791,7 +4797,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result, + set_bit(CONF_REQ_SENT, &chan->conf_state); + l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), + L2CAP_CONF_REQ, +- l2cap_build_conf_req(chan, buf), buf); ++ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf); + chan->num_conf_req++; + } + } +@@ -7465,7 +7471,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) + set_bit(CONF_REQ_SENT, &chan->conf_state); + l2cap_send_cmd(conn, l2cap_get_ident(conn), + L2CAP_CONF_REQ, +- l2cap_build_conf_req(chan, buf), ++ l2cap_build_conf_req(chan, buf, sizeof(buf)), + buf); + chan->num_conf_req++; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-1000364/0.patch b/Patches/Linux_CVEs/CVE-2017-1000364/0.patch new file mode 100644 index 00000000..88454e1f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-1000364/0.patch @@ -0,0 +1,874 @@ +From d4712eb79b17d85c9e354efa2d3156ce50736128 Mon Sep 17 00:00:00 2001 +From: Hugh Dickins +Date: Mon, 19 Jun 2017 04:03:24 -0700 +Subject: mm: larger stack guard gap, between vmas + +commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream. + +Stack guard page is a useful feature to reduce a risk of stack smashing +into a different mapping. We have been using a single page gap which +is sufficient to prevent having stack adjacent to a different mapping. +But this seems to be insufficient in the light of the stack usage in +userspace. E.g. glibc uses as large as 64kB alloca() in many commonly +used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX] +which is 256kB or stack strings with MAX_ARG_STRLEN. + +This will become especially dangerous for suid binaries and the default +no limit for the stack size limit because those applications can be +tricked to consume a large portion of the stack and a single glibc call +could jump over the guard page. These attacks are not theoretical, +unfortunatelly. + +Make those attacks less probable by increasing the stack guard gap +to 1MB (on systems with 4k pages; but make it depend on the page size +because systems with larger base pages might cap stack allocations in +the PAGE_SIZE units) which should cover larger alloca() and VLA stack +allocations. It is obviously not a full fix because the problem is +somehow inherent, but it should reduce attack space a lot. + +One could argue that the gap size should be configurable from userspace, +but that can be done later when somebody finds that the new 1MB is wrong +for some special case applications. For now, add a kernel command line +option (stack_guard_gap) to specify the stack gap size (in page units). + +Implementation wise, first delete all the old code for stack guard page: +because although we could get away with accounting one extra page in a +stack vma, accounting a larger gap can break userspace - case in point, +a program run with "ulimit -S -v 20000" failed when the 1MB gap was +counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK +and strict non-overcommit mode. + +Instead of keeping gap inside the stack vma, maintain the stack guard +gap as a gap between vmas: using vm_start_gap() in place of vm_start +(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few +places which need to respect the gap - mainly arch_get_unmapped_area(), +and and the vma tree's subtree_gap support for that. + +Original-patch-by: Oleg Nesterov +Original-patch-by: Michal Hocko +Signed-off-by: Hugh Dickins +Acked-by: Michal Hocko +Tested-by: Helge Deller # parisc +Signed-off-by: Linus Torvalds +[wt: backport to 4.11: adjust context] +[wt: backport to 4.9: adjust context ; kernel doc was not in admin-guide] +[wt: backport to 4.4: adjust context ; drop ppc hugetlb_radix changes] +[wt: backport to 3.18: adjust context ; no FOLL_POPULATE ; + s390 uses generic arch_get_unmapped_area()] +Signed-off-by: Willy Tarreau +[gkh: minor build fixes for 3.18] +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/kernel-parameters.txt | 7 ++ + arch/arc/mm/mmap.c | 2 +- + arch/arm/mm/mmap.c | 4 +- + arch/frv/mm/elf-fdpic.c | 2 +- + arch/mips/mm/mmap.c | 2 +- + arch/parisc/kernel/sys_parisc.c | 15 ++-- + arch/powerpc/mm/slice.c | 2 +- + arch/sh/mm/mmap.c | 4 +- + arch/sparc/kernel/sys_sparc_64.c | 4 +- + arch/sparc/mm/hugetlbpage.c | 2 +- + arch/tile/mm/hugetlbpage.c | 2 +- + arch/x86/kernel/sys_x86_64.c | 4 +- + arch/x86/mm/hugetlbpage.c | 2 +- + arch/xtensa/kernel/syscall.c | 2 +- + fs/hugetlbfs/inode.c | 2 +- + fs/proc/task_mmu.c | 4 - + include/linux/mm.h | 53 ++++++------- + mm/gup.c | 5 -- + mm/memory.c | 38 --------- + mm/mmap.c | 149 +++++++++++++++++++++--------------- + 20 files changed, 147 insertions(+), 158 deletions(-) + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index b2bdea19..9abe552 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -3324,6 +3324,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + spia_pedr= + spia_peddr= + ++ stack_guard_gap= [MM] ++ override the default stack gap protection. The value ++ is in page units and it defines how many pages prior ++ to (for stacks growing down) resp. after (for stacks ++ growing up) the main stack are reserved for no other ++ mapping. Default value is 256 pages. ++ + stacktrace [FTRACE] + Enabled the stack tracer on boot up. + +diff --git a/arch/arc/mm/mmap.c b/arch/arc/mm/mmap.c +index 2e06d56..cf4ae69 100644 +--- a/arch/arc/mm/mmap.c ++++ b/arch/arc/mm/mmap.c +@@ -64,7 +64,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c +index 5e85ed3..8f9d1cf 100644 +--- a/arch/arm/mm/mmap.c ++++ b/arch/arm/mm/mmap.c +@@ -89,7 +89,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -140,7 +140,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c +index 836f1470..efa59f1 100644 +--- a/arch/frv/mm/elf-fdpic.c ++++ b/arch/frv/mm/elf-fdpic.c +@@ -74,7 +74,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + addr = PAGE_ALIGN(addr); + vma = find_vma(current->mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + goto success; + } + +diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c +index f1baadd..9be924f 100644 +--- a/arch/mips/mm/mmap.c ++++ b/arch/mips/mm/mmap.c +@@ -92,7 +92,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c +index 5aba01a..4dda73c 100644 +--- a/arch/parisc/kernel/sys_parisc.c ++++ b/arch/parisc/kernel/sys_parisc.c +@@ -88,7 +88,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) + { + struct mm_struct *mm = current->mm; +- struct vm_area_struct *vma; ++ struct vm_area_struct *vma, *prev; + unsigned long task_size = TASK_SIZE; + int do_color_align, last_mmap; + struct vm_unmapped_area_info info; +@@ -115,9 +115,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + else + addr = PAGE_ALIGN(addr); + +- vma = find_vma(mm, addr); ++ vma = find_vma_prev(mm, addr, &prev); + if (task_size - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma)) && ++ (!prev || addr >= vm_end_gap(prev))) + goto found_addr; + } + +@@ -141,7 +142,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, const unsigned long pgoff, + const unsigned long flags) + { +- struct vm_area_struct *vma; ++ struct vm_area_struct *vma, *prev; + struct mm_struct *mm = current->mm; + unsigned long addr = addr0; + int do_color_align, last_mmap; +@@ -175,9 +176,11 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + addr = COLOR_ALIGN(addr, last_mmap, pgoff); + else + addr = PAGE_ALIGN(addr); +- vma = find_vma(mm, addr); ++ ++ vma = find_vma_prev(mm, addr, &prev); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma)) && ++ (!prev || addr >= vm_end_gap(prev))) + goto found_addr; + } + +diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c +index ded0ea1..4c14626 100644 +--- a/arch/powerpc/mm/slice.c ++++ b/arch/powerpc/mm/slice.c +@@ -105,7 +105,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr, + if ((mm->task_size - len) < addr) + return 0; + vma = find_vma(mm, addr); +- return (!vma || (addr + len) <= vma->vm_start); ++ return (!vma || (addr + len) <= vm_start_gap(vma)); + } + + static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice) +diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c +index 6777177..7df7d59 100644 +--- a/arch/sh/mm/mmap.c ++++ b/arch/sh/mm/mmap.c +@@ -63,7 +63,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -113,7 +113,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c +index c690c8e..7f0f7c01 100644 +--- a/arch/sparc/kernel/sys_sparc_64.c ++++ b/arch/sparc/kernel/sys_sparc_64.c +@@ -118,7 +118,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + + vma = find_vma(mm, addr); + if (task_size - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -181,7 +181,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + + vma = find_vma(mm, addr); + if (task_size - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c +index 4242eab..2b6fae6 100644 +--- a/arch/sparc/mm/hugetlbpage.c ++++ b/arch/sparc/mm/hugetlbpage.c +@@ -115,7 +115,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + addr = ALIGN(addr, HPAGE_SIZE); + vma = find_vma(mm, addr); + if (task_size - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + if (mm->get_unmapped_area == arch_get_unmapped_area) +diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c +index 8a00c7b..52deac2 100644 +--- a/arch/tile/mm/hugetlbpage.c ++++ b/arch/tile/mm/hugetlbpage.c +@@ -237,7 +237,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + addr = ALIGN(addr, huge_page_size(h)); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + if (current->mm->get_unmapped_area == arch_get_unmapped_area) +diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c +index 30277e2..d050393 100644 +--- a/arch/x86/kernel/sys_x86_64.c ++++ b/arch/x86/kernel/sys_x86_64.c +@@ -127,7 +127,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (end - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -166,7 +166,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c +index 9161f76..c504866 100644 +--- a/arch/x86/mm/hugetlbpage.c ++++ b/arch/x86/mm/hugetlbpage.c +@@ -144,7 +144,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + addr = ALIGN(addr, huge_page_size(h)); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + if (mm->get_unmapped_area == arch_get_unmapped_area) +diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c +index 5d3f7a1..1ff0b92 100644 +--- a/arch/xtensa/kernel/syscall.c ++++ b/arch/xtensa/kernel/syscall.c +@@ -86,7 +86,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + /* At this point: (!vmm || addr < vmm->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; +- if (!vmm || addr + len <= vmm->vm_start) ++ if (!vmm || addr + len <= vm_start_gap(vmm)) + return addr; + addr = vmm->vm_end; + if (flags & MAP_SHARED) +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index 1e2872b..148c4e9 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -171,7 +171,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + addr = ALIGN(addr, huge_page_size(h)); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index af33fb7..aea2d0b 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -284,11 +284,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) + + /* We don't show the stack guard page in /proc/maps */ + start = vma->vm_start; +- if (stack_guard_page_start(vma, start)) +- start += PAGE_SIZE; + end = vma->vm_end; +- if (stack_guard_page_end(vma, end)) +- end -= PAGE_SIZE; + + seq_setwidth(m, 25 + sizeof(void *) * 6 - 1); + seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ", +diff --git a/include/linux/mm.h b/include/linux/mm.h +index db853de..54ad2e4 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1242,34 +1242,6 @@ int set_page_dirty_lock(struct page *page); + int clear_page_dirty_for_io(struct page *page); + int get_cmdline(struct task_struct *task, char *buffer, int buflen); + +-/* Is the vma a continuation of the stack vma above it? */ +-static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) +-{ +- return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); +-} +- +-static inline int stack_guard_page_start(struct vm_area_struct *vma, +- unsigned long addr) +-{ +- return (vma->vm_flags & VM_GROWSDOWN) && +- (vma->vm_start == addr) && +- !vma_growsdown(vma->vm_prev, addr); +-} +- +-/* Is the vma a continuation of the stack vma below it? */ +-static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr) +-{ +- return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP); +-} +- +-static inline int stack_guard_page_end(struct vm_area_struct *vma, +- unsigned long addr) +-{ +- return (vma->vm_flags & VM_GROWSUP) && +- (vma->vm_end == addr) && +- !vma_growsup(vma->vm_next, addr); +-} +- + extern struct task_struct *task_of_stack(struct task_struct *task, + struct vm_area_struct *vma, bool in_group); + +@@ -1930,6 +1902,7 @@ void page_cache_async_readahead(struct address_space *mapping, + + unsigned long max_sane_readahead(unsigned long nr); + ++extern unsigned long stack_guard_gap; + /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */ + extern int expand_stack(struct vm_area_struct *vma, unsigned long address); + +@@ -1958,6 +1931,30 @@ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * m + return vma; + } + ++static inline unsigned long vm_start_gap(struct vm_area_struct *vma) ++{ ++ unsigned long vm_start = vma->vm_start; ++ ++ if (vma->vm_flags & VM_GROWSDOWN) { ++ vm_start -= stack_guard_gap; ++ if (vm_start > vma->vm_start) ++ vm_start = 0; ++ } ++ return vm_start; ++} ++ ++static inline unsigned long vm_end_gap(struct vm_area_struct *vma) ++{ ++ unsigned long vm_end = vma->vm_end; ++ ++ if (vma->vm_flags & VM_GROWSUP) { ++ vm_end += stack_guard_gap; ++ if (vm_end < vma->vm_end) ++ vm_end = -PAGE_SIZE; ++ } ++ return vm_end; ++} ++ + static inline unsigned long vma_pages(struct vm_area_struct *vma) + { + return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; +diff --git a/mm/gup.c b/mm/gup.c +index 3cec4df..ce1630b 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -275,11 +275,6 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, + unsigned int fault_flags = 0; + int ret; + +- /* For mlock, just skip the stack guard page. */ +- if ((*flags & FOLL_MLOCK) && +- (stack_guard_page_start(vma, address) || +- stack_guard_page_end(vma, address + PAGE_SIZE))) +- return -ENOENT; + if (*flags & FOLL_WRITE) + fault_flags |= FAULT_FLAG_WRITE; + if (nonblocking) +diff --git a/mm/memory.c b/mm/memory.c +index 6ca26c3..0c4f5e3 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -2580,40 +2580,6 @@ out_release: + } + + /* +- * This is like a special single-page "expand_{down|up}wards()", +- * except we must first make sure that 'address{-|+}PAGE_SIZE' +- * doesn't hit another vma. +- */ +-static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) +-{ +- address &= PAGE_MASK; +- if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { +- struct vm_area_struct *prev = vma->vm_prev; +- +- /* +- * Is there a mapping abutting this one below? +- * +- * That's only ok if it's the same stack mapping +- * that has gotten split.. +- */ +- if (prev && prev->vm_end == address) +- return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; +- +- return expand_downwards(vma, address - PAGE_SIZE); +- } +- if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { +- struct vm_area_struct *next = vma->vm_next; +- +- /* As VM_GROWSDOWN but s/below/above/ */ +- if (next && next->vm_start == address + PAGE_SIZE) +- return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; +- +- return expand_upwards(vma, address + PAGE_SIZE); +- } +- return 0; +-} +- +-/* + * We enter with non-exclusive mmap_sem (to exclude vma changes, + * but allow concurrent faults), and pte mapped but not yet locked. + * We return with mmap_sem still held, but pte unmapped and unlocked. +@@ -2633,10 +2599,6 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, + if (vma->vm_flags & VM_SHARED) + return VM_FAULT_SIGBUS; + +- /* Check if we need to add a guard page to the stack */ +- if (check_stack_guard_page(vma, address) < 0) +- return VM_FAULT_SIGSEGV; +- + /* Use the zero-page for reads */ + if (!(flags & FAULT_FLAG_WRITE)) { + entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), +diff --git a/mm/mmap.c b/mm/mmap.c +index f032671..14ccc94 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -290,6 +290,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) + unsigned long retval; + unsigned long newbrk, oldbrk; + struct mm_struct *mm = current->mm; ++ struct vm_area_struct *next; + unsigned long min_brk; + bool populate; + +@@ -334,7 +335,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) + } + + /* Check against existing mmap mappings. */ +- if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) ++ next = find_vma(mm, oldbrk); ++ if (next && newbrk + PAGE_SIZE > vm_start_gap(next)) + goto out; + + /* Ok, looks good - let it rip. */ +@@ -357,10 +359,22 @@ out: + + static long vma_compute_subtree_gap(struct vm_area_struct *vma) + { +- unsigned long max, subtree_gap; +- max = vma->vm_start; +- if (vma->vm_prev) +- max -= vma->vm_prev->vm_end; ++ unsigned long max, prev_end, subtree_gap; ++ ++ /* ++ * Note: in the rare case of a VM_GROWSDOWN above a VM_GROWSUP, we ++ * allow two stack_guard_gaps between them here, and when choosing ++ * an unmapped area; whereas when expanding we only require one. ++ * That's a little inconsistent, but keeps the code here simpler. ++ */ ++ max = vm_start_gap(vma); ++ if (vma->vm_prev) { ++ prev_end = vm_end_gap(vma->vm_prev); ++ if (max > prev_end) ++ max -= prev_end; ++ else ++ max = 0; ++ } + if (vma->vm_rb.rb_left) { + subtree_gap = rb_entry(vma->vm_rb.rb_left, + struct vm_area_struct, vm_rb)->rb_subtree_gap; +@@ -453,7 +467,7 @@ static void validate_mm(struct mm_struct *mm) + anon_vma_unlock_read(anon_vma); + } + +- highest_address = vma->vm_end; ++ highest_address = vm_end_gap(vma); + vma = vma->vm_next; + i++; + } +@@ -622,7 +636,7 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma, + if (vma->vm_next) + vma_gap_update(vma->vm_next); + else +- mm->highest_vm_end = vma->vm_end; ++ mm->highest_vm_end = vm_end_gap(vma); + + /* + * vma->vm_prev wasn't known when we followed the rbtree to find the +@@ -874,7 +888,7 @@ again: remove_next = 1 + (end > next->vm_end); + vma_gap_update(vma); + if (end_changed) { + if (!next) +- mm->highest_vm_end = end; ++ mm->highest_vm_end = vm_end_gap(vma); + else if (!adjust_next) + vma_gap_update(next); + } +@@ -917,7 +931,7 @@ again: remove_next = 1 + (end > next->vm_end); + else if (next) + vma_gap_update(next); + else +- mm->highest_vm_end = end; ++ VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma)); + } + if (insert && file) + uprobe_mmap(insert); +@@ -1740,7 +1754,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) + + while (true) { + /* Visit left subtree if it looks promising */ +- gap_end = vma->vm_start; ++ gap_end = vm_start_gap(vma); + if (gap_end >= low_limit && vma->vm_rb.rb_left) { + struct vm_area_struct *left = + rb_entry(vma->vm_rb.rb_left, +@@ -1751,7 +1765,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info) + } + } + +- gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; ++ gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0; + check_current: + /* Check if current node has a suitable gap */ + if (gap_start > high_limit) +@@ -1778,8 +1792,8 @@ check_current: + vma = rb_entry(rb_parent(prev), + struct vm_area_struct, vm_rb); + if (prev == vma->vm_rb.rb_left) { +- gap_start = vma->vm_prev->vm_end; +- gap_end = vma->vm_start; ++ gap_start = vm_end_gap(vma->vm_prev); ++ gap_end = vm_start_gap(vma); + goto check_current; + } + } +@@ -1843,7 +1857,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info) + + while (true) { + /* Visit right subtree if it looks promising */ +- gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0; ++ gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0; + if (gap_start <= high_limit && vma->vm_rb.rb_right) { + struct vm_area_struct *right = + rb_entry(vma->vm_rb.rb_right, +@@ -1856,7 +1870,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info) + + check_current: + /* Check if current node has a suitable gap */ +- gap_end = vma->vm_start; ++ gap_end = vm_start_gap(vma); + if (gap_end < low_limit) + return -ENOMEM; + if (gap_start <= high_limit && gap_end - gap_start >= length) +@@ -1882,7 +1896,7 @@ check_current: + struct vm_area_struct, vm_rb); + if (prev == vma->vm_rb.rb_right) { + gap_start = vma->vm_prev ? +- vma->vm_prev->vm_end : 0; ++ vm_end_gap(vma->vm_prev) : 0; + goto check_current; + } + } +@@ -1920,7 +1934,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) + { + struct mm_struct *mm = current->mm; +- struct vm_area_struct *vma; ++ struct vm_area_struct *vma, *prev; + struct vm_unmapped_area_info info; + + if (len > TASK_SIZE - mmap_min_addr) +@@ -1931,9 +1945,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + + if (addr) { + addr = PAGE_ALIGN(addr); +- vma = find_vma(mm, addr); ++ vma = find_vma_prev(mm, addr, &prev); + if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma)) && ++ (!prev || addr >= vm_end_gap(prev))) + return addr; + } + +@@ -1956,7 +1971,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, const unsigned long pgoff, + const unsigned long flags) + { +- struct vm_area_struct *vma; ++ struct vm_area_struct *vma, *prev; + struct mm_struct *mm = current->mm; + unsigned long addr = addr0; + struct vm_unmapped_area_info info; +@@ -1971,9 +1986,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + /* requesting a specific address */ + if (addr) { + addr = PAGE_ALIGN(addr); +- vma = find_vma(mm, addr); ++ vma = find_vma_prev(mm, addr, &prev); + if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma)) && ++ (!prev || addr >= vm_end_gap(prev))) + return addr; + } + +@@ -2099,21 +2115,19 @@ find_vma_prev(struct mm_struct *mm, unsigned long addr, + * update accounting. This is shared with both the + * grow-up and grow-down cases. + */ +-static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow) ++static int acct_stack_growth(struct vm_area_struct *vma, ++ unsigned long size, unsigned long grow) + { + struct mm_struct *mm = vma->vm_mm; + struct rlimit *rlim = current->signal->rlim; +- unsigned long new_start, actual_size; ++ unsigned long new_start; + + /* address space limit tests */ + if (!may_expand_vm(mm, grow)) + return -ENOMEM; + + /* Stack limit test */ +- actual_size = size; +- if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN))) +- actual_size -= PAGE_SIZE; +- if (actual_size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) ++ if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) + return -ENOMEM; + + /* mlock limit tests */ +@@ -2154,17 +2168,30 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns + */ + int expand_upwards(struct vm_area_struct *vma, unsigned long address) + { ++ struct vm_area_struct *next; ++ unsigned long gap_addr; + int error = 0; + + if (!(vma->vm_flags & VM_GROWSUP)) + return -EFAULT; + + /* Guard against wrapping around to address 0. */ +- if (address < PAGE_ALIGN(address+4)) +- address = PAGE_ALIGN(address+4); +- else ++ address &= PAGE_MASK; ++ address += PAGE_SIZE; ++ if (!address) + return -ENOMEM; + ++ /* Enforce stack_guard_gap */ ++ gap_addr = address + stack_guard_gap; ++ if (gap_addr < address) ++ return -ENOMEM; ++ next = vma->vm_next; ++ if (next && next->vm_start < gap_addr) { ++ if (!(next->vm_flags & VM_GROWSUP)) ++ return -ENOMEM; ++ /* Check that both stack segments have the same anon_vma? */ ++ } ++ + /* We must make sure the anon_vma is allocated. */ + if (unlikely(anon_vma_prepare(vma))) + return -ENOMEM; +@@ -2205,7 +2232,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) + if (vma->vm_next) + vma_gap_update(vma->vm_next); + else +- vma->vm_mm->highest_vm_end = address; ++ vma->vm_mm->highest_vm_end = vm_end_gap(vma); + spin_unlock(&vma->vm_mm->page_table_lock); + + perf_event_mmap(vma); +@@ -2225,6 +2252,8 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) + int expand_downwards(struct vm_area_struct *vma, + unsigned long address) + { ++ struct vm_area_struct *prev; ++ unsigned long gap_addr; + int error; + + address &= PAGE_MASK; +@@ -2232,6 +2261,17 @@ int expand_downwards(struct vm_area_struct *vma, + if (error) + return error; + ++ /* Enforce stack_guard_gap */ ++ gap_addr = address - stack_guard_gap; ++ if (gap_addr > address) ++ return -ENOMEM; ++ prev = vma->vm_prev; ++ if (prev && prev->vm_end > gap_addr) { ++ if (!(prev->vm_flags & VM_GROWSDOWN)) ++ return -ENOMEM; ++ /* Check that both stack segments have the same anon_vma? */ ++ } ++ + /* We must make sure the anon_vma is allocated. */ + if (unlikely(anon_vma_prepare(vma))) + return -ENOMEM; +@@ -2283,28 +2323,25 @@ int expand_downwards(struct vm_area_struct *vma, + return error; + } + +-/* +- * Note how expand_stack() refuses to expand the stack all the way to +- * abut the next virtual mapping, *unless* that mapping itself is also +- * a stack mapping. We want to leave room for a guard page, after all +- * (the guard page itself is not added here, that is done by the +- * actual page faulting logic) +- * +- * This matches the behavior of the guard page logic (see mm/memory.c: +- * check_stack_guard_page()), which only allows the guard page to be +- * removed under these circumstances. +- */ ++/* enforced gap between the expanding stack and other mappings. */ ++unsigned long stack_guard_gap = 256UL< +Debugged-by: Linus Torvalds +Signed-off-by: Hugh Dickins +Acked-by: Michal Hocko +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + mm/mmap.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/mm/mmap.c b/mm/mmap.c +index ff12e23..f975ec9 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -1770,7 +1770,8 @@ check_current: + /* Check if current node has a suitable gap */ + if (gap_start > high_limit) + return -ENOMEM; +- if (gap_end >= low_limit && gap_end - gap_start >= length) ++ if (gap_end >= low_limit && ++ gap_end > gap_start && gap_end - gap_start >= length) + goto found; + + /* Visit right subtree if it looks promising */ +@@ -1873,7 +1874,8 @@ check_current: + gap_end = vm_start_gap(vma); + if (gap_end < low_limit) + return -ENOMEM; +- if (gap_start <= high_limit && gap_end - gap_start >= length) ++ if (gap_start <= high_limit && ++ gap_end > gap_start && gap_end - gap_start >= length) + goto found; + + /* Visit left subtree if it looks promising */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-1000364/3.patch b/Patches/Linux_CVEs/CVE-2017-1000364/3.patch new file mode 100644 index 00000000..01c19765 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-1000364/3.patch @@ -0,0 +1,1549 @@ +From 640c7dfdc7c723143b1ce42f5569ec8565cbbde7 Mon Sep 17 00:00:00 2001 +From: Hugh Dickins +Date: Mon, 19 Jun 2017 20:32:47 +0200 +Subject: mm: larger stack guard gap, between vmas + +commit 1be7107fbe18eed3e319a6c3e83c78254b693acb upstream. + +Stack guard page is a useful feature to reduce a risk of stack smashing +into a different mapping. We have been using a single page gap which +is sufficient to prevent having stack adjacent to a different mapping. +But this seems to be insufficient in the light of the stack usage in +userspace. E.g. glibc uses as large as 64kB alloca() in many commonly +used functions. Others use constructs liks gid_t buffer[NGROUPS_MAX] +which is 256kB or stack strings with MAX_ARG_STRLEN. + +This will become especially dangerous for suid binaries and the default +no limit for the stack size limit because those applications can be +tricked to consume a large portion of the stack and a single glibc call +could jump over the guard page. These attacks are not theoretical, +unfortunatelly. + +Make those attacks less probable by increasing the stack guard gap +to 1MB (on systems with 4k pages; but make it depend on the page size +because systems with larger base pages might cap stack allocations in +the PAGE_SIZE units) which should cover larger alloca() and VLA stack +allocations. It is obviously not a full fix because the problem is +somehow inherent, but it should reduce attack space a lot. + +One could argue that the gap size should be configurable from userspace, +but that can be done later when somebody finds that the new 1MB is wrong +for some special case applications. For now, add a kernel command line +option (stack_guard_gap) to specify the stack gap size (in page units). + +Implementation wise, first delete all the old code for stack guard page: +because although we could get away with accounting one extra page in a +stack vma, accounting a larger gap can break userspace - case in point, +a program run with "ulimit -S -v 20000" failed when the 1MB gap was +counted for RLIMIT_AS; similar problems could come with RLIMIT_MLOCK +and strict non-overcommit mode. + +Instead of keeping gap inside the stack vma, maintain the stack guard +gap as a gap between vmas: using vm_start_gap() in place of vm_start +(or vm_end_gap() in place of vm_end if VM_GROWSUP) in just those few +places which need to respect the gap - mainly arch_get_unmapped_area(), +and and the vma tree's subtree_gap support for that. + +Original-patch-by: Oleg Nesterov +Original-patch-by: Michal Hocko +Signed-off-by: Hugh Dickins +Acked-by: Michal Hocko +Tested-by: Helge Deller # parisc +Signed-off-by: Linus Torvalds +[Hugh Dickins: Backported to 3.2] +[bwh: Fix more instances of vma->vm_start in sparc64 impl. of + arch_get_unmapped_area_topdown() and generic impl. of + hugetlb_get_unmapped_area()] +Signed-off-by: Ben Hutchings +--- + Documentation/kernel-parameters.txt | 7 ++ + arch/alpha/kernel/osf_sys.c | 2 +- + arch/arm/mm/mmap.c | 12 +-- + arch/frv/mm/elf-fdpic.c | 6 +- + arch/ia64/kernel/sys_ia64.c | 18 +++- + arch/ia64/mm/hugetlbpage.c | 4 +- + arch/mips/mm/mmap.c | 19 ++-- + arch/parisc/kernel/sys_parisc.c | 40 ++++++--- + arch/powerpc/mm/slice.c | 24 ++--- + arch/sh/mm/mmap.c | 29 +++--- + arch/sparc/kernel/sys_sparc_32.c | 2 +- + arch/sparc/kernel/sys_sparc_64.c | 30 ++++--- + arch/sparc/mm/hugetlbpage.c | 27 +++--- + arch/tile/mm/hugetlbpage.c | 26 +++--- + arch/x86/kernel/sys_x86_64.c | 29 +++--- + arch/x86/mm/hugetlbpage.c | 24 ++--- + fs/hugetlbfs/inode.c | 4 +- + fs/proc/task_mmu.c | 4 - + include/linux/mm.h | 53 ++++++----- + mm/memory.c | 49 ---------- + mm/mmap.c | 175 ++++++++++++++++++++---------------- + 21 files changed, 312 insertions(+), 272 deletions(-) + +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index ac601c4..356bf4b 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -2457,6 +2457,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + spia_pedr= + spia_peddr= + ++ stack_guard_gap= [MM] ++ override the default stack gap protection. The value ++ is in page units and it defines how many pages prior ++ to (for stacks growing down) resp. after (for stacks ++ growing up) the main stack are reserved for no other ++ mapping. Default value is 256 pages. ++ + stacktrace [FTRACE] + Enabled the stack tracer on boot up. + +diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c +index 01e8715..b9abe5b 100644 +--- a/arch/alpha/kernel/osf_sys.c ++++ b/arch/alpha/kernel/osf_sys.c +@@ -1147,7 +1147,7 @@ arch_get_unmapped_area_1(unsigned long addr, unsigned long len, + /* At this point: (!vma || addr < vma->vm_end). */ + if (limit - len < addr) + return -ENOMEM; +- if (!vma || addr + len <= vma->vm_start) ++ if (!vma || addr + len <= vm_start_gap(vma)) + return addr; + addr = vma->vm_end; + vma = vma->vm_next; +diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c +index 44b628e..4497b5e 100644 +--- a/arch/arm/mm/mmap.c ++++ b/arch/arm/mm/mmap.c +@@ -30,7 +30,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + { + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; +- unsigned long start_addr; ++ unsigned long start_addr, vm_start; + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); + +@@ -62,7 +62,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + if (len > mm->cached_hole_size) { +@@ -96,15 +96,17 @@ full_search: + } + return -ENOMEM; + } +- if (!vma || addr + len <= vma->vm_start) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (!vma || addr + len <= vm_start) { + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + addr = vma->vm_end; + if (do_align) + addr = COLOUR_ALIGN(addr, pgoff); +diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c +index 385fd30..96eca58 100644 +--- a/arch/frv/mm/elf-fdpic.c ++++ b/arch/frv/mm/elf-fdpic.c +@@ -74,7 +74,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + addr = PAGE_ALIGN(addr); + vma = find_vma(current->mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + goto success; + } + +@@ -89,7 +89,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + for (; vma; vma = vma->vm_next) { + if (addr > limit) + break; +- if (addr + len <= vma->vm_start) ++ if (addr + len <= vm_start_gap(vma)) + goto success; + addr = vma->vm_end; + } +@@ -104,7 +104,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + for (; vma; vma = vma->vm_next) { + if (addr > limit) + break; +- if (addr + len <= vma->vm_start) ++ if (addr + len <= vm_start_gap(vma)) + goto success; + addr = vma->vm_end; + } +diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c +index 609d500..77c0aff 100644 +--- a/arch/ia64/kernel/sys_ia64.c ++++ b/arch/ia64/kernel/sys_ia64.c +@@ -27,7 +27,8 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len + long map_shared = (flags & MAP_SHARED); + unsigned long start_addr, align_mask = PAGE_SIZE - 1; + struct mm_struct *mm = current->mm; +- struct vm_area_struct *vma; ++ struct vm_area_struct *vma, *prev; ++ unsigned long prev_end; + + if (len > RGN_MAP_LIMIT) + return -ENOMEM; +@@ -58,7 +59,17 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len + full_search: + start_addr = addr = (addr + align_mask) & ~align_mask; + +- for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { ++ for (vma = find_vma_prev(mm, addr, &prev); ; prev = vma, ++ vma = vma->vm_next) { ++ if (prev) { ++ prev_end = vm_end_gap(prev); ++ if (addr < prev_end) { ++ addr = (prev_end + align_mask) & ~align_mask; ++ /* If vma already violates gap, forget it */ ++ if (vma && addr > vma->vm_start) ++ addr = vma->vm_start; ++ } ++ } + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) { + if (start_addr != TASK_UNMAPPED_BASE) { +@@ -68,12 +79,11 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len + } + return -ENOMEM; + } +- if (!vma || addr + len <= vma->vm_start) { ++ if (!vma || addr + len <= vm_start_gap(vma)) { + /* Remember the address where we stopped this search: */ + mm->free_area_cache = addr + len; + return addr; + } +- addr = (vma->vm_end + align_mask) & ~align_mask; + } + } + +diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c +index 5ca674b..66a1ec0 100644 +--- a/arch/ia64/mm/hugetlbpage.c ++++ b/arch/ia64/mm/hugetlbpage.c +@@ -171,9 +171,9 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u + /* At this point: (!vmm || addr < vmm->vm_end). */ + if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT) + return -ENOMEM; +- if (!vmm || (addr + len) <= vmm->vm_start) ++ if (!vmm || (addr + len) <= vm_start_gap(vmm)) + return addr; +- addr = ALIGN(vmm->vm_end, HPAGE_SIZE); ++ addr = ALIGN(vm_end_gap(vmm), HPAGE_SIZE); + } + } + +diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c +index 302d779..a79ddcf 100644 +--- a/arch/mips/mm/mmap.c ++++ b/arch/mips/mm/mmap.c +@@ -70,6 +70,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long addr = addr0; ++ unsigned long vm_start; + int do_color_align; + + if (unlikely(len > TASK_SIZE)) +@@ -103,7 +104,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -118,7 +119,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; +- if (!vma || addr + len <= vma->vm_start) ++ if (!vma || addr + len <= vm_start_gap(vma)) + return addr; + addr = vma->vm_end; + if (do_color_align) +@@ -145,7 +146,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + /* make sure it can fit in the remaining address space */ + if (likely(addr > len)) { + vma = find_vma(mm, addr - len); +- if (!vma || addr <= vma->vm_start) { ++ if (!vma || addr <= vm_start_gap(vma)) { + /* cache the address as a hint for next time */ + return mm->free_area_cache = addr - len; + } +@@ -165,20 +166,22 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, + * return with success: + */ + vma = find_vma(mm, addr); +- if (likely(!vma || addr + len <= vma->vm_start)) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (likely(!vma || addr + len <= vm_start)) { + /* cache the address as a hint for next time */ + return mm->free_area_cache = addr; + } + + /* remember the largest hole we saw so far */ +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = vma->vm_start - len; ++ addr = vm_start - len; + if (do_color_align) + addr = COLOUR_ALIGN_DOWN(addr, pgoff); +- } while (likely(len < vma->vm_start)); ++ } while (likely(len < vm_start)); + + bottomup: + /* +diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c +index 7ea75d1..1d4ac8d 100644 +--- a/arch/parisc/kernel/sys_parisc.c ++++ b/arch/parisc/kernel/sys_parisc.c +@@ -35,17 +35,27 @@ + + static unsigned long get_unshared_area(unsigned long addr, unsigned long len) + { +- struct vm_area_struct *vma; ++ struct vm_area_struct *vma, *prev; ++ unsigned long prev_end; + + addr = PAGE_ALIGN(addr); + +- for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { ++ for (vma = find_vma_prev(current->mm, addr, &prev); ; prev = vma, ++ vma = vma->vm_next) { ++ if (prev) { ++ prev_end = vm_end_gap(prev); ++ if (addr < prev_end) { ++ addr = prev_end; ++ /* If vma already violates gap, forget it */ ++ if (vma && addr > vma->vm_start) ++ addr = vma->vm_start; ++ } ++ } + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; +- if (!vma || addr + len <= vma->vm_start) ++ if (!vma || addr + len <= vm_start_gap(vma)) + return addr; +- addr = vma->vm_end; + } + } + +@@ -70,22 +80,32 @@ static int get_offset(struct address_space *mapping) + static unsigned long get_shared_area(struct address_space *mapping, + unsigned long addr, unsigned long len, unsigned long pgoff) + { +- struct vm_area_struct *vma; ++ struct vm_area_struct *vma, *prev; ++ unsigned long prev_end; + int offset = mapping ? get_offset(mapping) : 0; + + offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000; + + addr = DCACHE_ALIGN(addr - offset) + offset; + +- for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { ++ for (vma = find_vma_prev(current->mm, addr, &prev); ; prev = vma, ++ vma = vma->vm_next) { ++ if (prev) { ++ prev_end = vm_end_gap(prev); ++ if (addr < prev_end) { ++ addr = DCACHE_ALIGN(prev_end - offset) + offset; ++ if (addr < prev_end) /* handle wraparound */ ++ return -ENOMEM; ++ /* If vma already violates gap, forget it */ ++ if (vma && addr > vma->vm_start) ++ addr = vma->vm_start; ++ } ++ } + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; +- if (!vma || addr + len <= vma->vm_start) ++ if (!vma || addr + len <= vm_start_gap(vma)) + return addr; +- addr = DCACHE_ALIGN(vma->vm_end - offset) + offset; +- if (addr < vma->vm_end) /* handle wraparound */ +- return -ENOMEM; + } + } + +diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c +index 73709f7..57654c9 100644 +--- a/arch/powerpc/mm/slice.c ++++ b/arch/powerpc/mm/slice.c +@@ -98,7 +98,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr, + if ((mm->task_size - len) < addr) + return 0; + vma = find_vma(mm, addr); +- return (!vma || (addr + len) <= vma->vm_start); ++ return (!vma || (addr + len) <= vm_start_gap(vma)); + } + + static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice) +@@ -227,7 +227,7 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm, + int psize, int use_cache) + { + struct vm_area_struct *vma; +- unsigned long start_addr, addr; ++ unsigned long start_addr, addr, vm_start; + struct slice_mask mask; + int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); + +@@ -256,7 +256,9 @@ full_search: + addr = _ALIGN_UP(addr + 1, 1ul << SLICE_HIGH_SHIFT); + continue; + } +- if (!vma || addr + len <= vma->vm_start) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (!vma || addr + len <= vm_start) { + /* + * Remember the place where we stopped the search: + */ +@@ -264,8 +266,8 @@ full_search: + mm->free_area_cache = addr + len; + return addr; + } +- if (use_cache && (addr + mm->cached_hole_size) < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (use_cache && (addr + mm->cached_hole_size) < vm_start) ++ mm->cached_hole_size = vm_start - addr; + addr = vma->vm_end; + } + +@@ -284,7 +286,7 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, + int psize, int use_cache) + { + struct vm_area_struct *vma; +- unsigned long addr; ++ unsigned long addr, vm_start; + struct slice_mask mask; + int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); + +@@ -336,7 +338,9 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, + * return with success: + */ + vma = find_vma(mm, addr); +- if (!vma || (addr + len) <= vma->vm_start) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (!vma || (addr + len) <= vm_start) { + /* remember the address as a hint for next time */ + if (use_cache) + mm->free_area_cache = addr; +@@ -344,11 +348,11 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, + } + + /* remember the largest hole we saw so far */ +- if (use_cache && (addr + mm->cached_hole_size) < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (use_cache && (addr + mm->cached_hole_size) < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = vma->vm_start; ++ addr = vm_start; + } + + /* +diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c +index afeb710..22eff46 100644 +--- a/arch/sh/mm/mmap.c ++++ b/arch/sh/mm/mmap.c +@@ -47,7 +47,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + { + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; +- unsigned long start_addr; ++ unsigned long start_addr, vm_start; + int do_colour_align; + + if (flags & MAP_FIXED) { +@@ -75,7 +75,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -106,15 +106,17 @@ full_search: + } + return -ENOMEM; + } +- if (likely(!vma || addr + len <= vma->vm_start)) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (likely(!vma || addr + len <= vm_start)) { + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + addr = vma->vm_end; + if (do_colour_align) +@@ -130,6 +132,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + unsigned long addr = addr0; ++ unsigned long vm_start; + int do_colour_align; + + if (flags & MAP_FIXED) { +@@ -158,7 +161,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -179,7 +182,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + /* make sure it can fit in the remaining address space */ + if (likely(addr > len)) { + vma = find_vma(mm, addr-len); +- if (!vma || addr <= vma->vm_start) { ++ if (!vma || addr <= vm_start_gap(vma)) { + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr-len); + } +@@ -199,20 +202,22 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + * return with success: + */ + vma = find_vma(mm, addr); +- if (likely(!vma || addr+len <= vma->vm_start)) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (likely(!vma || addr + len <= vm_start)) { + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr); + } + + /* remember the largest hole we saw so far */ +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = vma->vm_start-len; ++ addr = vm_start-len; + if (do_colour_align) + addr = COLOUR_ALIGN_DOWN(addr, pgoff); +- } while (likely(len < vma->vm_start)); ++ } while (likely(len < vm_start)); + + bottomup: + /* +diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c +index 42b282f..eeae89b 100644 +--- a/arch/sparc/kernel/sys_sparc_32.c ++++ b/arch/sparc/kernel/sys_sparc_32.c +@@ -71,7 +71,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + } + if (TASK_SIZE - PAGE_SIZE - len < addr) + return -ENOMEM; +- if (!vmm || addr + len <= vmm->vm_start) ++ if (!vmm || addr + len <= vm_start_gap(vmm)) + return addr; + addr = vmm->vm_end; + if (flags & MAP_SHARED) +diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c +index a062fe9..39f4999 100644 +--- a/arch/sparc/kernel/sys_sparc_64.c ++++ b/arch/sparc/kernel/sys_sparc_64.c +@@ -117,7 +117,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + struct mm_struct *mm = current->mm; + struct vm_area_struct * vma; + unsigned long task_size = TASK_SIZE; +- unsigned long start_addr; ++ unsigned long start_addr, vm_start; + int do_color_align; + + if (flags & MAP_FIXED) { +@@ -147,7 +147,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi + + vma = find_vma(mm, addr); + if (task_size - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -181,15 +181,17 @@ full_search: + } + return -ENOMEM; + } +- if (likely(!vma || addr + len <= vma->vm_start)) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (likely(!vma || addr + len <= vm_start)) { + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + addr = vma->vm_end; + if (do_color_align) +@@ -205,7 +207,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + unsigned long task_size = STACK_TOP32; +- unsigned long addr = addr0; ++ unsigned long addr = addr0, vm_start; + int do_color_align; + + /* This should only ever run for 32-bit processes. */ +@@ -237,7 +239,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + + vma = find_vma(mm, addr); + if (task_size - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -258,7 +260,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + /* make sure it can fit in the remaining address space */ + if (likely(addr > len)) { + vma = find_vma(mm, addr-len); +- if (!vma || addr <= vma->vm_start) { ++ if (!vma || addr <= vm_start_gap(vma)) { + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr-len); + } +@@ -278,20 +280,22 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + * return with success: + */ + vma = find_vma(mm, addr); +- if (likely(!vma || addr+len <= vma->vm_start)) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (likely(!vma || addr + len <= vm_start)) { + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr); + } + + /* remember the largest hole we saw so far */ +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = vma->vm_start-len; ++ addr = vm_start - len; + if (do_color_align) + addr = COLOUR_ALIGN_DOWN(addr, pgoff); +- } while (likely(len < vma->vm_start)); ++ } while (likely(len < vm_start)); + + bottomup: + /* +diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c +index 07e1453..e13e85d 100644 +--- a/arch/sparc/mm/hugetlbpage.c ++++ b/arch/sparc/mm/hugetlbpage.c +@@ -33,7 +33,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp, + struct mm_struct *mm = current->mm; + struct vm_area_struct * vma; + unsigned long task_size = TASK_SIZE; +- unsigned long start_addr; ++ unsigned long start_addr, vm_start; + + if (test_thread_flag(TIF_32BIT)) + task_size = STACK_TOP32; +@@ -67,15 +67,17 @@ full_search: + } + return -ENOMEM; + } +- if (likely(!vma || addr + len <= vma->vm_start)) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (likely(!vma || addr + len <= vm_start)) { + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + addr = ALIGN(vma->vm_end, HPAGE_SIZE); + } +@@ -90,6 +92,7 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + unsigned long addr = addr0; ++ unsigned long vm_start; + + /* This should only ever run for 32-bit processes. */ + BUG_ON(!test_thread_flag(TIF_32BIT)); +@@ -106,7 +109,7 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + /* make sure it can fit in the remaining address space */ + if (likely(addr > len)) { + vma = find_vma(mm, addr-len); +- if (!vma || addr <= vma->vm_start) { ++ if (!vma || addr <= vm_start_gap(vma)) { + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr-len); + } +@@ -124,18 +127,20 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + * return with success: + */ + vma = find_vma(mm, addr); +- if (likely(!vma || addr+len <= vma->vm_start)) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (likely(!vma || addr + len <= vm_start)) { + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr); + } + + /* remember the largest hole we saw so far */ +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = (vma->vm_start-len) & HPAGE_MASK; +- } while (likely(len < vma->vm_start)); ++ addr = (vm_start - len) & HPAGE_MASK; ++ } while (likely(len < vm_start)); + + bottomup: + /* +@@ -182,7 +187,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + addr = ALIGN(addr, HPAGE_SIZE); + vma = find_vma(mm, addr); + if (task_size - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + if (mm->get_unmapped_area == arch_get_unmapped_area) +diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c +index 42cfcba..184e033 100644 +--- a/arch/tile/mm/hugetlbpage.c ++++ b/arch/tile/mm/hugetlbpage.c +@@ -159,7 +159,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, + struct hstate *h = hstate_file(file); + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; +- unsigned long start_addr; ++ unsigned long start_addr, vm_start; + + if (len > mm->cached_hole_size) { + start_addr = mm->free_area_cache; +@@ -185,12 +185,14 @@ full_search: + } + return -ENOMEM; + } +- if (!vma || addr + len <= vma->vm_start) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (!vma || addr + len <= vm_start) { + mm->free_area_cache = addr + len; + return addr; + } +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + addr = ALIGN(vma->vm_end, huge_page_size(h)); + } + } +@@ -204,6 +206,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, + struct vm_area_struct *vma, *prev_vma; + unsigned long base = mm->mmap_base, addr = addr0; + unsigned long largest_hole = mm->cached_hole_size; ++ unsigned long vm_start; + int first_time = 1; + + /* don't allow allocations above current base */ +@@ -234,9 +237,10 @@ try_again: + + /* + * new region fits between prev_vma->vm_end and +- * vma->vm_start, use it: ++ * vm_start, use it: + */ +- if (addr + len <= vma->vm_start && ++ vm_start = vm_start_gap(vma); ++ if (addr + len <= vm_start && + (!prev_vma || (addr >= prev_vma->vm_end))) { + /* remember the address as a hint for next time */ + mm->cached_hole_size = largest_hole; +@@ -251,13 +255,13 @@ try_again: + } + + /* remember the largest hole we saw so far */ +- if (addr + largest_hole < vma->vm_start) +- largest_hole = vma->vm_start - addr; ++ if (addr + largest_hole < vm_start) ++ largest_hole = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = (vma->vm_start - len) & huge_page_mask(h); ++ addr = (vm_start - len) & huge_page_mask(h); + +- } while (len <= vma->vm_start); ++ } while (len <= vm_start); + + fail: + /* +@@ -312,7 +316,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + addr = ALIGN(addr, huge_page_size(h)); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + if (current->mm->get_unmapped_area == arch_get_unmapped_area) +diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c +index cdb2fc9..0dbfff8 100644 +--- a/arch/x86/kernel/sys_x86_64.c ++++ b/arch/x86/kernel/sys_x86_64.c +@@ -126,7 +126,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + { + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; +- unsigned long start_addr; ++ unsigned long start_addr, vm_start; + unsigned long begin, end; + + if (flags & MAP_FIXED) +@@ -141,7 +141,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (end - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32)) +@@ -172,15 +172,17 @@ full_search: + } + return -ENOMEM; + } +- if (!vma || addr + len <= vma->vm_start) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (!vma || addr + len <= vm_start) { + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + addr = vma->vm_end; + addr = align_addr(addr, filp, 0); +@@ -196,6 +198,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + unsigned long addr = addr0; ++ unsigned long vm_start; + + /* requested length too big for entire address space */ + if (len > TASK_SIZE) +@@ -213,7 +216,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -232,7 +235,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + ALIGN_TOPDOWN); + + vma = find_vma(mm, tmp_addr); +- if (!vma || tmp_addr + len <= vma->vm_start) ++ if (!vma || tmp_addr + len <= vm_start_gap(vma)) + /* remember the address as a hint for next time */ + return mm->free_area_cache = tmp_addr; + } +@@ -251,17 +254,19 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + * return with success: + */ + vma = find_vma(mm, addr); +- if (!vma || addr+len <= vma->vm_start) ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (!vma || addr + len <= vm_start) + /* remember the address as a hint for next time */ + return mm->free_area_cache = addr; + + /* remember the largest hole we saw so far */ +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = vma->vm_start-len; +- } while (len < vma->vm_start); ++ addr = vm_start - len; ++ } while (len < vm_start); + + bottomup: + /* +diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c +index df7d12c..67b8760 100644 +--- a/arch/x86/mm/hugetlbpage.c ++++ b/arch/x86/mm/hugetlbpage.c +@@ -277,7 +277,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, + struct hstate *h = hstate_file(file); + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; +- unsigned long start_addr; ++ unsigned long start_addr, vm_start; + + if (len > mm->cached_hole_size) { + start_addr = mm->free_area_cache; +@@ -303,12 +303,14 @@ full_search: + } + return -ENOMEM; + } +- if (!vma || addr + len <= vma->vm_start) { ++ if (vma) ++ vm_start = vm_start_gap(vma); ++ if (!vma || addr + len <= vm_start) { + mm->free_area_cache = addr + len; + return addr; + } +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + addr = ALIGN(vma->vm_end, huge_page_size(h)); + } + } +@@ -322,6 +324,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, + struct vm_area_struct *vma, *prev_vma; + unsigned long base = mm->mmap_base, addr = addr0; + unsigned long largest_hole = mm->cached_hole_size; ++ unsigned long vm_start; + int first_time = 1; + + /* don't allow allocations above current base */ +@@ -351,7 +354,8 @@ try_again: + * new region fits between prev_vma->vm_end and + * vma->vm_start, use it: + */ +- if (addr + len <= vma->vm_start && ++ vm_start = vm_start_gap(vma); ++ if (addr + len <= vm_start && + (!prev_vma || (addr >= prev_vma->vm_end))) { + /* remember the address as a hint for next time */ + mm->cached_hole_size = largest_hole; +@@ -365,12 +369,12 @@ try_again: + } + + /* remember the largest hole we saw so far */ +- if (addr + largest_hole < vma->vm_start) +- largest_hole = vma->vm_start - addr; ++ if (addr + largest_hole < vm_start) ++ largest_hole = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = (vma->vm_start - len) & huge_page_mask(h); +- } while (len <= vma->vm_start); ++ addr = (vm_start - len) & huge_page_mask(h); ++ } while (len <= vm_start); + + fail: + /* +@@ -426,7 +430,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + addr = ALIGN(addr, huge_page_size(h)); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + if (mm->get_unmapped_area == arch_get_unmapped_area) +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index 5557332..99c51d6 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -150,7 +150,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + addr = ALIGN(addr, huge_page_size(h)); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + +@@ -176,7 +176,7 @@ full_search: + return -ENOMEM; + } + +- if (!vma || addr + len <= vma->vm_start) ++ if (!vma || addr + len <= vm_start_gap(vma)) + return addr; + addr = ALIGN(vma->vm_end, huge_page_size(h)); + } +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index de404f2..6037a13 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -230,11 +230,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) + + /* We don't show the stack guard page in /proc/maps */ + start = vma->vm_start; +- if (stack_guard_page_start(vma, start)) +- start += PAGE_SIZE; + end = vma->vm_end; +- if (stack_guard_page_end(vma, end)) +- end -= PAGE_SIZE; + + seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", + start, +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 16394da..19f9043 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1015,34 +1015,6 @@ int set_page_dirty(struct page *page); + int set_page_dirty_lock(struct page *page); + int clear_page_dirty_for_io(struct page *page); + +-/* Is the vma a continuation of the stack vma above it? */ +-static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) +-{ +- return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); +-} +- +-static inline int stack_guard_page_start(struct vm_area_struct *vma, +- unsigned long addr) +-{ +- return (vma->vm_flags & VM_GROWSDOWN) && +- (vma->vm_start == addr) && +- !vma_growsdown(vma->vm_prev, addr); +-} +- +-/* Is the vma a continuation of the stack vma below it? */ +-static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr) +-{ +- return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP); +-} +- +-static inline int stack_guard_page_end(struct vm_area_struct *vma, +- unsigned long addr) +-{ +- return (vma->vm_flags & VM_GROWSUP) && +- (vma->vm_end == addr) && +- !vma_growsup(vma->vm_next, addr); +-} +- + extern unsigned long move_page_tables(struct vm_area_struct *vma, + unsigned long old_addr, struct vm_area_struct *new_vma, + unsigned long new_addr, unsigned long len); +@@ -1462,6 +1434,7 @@ unsigned long ra_submit(struct file_ra_state *ra, + struct address_space *mapping, + struct file *filp); + ++extern unsigned long stack_guard_gap; + /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */ + extern int expand_stack(struct vm_area_struct *vma, unsigned long address); + +@@ -1490,6 +1463,30 @@ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * m + return vma; + } + ++static inline unsigned long vm_start_gap(struct vm_area_struct *vma) ++{ ++ unsigned long vm_start = vma->vm_start; ++ ++ if (vma->vm_flags & VM_GROWSDOWN) { ++ vm_start -= stack_guard_gap; ++ if (vm_start > vma->vm_start) ++ vm_start = 0; ++ } ++ return vm_start; ++} ++ ++static inline unsigned long vm_end_gap(struct vm_area_struct *vma) ++{ ++ unsigned long vm_end = vma->vm_end; ++ ++ if (vma->vm_flags & VM_GROWSUP) { ++ vm_end += stack_guard_gap; ++ if (vm_end < vma->vm_end) ++ vm_end = -PAGE_SIZE; ++ } ++ return vm_end; ++} ++ + static inline unsigned long vma_pages(struct vm_area_struct *vma) + { + return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; +diff --git a/mm/memory.c b/mm/memory.c +index 2917e9b..6325103d 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1605,12 +1605,6 @@ no_page_table: + return page; + } + +-static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) +-{ +- return stack_guard_page_start(vma, addr) || +- stack_guard_page_end(vma, addr+PAGE_SIZE); +-} +- + /** + * __get_user_pages() - pin user pages in memory + * @tsk: task_struct of target task +@@ -1761,11 +1755,6 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, + int ret; + unsigned int fault_flags = 0; + +- /* For mlock, just skip the stack guard page. */ +- if (foll_flags & FOLL_MLOCK) { +- if (stack_guard_page(vma, start)) +- goto next_page; +- } + if (foll_flags & FOLL_WRITE) + fault_flags |= FAULT_FLAG_WRITE; + if (nonblocking) +@@ -3122,40 +3111,6 @@ out_release: + } + + /* +- * This is like a special single-page "expand_{down|up}wards()", +- * except we must first make sure that 'address{-|+}PAGE_SIZE' +- * doesn't hit another vma. +- */ +-static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address) +-{ +- address &= PAGE_MASK; +- if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) { +- struct vm_area_struct *prev = vma->vm_prev; +- +- /* +- * Is there a mapping abutting this one below? +- * +- * That's only ok if it's the same stack mapping +- * that has gotten split.. +- */ +- if (prev && prev->vm_end == address) +- return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; +- +- return expand_downwards(vma, address - PAGE_SIZE); +- } +- if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { +- struct vm_area_struct *next = vma->vm_next; +- +- /* As VM_GROWSDOWN but s/below/above/ */ +- if (next && next->vm_start == address + PAGE_SIZE) +- return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; +- +- return expand_upwards(vma, address + PAGE_SIZE); +- } +- return 0; +-} +- +-/* + * We enter with non-exclusive mmap_sem (to exclude vma changes, + * but allow concurrent faults), and pte mapped but not yet locked. + * We return with mmap_sem still held, but pte unmapped and unlocked. +@@ -3174,10 +3129,6 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, + if (vma->vm_flags & VM_SHARED) + return VM_FAULT_SIGBUS; + +- /* Check if we need to add a guard page to the stack */ +- if (check_stack_guard_page(vma, address) < 0) +- return VM_FAULT_SIGSEGV; +- + /* Use the zero-page for reads */ + if (!(flags & FAULT_FLAG_WRITE)) { + entry = pte_mkspecial(pfn_pte(my_zero_pfn(address), +diff --git a/mm/mmap.c b/mm/mmap.c +index e949a20..cbcf486 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -245,6 +245,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) + unsigned long rlim, retval; + unsigned long newbrk, oldbrk; + struct mm_struct *mm = current->mm; ++ struct vm_area_struct *next; + unsigned long min_brk; + + down_write(&mm->mmap_sem); +@@ -289,7 +290,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) + } + + /* Check against existing mmap mappings. */ +- if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) ++ next = find_vma(mm, oldbrk); ++ if (next && newbrk + PAGE_SIZE > vm_start_gap(next)) + goto out; + + /* Ok, looks good - let it rip. */ +@@ -1368,8 +1370,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) + { + struct mm_struct *mm = current->mm; +- struct vm_area_struct *vma; +- unsigned long start_addr; ++ struct vm_area_struct *vma, *prev; ++ unsigned long start_addr, vm_start, prev_end; + + if (len > TASK_SIZE - mmap_min_addr) + return -ENOMEM; +@@ -1379,9 +1381,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + + if (addr) { + addr = PAGE_ALIGN(addr); +- vma = find_vma(mm, addr); ++ vma = find_vma_prev(mm, addr, &prev); + if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma)) && ++ (!prev || addr >= vm_end_gap(prev))) + return addr; + } + if (len > mm->cached_hole_size) { +@@ -1392,7 +1395,17 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, + } + + full_search: +- for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { ++ for (vma = find_vma_prev(mm, addr, &prev); ; prev = vma, ++ vma = vma->vm_next) { ++ if (prev) { ++ prev_end = vm_end_gap(prev); ++ if (addr < prev_end) { ++ addr = prev_end; ++ /* If vma already violates gap, forget it */ ++ if (vma && addr > vma->vm_start) ++ addr = vma->vm_start; ++ } ++ } + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) { + /* +@@ -1407,16 +1420,16 @@ full_search: + } + return -ENOMEM; + } +- if (!vma || addr + len <= vma->vm_start) { ++ vm_start = vma ? vm_start_gap(vma) : TASK_SIZE; ++ if (addr + len <= vm_start) { + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; +- addr = vma->vm_end; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + } + } + #endif +@@ -1442,9 +1455,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, const unsigned long pgoff, + const unsigned long flags) + { +- struct vm_area_struct *vma; ++ struct vm_area_struct *vma, *prev; + struct mm_struct *mm = current->mm; + unsigned long addr = addr0; ++ unsigned long vm_start, prev_end; + unsigned long low_limit = max(PAGE_SIZE, mmap_min_addr); + + /* requested length too big for entire address space */ +@@ -1457,9 +1471,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + /* requesting a specific address */ + if (addr) { + addr = PAGE_ALIGN(addr); +- vma = find_vma(mm, addr); ++ vma = find_vma_prev(mm, addr, &prev); + if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && +- (!vma || addr + len <= vma->vm_start)) ++ (!vma || addr + len <= vm_start_gap(vma)) && ++ (!prev || addr >= vm_end_gap(prev))) + return addr; + } + +@@ -1474,8 +1489,9 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + + /* make sure it can fit in the remaining address space */ + if (addr >= low_limit + len) { +- vma = find_vma(mm, addr-len); +- if (!vma || addr <= vma->vm_start) ++ vma = find_vma_prev(mm, addr-len, &prev); ++ if ((!vma || addr <= vm_start_gap(vma)) && ++ (!prev || addr-len >= vm_end_gap(prev))) + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr-len); + } +@@ -1491,18 +1507,21 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + * else if new region fits below vma->vm_start, + * return with success: + */ +- vma = find_vma(mm, addr); +- if (!vma || addr+len <= vma->vm_start) ++ vma = find_vma_prev(mm, addr, &prev); ++ vm_start = vma ? vm_start_gap(vma) : mm->mmap_base; ++ prev_end = prev ? vm_end_gap(prev) : low_limit; ++ ++ if (addr + len <= vm_start && addr >= prev_end) + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr); + + /* remember the largest hole we saw so far */ +- if (addr + mm->cached_hole_size < vma->vm_start) +- mm->cached_hole_size = vma->vm_start - addr; ++ if (addr + mm->cached_hole_size < vm_start) ++ mm->cached_hole_size = vm_start - addr; + + /* try just below the current vma->vm_start */ +- addr = vma->vm_start-len; +- } while (vma->vm_start >= low_limit + len); ++ addr = vm_start - len; ++ } while (vm_start >= low_limit + len); + + bottomup: + /* +@@ -1647,21 +1666,19 @@ out: + * update accounting. This is shared with both the + * grow-up and grow-down cases. + */ +-static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow) ++static int acct_stack_growth(struct vm_area_struct *vma, ++ unsigned long size, unsigned long grow) + { + struct mm_struct *mm = vma->vm_mm; + struct rlimit *rlim = current->signal->rlim; +- unsigned long new_start, actual_size; ++ unsigned long new_start; + + /* address space limit tests */ + if (!may_expand_vm(mm, grow)) + return -ENOMEM; + + /* Stack limit test */ +- actual_size = size; +- if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN))) +- actual_size -= PAGE_SIZE; +- if (actual_size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) ++ if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) + return -ENOMEM; + + /* mlock limit tests */ +@@ -1703,32 +1720,40 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns + */ + int expand_upwards(struct vm_area_struct *vma, unsigned long address) + { +- int error; ++ struct vm_area_struct *next; ++ unsigned long gap_addr; ++ int error = 0; + + if (!(vma->vm_flags & VM_GROWSUP)) + return -EFAULT; + +- /* +- * We must make sure the anon_vma is allocated +- * so that the anon_vma locking is not a noop. +- */ ++ /* Guard against wrapping around to address 0. */ ++ address &= PAGE_MASK; ++ address += PAGE_SIZE; ++ if (!address) ++ return -ENOMEM; ++ ++ /* Enforce stack_guard_gap */ ++ gap_addr = address + stack_guard_gap; ++ if (gap_addr < address) ++ return -ENOMEM; ++ next = vma->vm_next; ++ if (next && next->vm_start < gap_addr) { ++ if (!(next->vm_flags & VM_GROWSUP)) ++ return -ENOMEM; ++ /* Check that both stack segments have the same anon_vma? */ ++ } ++ ++ /* We must make sure the anon_vma is allocated. */ + if (unlikely(anon_vma_prepare(vma))) + return -ENOMEM; +- vma_lock_anon_vma(vma); + + /* + * vma->vm_start/vm_end cannot change under us because the caller + * is required to hold the mmap_sem in read mode. We need the + * anon_vma lock to serialize against concurrent expand_stacks. +- * Also guard against wrapping around to address 0. + */ +- if (address < PAGE_ALIGN(address+4)) +- address = PAGE_ALIGN(address+4); +- else { +- vma_unlock_anon_vma(vma); +- return -ENOMEM; +- } +- error = 0; ++ vma_lock_anon_vma(vma); + + /* Somebody else might have raced and expanded it already */ + if (address > vma->vm_end) { +@@ -1758,27 +1783,36 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address) + int expand_downwards(struct vm_area_struct *vma, + unsigned long address) + { ++ struct vm_area_struct *prev; ++ unsigned long gap_addr; + int error; + +- /* +- * We must make sure the anon_vma is allocated +- * so that the anon_vma locking is not a noop. +- */ +- if (unlikely(anon_vma_prepare(vma))) +- return -ENOMEM; +- + address &= PAGE_MASK; + error = security_file_mmap(NULL, 0, 0, 0, address, 1); + if (error) + return error; + +- vma_lock_anon_vma(vma); ++ /* Enforce stack_guard_gap */ ++ gap_addr = address - stack_guard_gap; ++ if (gap_addr > address) ++ return -ENOMEM; ++ prev = vma->vm_prev; ++ if (prev && prev->vm_end > gap_addr) { ++ if (!(prev->vm_flags & VM_GROWSDOWN)) ++ return -ENOMEM; ++ /* Check that both stack segments have the same anon_vma? */ ++ } ++ ++ /* We must make sure the anon_vma is allocated. */ ++ if (unlikely(anon_vma_prepare(vma))) ++ return -ENOMEM; + + /* + * vma->vm_start/vm_end cannot change under us because the caller + * is required to hold the mmap_sem in read mode. We need the + * anon_vma lock to serialize against concurrent expand_stacks. + */ ++ vma_lock_anon_vma(vma); + + /* Somebody else might have raced and expanded it already */ + if (address < vma->vm_start) { +@@ -1802,28 +1836,25 @@ int expand_downwards(struct vm_area_struct *vma, + return error; + } + +-/* +- * Note how expand_stack() refuses to expand the stack all the way to +- * abut the next virtual mapping, *unless* that mapping itself is also +- * a stack mapping. We want to leave room for a guard page, after all +- * (the guard page itself is not added here, that is done by the +- * actual page faulting logic) +- * +- * This matches the behavior of the guard page logic (see mm/memory.c: +- * check_stack_guard_page()), which only allows the guard page to be +- * removed under these circumstances. +- */ ++/* enforced gap between the expanding stack and other mappings. */ ++unsigned long stack_guard_gap = 256UL< +Acked-by: Rik van Riel +Acked-by: Michal Hocko +Cc: Alexander Viro +Cc: Qualys Security Advisory +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/exec.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index fe9ec45..6fa04b3 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -199,8 +199,26 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + + if (write) { + unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; ++ unsigned long ptr_size; + struct rlimit *rlim; + ++ /* ++ * Since the stack will hold pointers to the strings, we ++ * must account for them as well. ++ * ++ * The size calculation is the entire vma while each arg page is ++ * built, so each time we get here it's calculating how far it ++ * is currently (rather than each call being just the newly ++ * added size from the arg page). As a result, we need to ++ * always add the entire size of the pointers, so that on the ++ * last call to get_arg_page() we'll actually have the entire ++ * correct size. ++ */ ++ ptr_size = (bprm->argc + bprm->envc) * sizeof(void *); ++ if (ptr_size > ULONG_MAX - size) ++ goto fail; ++ size += ptr_size; ++ + acct_arg_size(bprm, size / PAGE_SIZE); + + /* +@@ -218,13 +236,15 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + * to work from. + */ + rlim = current->signal->rlim; +- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) { +- put_page(page); +- return NULL; +- } ++ if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) ++ goto fail; + } + + return page; ++ ++fail: ++ put_page(page); ++ return NULL; + } + + static void put_arg_page(struct page *page) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-1000380/0.patch b/Patches/Linux_CVEs/CVE-2017-1000380/0.patch new file mode 100644 index 00000000..1bf26f3f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-1000380/0.patch @@ -0,0 +1,56 @@ +From ba3021b2c79b2fa9114f92790a99deb27a65b728 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 2 Jun 2017 17:26:56 +0200 +Subject: ALSA: timer: Fix missing queue indices reset at + SNDRV_TIMER_IOCTL_SELECT + +snd_timer_user_tselect() reallocates the queue buffer dynamically, but +it forgot to reset its indices. Since the read may happen +concurrently with ioctl and snd_timer_user_tselect() allocates the +buffer via kmalloc(), this may lead to the leak of uninitialized +kernel-space data, as spotted via KMSAN: + + BUG: KMSAN: use of unitialized memory in snd_timer_user_read+0x6c4/0xa10 + CPU: 0 PID: 1037 Comm: probe Not tainted 4.11.0-rc5+ #2739 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + Call Trace: + __dump_stack lib/dump_stack.c:16 + dump_stack+0x143/0x1b0 lib/dump_stack.c:52 + kmsan_report+0x12a/0x180 mm/kmsan/kmsan.c:1007 + kmsan_check_memory+0xc2/0x140 mm/kmsan/kmsan.c:1086 + copy_to_user ./arch/x86/include/asm/uaccess.h:725 + snd_timer_user_read+0x6c4/0xa10 sound/core/timer.c:2004 + do_loop_readv_writev fs/read_write.c:716 + __do_readv_writev+0x94c/0x1380 fs/read_write.c:864 + do_readv_writev fs/read_write.c:894 + vfs_readv fs/read_write.c:908 + do_readv+0x52a/0x5d0 fs/read_write.c:934 + SYSC_readv+0xb6/0xd0 fs/read_write.c:1021 + SyS_readv+0x87/0xb0 fs/read_write.c:1018 + +This patch adds the missing reset of queue indices. Together with the +previous fix for the ioctl/read race, we cover the whole problem. + +Reported-by: Alexander Potapenko +Tested-by: Alexander Potapenko +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/timer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 1118bd8..cd67d1c 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -1618,6 +1618,7 @@ static int snd_timer_user_tselect(struct file *file, + if (err < 0) + goto __err; + ++ tu->qhead = tu->qtail = tu->qused = 0; + kfree(tu->queue); + tu->queue = NULL; + kfree(tu->tqueue); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-1000380/1.patch b/Patches/Linux_CVEs/CVE-2017-1000380/1.patch new file mode 100644 index 00000000..8a55d454 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-1000380/1.patch @@ -0,0 +1,73 @@ +From d11662f4f798b50d8c8743f433842c3e40fe3378 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 2 Jun 2017 15:03:38 +0200 +Subject: ALSA: timer: Fix race between read and ioctl + +The read from ALSA timer device, the function snd_timer_user_tread(), +may access to an uninitialized struct snd_timer_user fields when the +read is concurrently performed while the ioctl like +snd_timer_user_tselect() is invoked. We have already fixed the races +among ioctls via a mutex, but we seem to have forgotten the race +between read vs ioctl. + +This patch simply applies (more exactly extends the already applied +range of) tu->ioctl_lock in snd_timer_user_tread() for closing the +race window. + +Reported-by: Alexander Potapenko +Tested-by: Alexander Potapenko +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/timer.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 2f836ca..1118bd8 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -1959,6 +1959,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, + + tu = file->private_data; + unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read); ++ mutex_lock(&tu->ioctl_lock); + spin_lock_irq(&tu->qlock); + while ((long)count - result >= unit) { + while (!tu->qused) { +@@ -1974,7 +1975,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, + add_wait_queue(&tu->qchange_sleep, &wait); + + spin_unlock_irq(&tu->qlock); ++ mutex_unlock(&tu->ioctl_lock); + schedule(); ++ mutex_lock(&tu->ioctl_lock); + spin_lock_irq(&tu->qlock); + + remove_wait_queue(&tu->qchange_sleep, &wait); +@@ -1994,7 +1997,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, + tu->qused--; + spin_unlock_irq(&tu->qlock); + +- mutex_lock(&tu->ioctl_lock); + if (tu->tread) { + if (copy_to_user(buffer, &tu->tqueue[qhead], + sizeof(struct snd_timer_tread))) +@@ -2004,7 +2006,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, + sizeof(struct snd_timer_read))) + err = -EFAULT; + } +- mutex_unlock(&tu->ioctl_lock); + + spin_lock_irq(&tu->qlock); + if (err < 0) +@@ -2014,6 +2015,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, + } + _error: + spin_unlock_irq(&tu->qlock); ++ mutex_unlock(&tu->ioctl_lock); + return result > 0 ? result : err; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-10661/0.patch b/Patches/Linux_CVEs/CVE-2017-10661/0.patch new file mode 100644 index 00000000..e3a8ed31 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10661/0.patch @@ -0,0 +1,99 @@ +From 24a4020b992c7f3cd3320d574947c5a1f51f264d Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Tue, 31 Jan 2017 15:24:03 +0100 +Subject: [PATCH] timerfd: Protect the might cancel mechanism proper + +commit 1e38da300e1e395a15048b0af1e5305bd91402f6 upstream. + +The handling of the might_cancel queueing is not properly protected, so +parallel operations on the file descriptor can race with each other and +lead to list corruptions or use after free. + +Protect the context for these operations with a seperate lock. + +The wait queue lock cannot be reused for this because that would create a +lock inversion scenario vs. the cancel lock. Replacing might_cancel with an +atomic (atomic_t or atomic bit) does not help either because it still can +race vs. the actual list operation. + +Bug: 36266767 + +Reported-by: Dmitry Vyukov +Signed-off-by: Thomas Gleixner +Cc: "linux-fsdevel@vger.kernel.org" +Cc: syzkaller +Cc: Al Viro +Cc: linux-fsdevel@vger.kernel.org +Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1701311521430.3457@nanos +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Siqi Lin +Change-Id: I122753e0920e51757d3012cd1a133e823719be51 +--- + fs/timerfd.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/fs/timerfd.c b/fs/timerfd.c +index 86b32c3cb247f..31374ec8f9bd2 100644 +--- a/fs/timerfd.c ++++ b/fs/timerfd.c +@@ -40,6 +40,7 @@ struct timerfd_ctx { + short unsigned settime_flags; /* to show in fdinfo */ + struct rcu_head rcu; + struct list_head clist; ++ spinlock_t cancel_lock; + bool might_cancel; + }; + +@@ -113,7 +114,7 @@ void timerfd_clock_was_set(void) + rcu_read_unlock(); + } + +-static void timerfd_remove_cancel(struct timerfd_ctx *ctx) ++static void __timerfd_remove_cancel(struct timerfd_ctx *ctx) + { + if (ctx->might_cancel) { + ctx->might_cancel = false; +@@ -123,6 +124,13 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx) + } + } + ++static void timerfd_remove_cancel(struct timerfd_ctx *ctx) ++{ ++ spin_lock(&ctx->cancel_lock); ++ __timerfd_remove_cancel(ctx); ++ spin_unlock(&ctx->cancel_lock); ++} ++ + static bool timerfd_canceled(struct timerfd_ctx *ctx) + { + if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX) +@@ -133,6 +141,7 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx) + + static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags) + { ++ spin_lock(&ctx->cancel_lock); + if ((ctx->clockid == CLOCK_REALTIME || + ctx->clockid == CLOCK_REALTIME_ALARM || + ctx->clockid == CLOCK_POWEROFF_ALARM) && +@@ -143,9 +152,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags) + list_add_rcu(&ctx->clist, &cancel_list); + spin_unlock(&cancel_lock); + } +- } else if (ctx->might_cancel) { +- timerfd_remove_cancel(ctx); ++ } else { ++ __timerfd_remove_cancel(ctx); + } ++ spin_unlock(&ctx->cancel_lock); + } + + static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx) +@@ -397,6 +407,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) + return -ENOMEM; + + init_waitqueue_head(&ctx->wqh); ++ spin_lock_init(&ctx->cancel_lock); + ctx->clockid = clockid; + + if (isalarm(ctx)) { diff --git a/Patches/Linux_CVEs/CVE-2017-10662/0.patch b/Patches/Linux_CVEs/CVE-2017-10662/0.patch new file mode 100644 index 00000000..92c89cee --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10662/0.patch @@ -0,0 +1,56 @@ +From b69c3038bb41fa18c038ed93cf52123fda7f8c69 Mon Sep 17 00:00:00 2001 +From: Jin Qian +Date: Tue, 25 Apr 2017 16:28:48 -0700 +Subject: [PATCH] UPSTREAM: f2fs: sanity check segment count + +commit b9dd46188edc2f0d1f37328637860bb65a771124 upstream. + +F2FS uses 4 bytes to represent block address. As a result, supported +size of disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments. + +Signed-off-by: Jin Qian +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +Bug: 36815012 +Change-Id: I30ea36df066bc07e32e767336b7cae12063fe415 +--- + fs/f2fs/super.c | 8 ++++++++ + include/linux/f2fs_fs.h | 6 ++++++ + 2 files changed, 14 insertions(+) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 03ab8b830940b..77b2cd5ddd569 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -434,6 +434,14 @@ static int sanity_check_raw_super(struct super_block *sb, + f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block"); + return 1; + } ++ ++ if (le32_to_cpu(raw_super->segment_count) > F2FS_MAX_SEGMENT) { ++ f2fs_msg(sb, KERN_INFO, ++ "Invalid segment count (%u)", ++ le32_to_cpu(raw_super->segment_count)); ++ return 1; ++ } ++ + return 0; + } + +diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h +index df6fab82f87e7..fdb6cb9fe0bb3 100644 +--- a/include/linux/f2fs_fs.h ++++ b/include/linux/f2fs_fs.h +@@ -235,6 +235,12 @@ struct f2fs_nat_block { + #define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry)) + + /* ++ * F2FS uses 4 bytes to represent block address. As a result, supported size of ++ * disk is 16 TB and it equals to 16 * 1024 * 1024 / 2 segments. ++ */ ++#define F2FS_MAX_SEGMENT ((16 * 1024 * 1024) / 2) ++ ++/* + * Note that f2fs_sit_entry->vblocks has the following bit-field information. + * [15:10] : allocation type such as CURSEG_XXXX_TYPE + * [9:0] : valid block count diff --git a/Patches/Linux_CVEs/CVE-2017-10663/0.patch b/Patches/Linux_CVEs/CVE-2017-10663/0.patch new file mode 100644 index 00000000..2b50cc9b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10663/0.patch @@ -0,0 +1,57 @@ +From 2b97ce290c589827e21838c70c9c5601b663037a Mon Sep 17 00:00:00 2001 +From: Jin Qian +Date: Thu, 11 May 2017 16:15:15 -0700 +Subject: [PATCH] BACKPORT: f2fs: sanity check checkpoint segno and blkoff + +Make sure segno and blkoff read from raw image are valid. + +Fixed conflicts due to missing commit 1e968fdfe69e +("f2fs: introduce f2fs_cp_error for readability") and commit 6bacf52fb58a +("f2fs: add unlikely() macro for compiler more aggressively"). + +(url https://sourceforge.net/p/linux-f2fs/mailman/message/35835945) + +Signed-off-by: Jin Qian +Signed-off-by: Siqi Lin +Bug: 36588520 +Change-Id: Iba66ab97d3d0870ea48b5ef192d9075f225a934a +--- + fs/f2fs/super.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 77b2cd5ddd569..787d51b7b30d7 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -450,6 +450,8 @@ static int sanity_check_ckpt(struct f2fs_sb_info *sbi) + unsigned int total, fsmeta; + struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); ++ unsigned int main_segs, blocks_per_seg; ++ int i; + + total = le32_to_cpu(raw_super->segment_count); + fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); +@@ -461,6 +463,22 @@ static int sanity_check_ckpt(struct f2fs_sb_info *sbi) + if (fsmeta >= total) + return 1; + ++ main_segs = le32_to_cpu(sbi->raw_super->segment_count_main); ++ blocks_per_seg = sbi->blocks_per_seg; ++ ++ for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { ++ if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs || ++ le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) { ++ return 1; ++ } ++ } ++ for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { ++ if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs || ++ le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) { ++ return 1; ++ } ++ } ++ + if (is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) { + f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck"); + return 1; diff --git a/Patches/Linux_CVEs/CVE-2017-10663/1.patch b/Patches/Linux_CVEs/CVE-2017-10663/1.patch new file mode 100644 index 00000000..f0c46854 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10663/1.patch @@ -0,0 +1,52 @@ +From deaeed5b8acdd10c388616bbc57416cf3db213ff Mon Sep 17 00:00:00 2001 +From: Jin Qian +Date: Mon, 15 May 2017 10:45:08 -0700 +Subject: f2fs: sanity check checkpoint segno and blkoff + +Make sure segno and blkoff read from raw image are valid. + +Cc: stable@vger.kernel.org +Signed-off-by: Jin Qian +[Jaegeuk Kim: adjust minor coding style] +Signed-off-by: Jaegeuk Kim +--- + fs/f2fs/super.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 375dfab..e04be72 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -1509,6 +1509,8 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi) + struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + unsigned int ovp_segments, reserved_segments; ++ unsigned int main_segs, blocks_per_seg; ++ int i; + + total = le32_to_cpu(raw_super->segment_count); + fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); +@@ -1530,6 +1532,20 @@ int sanity_check_ckpt(struct f2fs_sb_info *sbi) + return 1; + } + ++ main_segs = le32_to_cpu(raw_super->segment_count_main); ++ blocks_per_seg = sbi->blocks_per_seg; ++ ++ for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { ++ if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs || ++ le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg) ++ return 1; ++ } ++ for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { ++ if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs || ++ le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg) ++ return 1; ++ } ++ + if (unlikely(f2fs_cp_error(sbi))) { + f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck"); + return 1; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-10996/0.patch b/Patches/Linux_CVEs/CVE-2017-10996/0.patch new file mode 100644 index 00000000..52763a1b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10996/0.patch @@ -0,0 +1,63 @@ +From 9f261e5dfe101bbe35043822a89bffa78e080b3b Mon Sep 17 00:00:00 2001 +From: "Se Wang (Patrick) Oh" +Date: Wed, 2 Sep 2015 21:07:47 -0700 +Subject: arm64: Fix out of bound access to compat_hwcap_str + +As compat_hwcap_str[] doesn't end with 'NULL', c_show() +tries to read the next element even after the end of the +array. So add 'NULL' at the end of compat_hwcap_str[]. +Below is the KASan report for referencing. + +BUG: KASan: out of bounds access in c_show+0x110/0x248 at addr ffffffc0011f6370 +Read of size 8 by task pool-1-thread-1/10526 +page:ffffffbac14b39c0 count:1 mapcount:0 mapping: (null) index:0x0 +flags: 0x400(reserved) +page dumped because: kasan: bad access detected +Address belongs to variable compat_hwcap_str+0xb0/0xe0 +CPU: 0 PID: 10526 Comm: pool-1-thread-1 Tainted: G B W 3.18.18-ga7b28e9-11552-ge4a827f #1 +Hardware name: Qualcomm Technologies, Inc. MSM 8996 v2 + PMI8994 MTP (DT) +Call trace: +[] dump_backtrace+0x0/0x1c4 +[] show_stack+0x10/0x1c +[] dump_stack+0x74/0xc8 +[] kasan_report_error+0x2b0/0x408 +[] kasan_report+0x34/0x40 +[] __asan_load8+0x84/0x90 +[] c_show+0x10c/0x248 +[] traverse+0x1a8/0x320 +[] seq_lseek+0x98/0x148 +[] proc_reg_llseek+0xa0/0xd8 +[] vfs_llseek+0x5c/0x70 +[] SyS_lseek+0x48/0x80 +[] compat_SyS_lseek+0xc/0x18 +Memory state around the buggy address: + ffffffc0011f6200: 00 00 fa fa fa fa fa fa 00 03 fa fa fa fa fa fa + ffffffc0011f6280: 04 fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 +>ffffffc0011f6300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa fa + ^ + ffffffc0011f6380: fa fa fa fa 00 00 00 00 00 00 fa fa fa fa fa fa + ffffffc0011f6400: 02 fa fa fa fa fa fa fa 00 00 00 02 fa fa fa fa + +Change-Id: I5e2098f9a7a676c47a01baf10de3ac1c86265e69 +Signed-off-by: Se Wang (Patrick) Oh +--- + arch/arm64/kernel/setup.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index 58e7c14..1da40ef 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -488,7 +488,8 @@ static const char *compat_hwcap_str[] = { + "idivt", + "vfpd32", + "lpae", +- "evtstrm" ++ "evtstrm", ++ NULL + }; + + static const char *compat_hwcap2_str[] = { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-10997/0.patch b/Patches/Linux_CVEs/CVE-2017-10997/0.patch new file mode 100644 index 00000000..2fcd6a1d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10997/0.patch @@ -0,0 +1,48 @@ +From fae242db5e1943ba878b4fb215fe6e7f1c387a20 Mon Sep 17 00:00:00 2001 +From: Tony Truong +Date: Fri, 6 Jan 2017 14:03:03 -0800 +Subject: msm: pcie: add bounds check for debugfs register write + +Via debugfs nodes, users have the option to read and write to +any PCIe register. To ensure clients do not access registers +outside the PCIe range, add checks to validate the offset clients +provide. + +Bug: 33039685 +Change-Id: Ia35cd04c57f01c21a47962be596bca395b5ca247 +Signed-off-by: Tony Truong +--- + drivers/pci/host/pci-msm.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c +index 1b80fa1..ffaa059 100644 +--- a/drivers/pci/host/pci-msm.c ++++ b/drivers/pci/host/pci-msm.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The 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 +@@ -1691,8 +1691,15 @@ static void msm_pcie_sel_debug_testcase(struct msm_pcie_dev_t *dev, + dev->res[base_sel - 1].base, + wr_offset, wr_mask, wr_value); + +- msm_pcie_write_reg_field(dev->res[base_sel - 1].base, +- wr_offset, wr_mask, wr_value); ++ base_sel_size = resource_size(dev->res[base_sel - 1].resource); ++ ++ if (wr_offset > base_sel_size - 4 || ++ msm_pcie_check_align(dev, wr_offset)) ++ pr_alert("PCIe: RC%d: Invalid wr_offset: 0x%x. wr_offset should be no more than 0x%x\n", ++ dev->rc_idx, wr_offset, base_sel_size - 4); ++ else ++ msm_pcie_write_reg_field(dev->res[base_sel - 1].base, ++ wr_offset, wr_mask, wr_value); + + break; + case 13: /* dump all registers of base_sel */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-10998/0.patch b/Patches/Linux_CVEs/CVE-2017-10998/0.patch new file mode 100644 index 00000000..8429a974 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10998/0.patch @@ -0,0 +1,45 @@ +From 9ffb3cdd7279b011a509267caa4a5119fd6346c0 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Wed, 11 Jan 2017 11:09:24 -0800 +Subject: ASoC: msm: qdsp6v2: extend validation of virtual address + +Validate a buffer virtual address is fully within the region before +returning the region to ensure functionality for an extended edge case. + +Change-Id: Iba3e080889980f393d6a9f0afe0231408b92d654 +Signed-off-by: Siena Richard +CRs-fixed: 1108461 + +Bug: 38195131 +Change-Id: Ib527a380a857719bff8254be514133528bd64c75 +--- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index 07de5a2..42a3ea7 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -1,6 +1,6 @@ + /* Copyright (C) 2008 Google, Inc. + * Copyright (C) 2008 HTC Corporation +- * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -119,7 +119,10 @@ static int audio_aio_ion_lookup_vaddr(struct q6audio_aio *audio, void *addr, + list_for_each_entry(region_elt, &audio->ion_region_queue, list) { + if (addr >= region_elt->vaddr && + addr < region_elt->vaddr + region_elt->len && +- addr + len <= region_elt->vaddr + region_elt->len) { ++ addr + len <= region_elt->vaddr + region_elt->len && ++ addr + len > addr) { ++ /* to avoid integer addition overflow */ ++ + /* offset since we could pass vaddr inside a registerd + * ion buffer + */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-10998/1.patch b/Patches/Linux_CVEs/CVE-2017-10998/1.patch new file mode 100644 index 00000000..9d70672c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10998/1.patch @@ -0,0 +1,43 @@ +From 208e72e59c8411e75d4118b48648a5b7d42b1682 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Wed, 11 Jan 2017 11:09:24 -0800 +Subject: ASoC: msm: qdsp6v2: extend validation of virtual address + +Validate a buffer virtual address is fully within the region before +returning the region to ensure functionality for an extended edge +case. + +Change-Id: Iba3e080889980f393d6a9f0afe0231408b92d654 +Signed-off-by: Siena Richard +CRs-fixed: 1108461 +--- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index 9ade557..c12f791 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -1,6 +1,6 @@ + /* Copyright (C) 2008 Google, Inc. + * Copyright (C) 2008 HTC Corporation +- * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -119,7 +119,10 @@ static int audio_aio_ion_lookup_vaddr(struct q6audio_aio *audio, void *addr, + list_for_each_entry(region_elt, &audio->ion_region_queue, list) { + if (addr >= region_elt->vaddr && + addr < region_elt->vaddr + region_elt->len && +- addr + len <= region_elt->vaddr + region_elt->len) { ++ addr + len <= region_elt->vaddr + region_elt->len && ++ addr + len > addr) { ++ /* to avoid integer addition overflow */ ++ + /* offset since we could pass vaddr inside a registerd + * ion buffer + */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-10999/0.patch b/Patches/Linux_CVEs/CVE-2017-10999/0.patch new file mode 100644 index 00000000..8075517a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-10999/0.patch @@ -0,0 +1,76 @@ +From f51a152ad52108457ae6b1caf7a04857f25c4bed Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Wed, 15 Mar 2017 21:27:35 -0700 +Subject: msm: ipa: fix security issues in ipa wan driver + +Fix the security issue in handling add mux channel event +in ipa wan driver. + +Bug: 36490777 +Change-Id: Ic2ffeafddad4954ec3ecba0d675646d0790eede7 +Signed-off-by: Skylar Chang +Acked-by: Shihuan Liu +--- + drivers/platform/msm/ipa/rmnet_ipa.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/msm/ipa/rmnet_ipa.c b/drivers/platform/msm/ipa/rmnet_ipa.c +index a149a9e..0d6fb33 100644 +--- a/drivers/platform/msm/ipa/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/rmnet_ipa.c +@@ -57,6 +57,7 @@ static atomic_t is_initialized; + static atomic_t is_ssr; + + u32 apps_to_ipa_hdl, ipa_to_apps_hdl; /* get handler from ipa */ ++static struct mutex add_mux_channel_lock; + static int wwan_add_ul_flt_rule_to_ipa(void); + static int wwan_del_ul_flt_rule_to_ipa(void); + +@@ -1242,9 +1243,11 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + rmnet_mux_val.mux_id); + return rc; + } ++ mutex_lock(&add_mux_channel_lock); + if (rmnet_index >= MAX_NUM_OF_MUX_CHANNEL) { + IPAWANERR("Exceed mux_channel limit(%d)\n", + rmnet_index); ++ mutex_unlock(&add_mux_channel_lock); + return -EFAULT; + } + IPAWANDBG("ADD_MUX_CHANNEL(%d, name: %s)\n", +@@ -1270,6 +1273,7 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + IPAWANERR("device %s reg IPA failed\n", + extend_ioctl_data.u. + rmnet_mux_val.vchannel_name); ++ mutex_unlock(&add_mux_channel_lock); + return -ENODEV; + } + mux_channel[rmnet_index].mux_channel_set = true; +@@ -1282,6 +1286,7 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + mux_channel[rmnet_index].ul_flt_reg = false; + } + rmnet_index++; ++ mutex_unlock(&add_mux_channel_lock); + break; + case RMNET_IOCTL_SET_EGRESS_DATA_FORMAT: + IPAWANDBG("get RMNET_IOCTL_SET_EGRESS_DATA_FORMAT\n"); +@@ -2050,7 +2055,7 @@ static int __init ipa_wwan_init(void) + + atomic_set(&is_initialized, 0); + atomic_set(&is_ssr, 0); +- ++ mutex_init(&add_mux_channel_lock); + /* Register for Modem SSR */ + subsys = subsys_notif_register_notifier(SUBSYS_MODEM, &ssr_notifier); + if (!IS_ERR(subsys)) +@@ -2061,6 +2066,7 @@ static int __init ipa_wwan_init(void) + + static void __exit ipa_wwan_cleanup(void) + { ++ mutex_destroy(&add_mux_channel_lock); + platform_driver_unregister(&rmnet_ipa_driver); + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11000/0.patch b/Patches/Linux_CVEs/CVE-2017-11000/0.patch new file mode 100644 index 00000000..63c8233a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11000/0.patch @@ -0,0 +1,33 @@ +From af787fdedeb62964efaf9e969ad17e3b6c232082 Mon Sep 17 00:00:00 2001 +From: Gaoxiang Chen +Date: Wed, 17 May 2017 15:14:36 +0800 +Subject: msm: camera: fix off-by-one overflow in msm_isp_get_bufq + +In msm_isp_get_bufq, if bufq_index equals buf_mgr->num_buf_q, +it will pass the check, leading to off-by-one overflow +(exceed the length of array by one element). + +CRs-Fixed: 2031677 +Bug: 36136563 +Change-Id: I7ea465897e2c37de6ca0155c3e225f1444b3cf13 +Signed-off-by: Gaoxiang Chen +--- + drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +index ee65528..433d59c 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +@@ -46,7 +46,7 @@ struct msm_isp_bufq *msm_isp_get_bufq( + + /* bufq_handle cannot be 0 */ + if ((bufq_handle == 0) || +- (bufq_index > buf_mgr->num_buf_q)) ++ (bufq_index >= buf_mgr->num_buf_q)) + return NULL; + + bufq = &buf_mgr->bufq[bufq_index]; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11001/0.patch b/Patches/Linux_CVEs/CVE-2017-11001/0.patch new file mode 100644 index 00000000..f1499616 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11001/0.patch @@ -0,0 +1,49 @@ +From d5d2c9baff89932e822ceae74b1569af07d55f19 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Fri, 7 Jul 2017 11:58:04 -0700 +Subject: qcacld-2.0: Fix out of bound read issue in get link properties + +Length of the MAC address is not checked which may cause out of bound +read issue. + +To resolve this add a check for MAC address length. + +CRs-Fixed: 2051433 +Change-Id: I58454b84c28b157cef35984d612a9bc6fdd9ec56 +Bug: 36815555 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index c153928..6d99f2d 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -8481,7 +8481,8 @@ static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy, + static const struct + nla_policy + qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = { +- [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { ++ .type = NLA_BINARY, .len = VOS_MAC_ADDR_SIZE }, + }; + + /** +@@ -8536,6 +8537,13 @@ static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy, + return -EINVAL; + } + ++ if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < sizeof(peer_mac)) { ++ hddLog(VOS_TRACE_LEVEL_ERROR, ++ FL("Attribute peerMac is invalid=%d"), ++ adapter->device_mode); ++ return -EINVAL; ++ } ++ + memcpy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]), + sizeof(peer_mac)); + hddLog(VOS_TRACE_LEVEL_INFO, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11002/0.patch b/Patches/Linux_CVEs/CVE-2017-11002/0.patch new file mode 100644 index 00000000..658443df --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11002/0.patch @@ -0,0 +1,88 @@ +From 825eeb85d4866e362452b18df929a54a7c6111f6 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Mon, 10 Jul 2017 11:50:46 -0700 +Subject: qcacld-2.0: Avoid concurrent matrix max param overread + +qcacld-3.0 to qcacld-2.0 propagation + +Currently there is no nl policy defined for vendor sub command +QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX which may result in +buffer overread error. + +To resolve this, add nl policy. + +Change-Id: I155efdbb07f1c5fe300bb2be0c2a3fe07c7e134b +CRs-Fixed: 2058452 +Bug: 37712167 +Signed-off-by: Srinivas Girigowda +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 24 ++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 6d99f2d..13956f9 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1666,6 +1666,15 @@ wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy, + return ret; + } + ++#define MAX_CONCURRENT_MATRIX \ ++ QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX ++#define MATRIX_CONFIG_PARAM_SET_SIZE_MAX \ ++ QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX ++static const struct nla_policy ++wlan_hdd_get_concurrency_matrix_policy[MAX_CONCURRENT_MATRIX + 1] = { ++ [MATRIX_CONFIG_PARAM_SET_SIZE_MAX] = {.type = NLA_U32}, ++}; ++ + static int + __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + struct wireless_dev *wdev, +@@ -1674,7 +1683,7 @@ __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + { + uint32_t feature_set_matrix[WLAN_HDD_MAX_FEATURE_SET] = {0}; + uint8_t i, feature_sets, max_feature_sets; +- struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1]; ++ struct nlattr *tb[MAX_CONCURRENT_MATRIX + 1]; + struct sk_buff *reply_skb; + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + int ret; +@@ -1690,19 +1699,19 @@ __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + if (0 != ret) + return ret; + +- if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX, +- data, data_len, NULL)) { ++ if (nla_parse(tb, MAX_CONCURRENT_MATRIX, ++ data, data_len, wlan_hdd_get_concurrency_matrix_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + /* Parse and fetch max feature set */ +- if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) { ++ if (!tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) { + hddLog(LOGE, FL("Attr max feature set size failed")); + return -EINVAL; + } +- max_feature_sets = nla_get_u32( +- tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]); ++ ++ max_feature_sets = nla_get_u32(tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]); + hddLog(LOG1, FL("Max feature set size: %d"), max_feature_sets); + + /* Fill feature combination matrix */ +@@ -1744,6 +1753,9 @@ __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + return -ENOMEM; + } + ++#undef MAX_CONCURRENT_MATRIX ++#undef MATRIX_CONFIG_PARAM_SET_SIZE_MAX ++ + /** + * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix + * @wiphy: pointer to wireless wiphy structure. +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11040/0.patch b/Patches/Linux_CVEs/CVE-2017-11040/0.patch new file mode 100644 index 00000000..6e70834b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11040/0.patch @@ -0,0 +1,35 @@ +From 7a4d0eea0ca0c8a72111ae58d9829be817f102c9 Mon Sep 17 00:00:00 2001 +From: Ashish Garg +Date: Fri, 9 Jun 2017 16:21:20 +0530 +Subject: msm: mdss: validate number of cea blocks before reading from edid_buf + +Number of cea blocks are read from edid buffer which comes from the +user. If the number of cea blocks are more than the supported blocks +kernel information leak is possible by reading more data than is +present in edid_buf. + +Change-Id: I03b8456ff1e1a7b15d711f06908bd5c83f83cc02 +Signed-off-by: Ashish Garg +--- + drivers/video/fbdev/msm/mdss_hdmi_tx.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c +index 4975aa2..9f897b4 100644 +--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c ++++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c +@@ -632,6 +632,11 @@ static ssize_t hdmi_tx_sysfs_rda_edid(struct device *dev, + + mutex_lock(&hdmi_ctrl->tx_lock); + cea_blks = hdmi_ctrl->edid_buf[EDID_BLOCK_SIZE - 2]; ++ if (cea_blks >= MAX_EDID_BLOCKS) { ++ DEV_ERR("%s: invalid cea blocks\n", __func__); ++ mutex_unlock(&hdmi_ctrl->tx_lock); ++ return -EINVAL; ++ } + size = (cea_blks + 1) * EDID_BLOCK_SIZE; + size = min_t(u32, size, PAGE_SIZE); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11046/0.patch b/Patches/Linux_CVEs/CVE-2017-11046/0.patch new file mode 100644 index 00000000..497d4f6f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11046/0.patch @@ -0,0 +1,48 @@ +From 5ff192e2c758298680b0c6cd364a55c59850901f Mon Sep 17 00:00:00 2001 +From: Vidyakumar Athota +Date: Tue, 20 Jun 2017 16:39:00 -0700 +Subject: [PATCH] ASoC: msm: qdsp6v2: add size check to fix out of bounds issue + +Before calling audio calibration ioctl functions, compare the +allocated buffer size to the size of the header and cal type header +to ensure the buffer is big enough. + +Bug: 37623773 +Change-Id: I601bb37ddcc34d459c207cf579f29744fe912d7b +Signed-off-by: Vidyakumar Athota +--- + sound/soc/msm/qdsp6v2/audio_calibration.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/audio_calibration.c b/sound/soc/msm/qdsp6v2/audio_calibration.c +index 60d09dfaeb7f7..2a1b34776b686 100644 +--- a/sound/soc/msm/qdsp6v2/audio_calibration.c ++++ b/sound/soc/msm/qdsp6v2/audio_calibration.c +@@ -453,6 +453,12 @@ static long audio_cal_shared_ioctl(struct file *file, unsigned int cmd, + data->cal_type.cal_hdr.buffer_number); + ret = -EINVAL; + goto done; ++ } else if ((data->hdr.cal_type_size + sizeof(data->hdr)) > size) { ++ pr_err("%s: cal type hdr size %zd + cal type size %d is greater than user buffer size %d\n", ++ __func__, sizeof(data->hdr), data->hdr.cal_type_size, ++ size); ++ ret = -EFAULT; ++ goto done; + } + + +@@ -490,13 +496,7 @@ static long audio_cal_shared_ioctl(struct file *file, unsigned int cmd, + goto unlock; + if (data == NULL) + goto unlock; +- if ((sizeof(data->hdr) + data->hdr.cal_type_size) > size) { +- pr_err("%s: header size %zd plus cal type size %d are greater than data buffer size %d\n", +- __func__, sizeof(data->hdr), +- data->hdr.cal_type_size, size); +- ret = -EFAULT; +- goto unlock; +- } else if (copy_to_user((void *)arg, data, ++ if (copy_to_user(arg, data, + sizeof(data->hdr) + data->hdr.cal_type_size)) { + pr_err("%s: Could not copy cal type to user\n", + __func__); diff --git a/Patches/Linux_CVEs/CVE-2017-11048/0.patch b/Patches/Linux_CVEs/CVE-2017-11048/0.patch new file mode 100644 index 00000000..df7f27b5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11048/0.patch @@ -0,0 +1,38 @@ +From a42f6e19316e9e5aaaf8bd2c3bec25fde136dcaa Mon Sep 17 00:00:00 2001 +From: Jayant Shekhar +Date: Thu, 22 Jun 2017 11:46:47 +0530 +Subject: [PATCH] msm: mdss: Increase fbmem buf ref count before use + +The reference count for fbmem buf is not increased before use, +which means it can be get freed unintentionally when the reference +count is decreased to "0". In this case, there is possibility of +use after free. Ensure that fbmem buf refcount is incremented +before use. + +Bug: 37093119 +Change-Id: I525d41e5496a1123e53a438b5f78d4da8bc046bd +Signed-off-by: Jayant Shekhar +--- + drivers/video/msm/mdss/mdss_mdp_overlay.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c +index 86c6196432e10..4ab89d11d1daa 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c ++++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c +@@ -3917,11 +3917,14 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd, + break; + case metadata_op_get_ion_fd: + if (mfd->fb_ion_handle) { ++ get_dma_buf(mfd->fbmem_buf); + metadata->data.fbmem_ionfd = + dma_buf_fd(mfd->fbmem_buf, 0); +- if (metadata->data.fbmem_ionfd < 0) ++ if (metadata->data.fbmem_ionfd < 0) { ++ dma_buf_put(mfd->fbmem_buf); + pr_err("fd allocation failed. fd = %d\n", + metadata->data.fbmem_ionfd); ++ } + } + break; + case metadata_op_crc: diff --git a/Patches/Linux_CVEs/CVE-2017-11050/0.patch b/Patches/Linux_CVEs/CVE-2017-11050/0.patch new file mode 100644 index 00000000..819a9ff6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11050/0.patch @@ -0,0 +1,45 @@ +From 725674586f5bc009ef5175d29eb0fd677e0ef1f2 Mon Sep 17 00:00:00 2001 +From: "Poddar, Siddarth" +Date: Mon, 3 Jul 2017 15:57:19 +0530 +Subject: qcacld-2.0: Restrict max/min pktlog buffer size using pktlogconf tool + +Restrict the pktlog buffer size to a minimum of 1MB and maximum +of 16MB using pktlogconf tool or through sysctl command. + +CRs-Fixed: 2064785 +Change-Id: I2951de86de083b610bb114ff4b9ddcb51c4c3042 +--- + CORE/UTILS/PKTLOG/pktlog_ac.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/CORE/UTILS/PKTLOG/pktlog_ac.c b/CORE/UTILS/PKTLOG/pktlog_ac.c +index 823d2d5..679a78c 100644 +--- a/CORE/UTILS/PKTLOG/pktlog_ac.c ++++ b/CORE/UTILS/PKTLOG/pktlog_ac.c +@@ -424,14 +424,22 @@ int pktlog_enable(struct ol_softc *scn, int32_t log_state) + return error; + } + ++#define ONE_MEGABYTE (1024 * 1024) ++#define MAX_ALLOWED_PKTLOG_SIZE (16 * ONE_MEGABYTE) + + static int + __pktlog_setsize(struct ol_softc *scn, int32_t size) + { + struct ol_pktlog_dev_t *pl_dev = scn->pdev_txrx_handle->pl_dev; + struct ath_pktlog_info *pl_info = pl_dev->pl_info; +- if (size < 0) ++ ++ if (size < ONE_MEGABYTE || size > MAX_ALLOWED_PKTLOG_SIZE) { ++ printk("%s: Cannot Set Pktlog Buffer size of %d bytes." ++ "Min required is %d MB and Max allowed is %d MB.\n", ++ __func__, size, (ONE_MEGABYTE/ONE_MEGABYTE), ++ (MAX_ALLOWED_PKTLOG_SIZE/ONE_MEGABYTE)); + return -EINVAL; ++ } + + if (size == pl_info->buf_size) + return 0; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11050/1.patch b/Patches/Linux_CVEs/CVE-2017-11050/1.patch new file mode 100644 index 00000000..c45ab055 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11050/1.patch @@ -0,0 +1,45 @@ +From 4d7233954031dcb34e08fb4f6a82fc3e9f08ce12 Mon Sep 17 00:00:00 2001 +From: "Poddar, Siddarth" +Date: Mon, 3 Jul 2017 15:57:19 +0530 +Subject: [PATCH] qcacld-2.0: Restrict max/min pktlog buffer size using + pktlogconf tool + +Restrict the pktlog buffer size to a minimum of 1MB and maximum +of 16MB using pktlogconf tool or through sysctl command. + +Bug: 62085265 +CRs-Fixed: 2064785 +Change-Id: I2951de86de083b610bb114ff4b9ddcb51c4c3042 +Signed-off-by: Ecco Park +--- + drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c +index 3d38ca44617d6..542ff90ba5952 100644 +--- a/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c ++++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c +@@ -389,14 +389,22 @@ pktlog_enable(struct ol_softc *scn, int32_t log_state) + return 0; + } + ++#define ONE_MEGABYTE (1024 * 1024) ++#define MAX_ALLOWED_PKTLOG_SIZE (16 * ONE_MEGABYTE) ++ + int + pktlog_setsize(struct ol_softc *scn, int32_t size) + { + struct ol_pktlog_dev_t *pl_dev = scn->pdev_txrx_handle->pl_dev; + struct ath_pktlog_info *pl_info = pl_dev->pl_info; + +- if (size < 0) ++ if (size < ONE_MEGABYTE || size > MAX_ALLOWED_PKTLOG_SIZE) { ++ printk("%s: Cannot Set Pktlog Buffer size of %d bytes." ++ "Min required is %d MB and Max allowed is %d MB.\n", ++ __func__, size, (ONE_MEGABYTE/ONE_MEGABYTE), ++ (MAX_ALLOWED_PKTLOG_SIZE/ONE_MEGABYTE)); + return -EINVAL; ++ } + + if (size == pl_info->buf_size) + return 0; diff --git a/Patches/Linux_CVEs/CVE-2017-11051/0.patch b/Patches/Linux_CVEs/CVE-2017-11051/0.patch new file mode 100644 index 00000000..3c8001fb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11051/0.patch @@ -0,0 +1,31 @@ +From c8f263f0e3b0b6cba38fae9b2330d77f802c51d8 Mon Sep 17 00:00:00 2001 +From: Ashish Kumar Dhanotiya +Date: Thu, 6 Jul 2017 16:51:53 +0530 +Subject: qcacld-2.0: Fix Uninitialized memory issue + +There is a possibility to read uninitialized memory within api +__wlan_hdd_cfg80211_testmode. + +To resolve this issue, initilaize buffer hb_params with zero. + +Change-Id: Ia8061610a8c35aa7290177c0dcd2c5c36d9fcb35 +CRs-Fixed: 2061755 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 20f127b..b19cfd8 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -28402,6 +28402,7 @@ static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, + return -ENOMEM; + } + ++ vos_mem_zero(hb_params, sizeof(tSirLPHBReq)); + vos_mem_copy(hb_params, buf, buf_len); + smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal), + hb_params, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11051/1.patch b/Patches/Linux_CVEs/CVE-2017-11051/1.patch new file mode 100644 index 00000000..03320fd4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11051/1.patch @@ -0,0 +1,30 @@ +From 9e08c4d35fc520e9c375884abdf04493e157a0ea Mon Sep 17 00:00:00 2001 +From: Ashish Kumar Dhanotiya +Date: Thu, 6 Jul 2017 16:51:53 +0530 +Subject: [PATCH] qcacld-2.0: Fix Uninitialized memory issue + +There is a possibility to read uninitialized memory within api +__wlan_hdd_cfg80211_testmode. + +To resolve this issue, initilaize buffer hb_params with zero. + +Bug: 62456806 +Change-Id: Ia8061610a8c35aa7290177c0dcd2c5c36d9fcb35 +CRs-Fixed: 2061755 +Signed-off-by: Ecco Park +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 13956f9063ede..9338b4b98ed5e 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -21990,6 +21990,7 @@ static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy, + return -ENOMEM; + } + ++ vos_mem_zero(hb_params, sizeof(tSirLPHBReq)); + vos_mem_copy(hb_params, buf, buf_len); + smeStatus = sme_LPHBConfigReq((tHalHandle)(pHddCtx->hHal), + hb_params, diff --git a/Patches/Linux_CVEs/CVE-2017-11052/0.patch b/Patches/Linux_CVEs/CVE-2017-11052/0.patch new file mode 100644 index 00000000..02939a76 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11052/0.patch @@ -0,0 +1,42 @@ +From c1ea8487f35d3f4dea574552afda6a1637f98bbb Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Thu, 15 Jun 2017 12:47:46 -0700 +Subject: qcacld-2.0: Properly validate QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR + +Currently the QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR nla_policy specifies +a type of NLA_STRING, but the underlying implementation expects a +NUL-terminated string. Update the policy to correctly use a type of +NLA_NUL_STRING with the len updated to remove the allocation needed +for the terminating NUL. + +Change-Id: Ic73241511ab73ae63fd7c1a8d6422da91931919c +CRs-Fixed: 2061688 +--- + CORE/HDD/src/wlan_hdd_nan_datapath.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_nan_datapath.c b/CORE/HDD/src/wlan_hdd_nan_datapath.c +index 2a2e6e4..d29a23a 100644 +--- a/CORE/HDD/src/wlan_hdd_nan_datapath.c ++++ b/CORE/HDD/src/wlan_hdd_nan_datapath.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -40,8 +40,8 @@ static const struct nla_policy + qca_wlan_vendor_ndp_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID] = { .type = NLA_U16 }, +- [QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR] = { .type = NLA_STRING, +- .len = IFNAMSIZ }, ++ [QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR] = { .type = NLA_NUL_STRING, ++ .len = IFNAMSIZ - 1 }, + [QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR] = { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11052/1.patch b/Patches/Linux_CVEs/CVE-2017-11052/1.patch new file mode 100644 index 00000000..3e1ea966 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11052/1.patch @@ -0,0 +1,41 @@ +From c18c5935d437e4b06ec630d755a42b49e11bd071 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Thu, 15 Jun 2017 12:47:46 -0700 +Subject: [PATCH] qcacld-2.0: Properly validate + QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR + +Currently the QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR nla_policy specifies +a type of NLA_STRING, but the underlying implementation expects a +NUL-terminated string. Update the policy to correctly use a type of +NLA_NUL_STRING with the len updated to remove the allocation needed +for the terminating NUL. + +Bug: 37687303 +Change-Id: Ic73241511ab73ae63fd7c1a8d6422da91931919c +CRs-Fixed: 2061688 +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_nan_datapath.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_nan_datapath.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_nan_datapath.c +index 1b5e4db3100c7..469ae96818cf4 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_nan_datapath.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_nan_datapath.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -38,8 +38,8 @@ static const struct nla_policy + qca_wlan_vendor_ndp_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID] = { .type = NLA_U16 }, +- [QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR] = { .type = NLA_STRING, +- .len = IFNAMSIZ }, ++ [QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR] = { .type = NLA_NUL_STRING, ++ .len = IFNAMSIZ - 1 }, + [QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR] = { diff --git a/Patches/Linux_CVEs/CVE-2017-11053/0.patch b/Patches/Linux_CVEs/CVE-2017-11053/0.patch new file mode 100644 index 00000000..58d91137 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11053/0.patch @@ -0,0 +1,40 @@ +From 99c00329bc13c526305dc826950c2cc117e6725d Mon Sep 17 00:00:00 2001 +From: yeshwanth sriram guntuka +Date: Mon, 3 Jul 2017 11:44:31 +0530 +Subject: qcacld-2.0: Fix kernel memory corruption + +Buffer overflow in ConvertQosMapsetFrame function +when num_dscp_exceptions value is less than 16. + +Fix is to return from function if num_dscp_exceptions +is less than 16. + +Change-Id: I2fcce60b7fe5e988348cee786e9a4d493d9512fe +CRs-Fixed: 2061544 +--- + CORE/SYS/legacy/src/utils/src/utilsParser.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/CORE/SYS/legacy/src/utils/src/utilsParser.c b/CORE/SYS/legacy/src/utils/src/utilsParser.c +index 6c99939..e64ce33 100644 +--- a/CORE/SYS/legacy/src/utils/src/utilsParser.c ++++ b/CORE/SYS/legacy/src/utils/src/utilsParser.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -706,6 +706,8 @@ void ConvertQosMapsetFrame(tpAniSirGlobal pMac, tSirQosMapSet* Qos, tDot11fIEQos + tANI_U8 i,j=0; + if (dot11fIE->num_dscp_exceptions > 58) + dot11fIE->num_dscp_exceptions = 58; ++ if (dot11fIE->num_dscp_exceptions < 16) ++ return; + Qos->num_dscp_exceptions = (dot11fIE->num_dscp_exceptions - 16)/2; + for (i = 0; i < Qos->num_dscp_exceptions; i++) + { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11053/1.patch b/Patches/Linux_CVEs/CVE-2017-11053/1.patch new file mode 100644 index 00000000..d014b1c2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11053/1.patch @@ -0,0 +1,41 @@ +From 6a16567622ff6ccc2a23bd8884b0781995a481b1 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Thu, 3 Aug 2017 16:59:51 -0700 +Subject: [PATCH] qcacld-2.0: Fix kernel memory corruption + +Buffer overflow in ConvertQosMapsetFrame function +when num_dscp_exceptions value is less than 16. + +Fix is to return from function if num_dscp_exceptions +is less than 16. + +Change-Id: I2fcce60b7fe5e988348cee786e9a4d493d9512fe +CRs-Fixed: 2061544 +Bug: 36895857 +Signed-off-by: Srinivas Girigowda +--- + .../staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsParser.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsParser.c b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsParser.c +index 6c9993935b481..887e33ada81ae 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsParser.c ++++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/utilsParser.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -706,6 +706,10 @@ void ConvertQosMapsetFrame(tpAniSirGlobal pMac, tSirQosMapSet* Qos, tDot11fIEQos + tANI_U8 i,j=0; + if (dot11fIE->num_dscp_exceptions > 58) + dot11fIE->num_dscp_exceptions = 58; ++ ++ if (dot11fIE->num_dscp_exceptions < 16) ++ return; ++ + Qos->num_dscp_exceptions = (dot11fIE->num_dscp_exceptions - 16)/2; + for (i = 0; i < Qos->num_dscp_exceptions; i++) + { diff --git a/Patches/Linux_CVEs/CVE-2017-11054/0.patch b/Patches/Linux_CVEs/CVE-2017-11054/0.patch new file mode 100644 index 00000000..772c38c8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11054/0.patch @@ -0,0 +1,90 @@ +From 4d9812973e8b12700afd8c3d6f36a94506ffb6fc Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Thu, 15 Jun 2017 10:51:02 -0700 +Subject: qcacld-2.0: Avoid overread when configuring MAC addresses + +Currently there are multiple cfg80211 vendor commands where MAC +address attributes are defined in a nla_policy table with a type of +NLA_UNSPEC but without a minimum length. Add the proper minimum length +to avoid buffer overread. + +Change-Id: I11ff2bd813dc4e6784a7cdee66a0c10ca0e69fcf +CRs-Fixed: 2061251 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 1ac1fc1..2ec3d68 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -841,7 +841,9 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = { .type = NLA_U8 }, + + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = { .type = NLA_U32 }, +- [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = { .type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = { .type = NLA_U32 }, +@@ -8080,7 +8082,9 @@ wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy, + static const struct nla_policy + wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] = + { +- [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {.type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] = + {.type = NLA_S32 }, +@@ -8092,15 +8096,18 @@ wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] = + static const struct nla_policy + wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +1] = + { +- [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = {.type = NLA_UNSPEC }, +- ++ [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + }; + + static const struct nla_policy + wlan_hdd_tdls_config_state_change_policy[ + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX +1] = + { +- [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = {.type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + [QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL] = {.type = NLA_U32 }, +@@ -8113,7 +8120,9 @@ static const struct nla_policy + wlan_hdd_tdls_config_get_status_policy[ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX +1] = + { +- [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = {.type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL] = {.type = NLA_U32 }, +@@ -10761,8 +10770,9 @@ static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy, + static const struct + nla_policy + qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = { +- [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = +- { .type = NLA_BINARY, .len = VOS_MAC_ADDR_SIZE }, ++ [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { ++ .type = NLA_BINARY, ++ .len = HDD_MAC_ADDR_LEN}, + }; + + /** +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11054/1.patch b/Patches/Linux_CVEs/CVE-2017-11054/1.patch new file mode 100644 index 00000000..e417f8bc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11054/1.patch @@ -0,0 +1,87 @@ +From 7dff4291c6aecad9143b8fc2c0769f818834c33a Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Thu, 15 Jun 2017 10:51:02 -0700 +Subject: [PATCH] qcacld-2.0: Avoid overread when configuring MAC addresses + +Currently there are multiple cfg80211 vendor commands where MAC +address attributes are defined in a nla_policy table with a type of +NLA_UNSPEC but without a minimum length. Add the proper minimum length +to avoid buffer overread. + +Bug: 37713609 +Change-Id: I11ff2bd813dc4e6784a7cdee66a0c10ca0e69fcf +CRs-Fixed: 2061251 +Signed-off-by: Ecco Park +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 24 +++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 6849a6c82f821..94b161e37a59a 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -833,7 +833,9 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = { .type = NLA_U8 }, + + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = { .type = NLA_U32 }, +- [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = { .type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = { .type = NLA_U32 }, +@@ -6742,7 +6744,9 @@ int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid, + static const struct nla_policy + wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] = + { +- [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {.type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] = + {.type = NLA_S32 }, +@@ -6754,15 +6758,18 @@ wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] = + static const struct nla_policy + wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +1] = + { +- [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = {.type = NLA_UNSPEC }, +- ++ [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + }; + + static const struct nla_policy + wlan_hdd_tdls_config_state_change_policy[ + QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX +1] = + { +- [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = {.type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + [QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL] = {.type = NLA_U32 }, +@@ -6775,7 +6782,9 @@ static const struct nla_policy + wlan_hdd_tdls_config_get_status_policy[ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX +1] = + { +- [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = {.type = NLA_UNSPEC }, ++ [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = { ++ .type = NLA_UNSPEC, ++ .len = HDD_MAC_ADDR_LEN}, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON] = {.type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL] = {.type = NLA_U32 }, +@@ -8493,7 +8502,8 @@ static const struct + nla_policy + qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = { + [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { +- .type = NLA_BINARY, .len = VOS_MAC_ADDR_SIZE }, ++ .type = NLA_BINARY, ++ .len = HDD_MAC_ADDR_LEN}, + }; + + /** diff --git a/Patches/Linux_CVEs/CVE-2017-11055/0.patch b/Patches/Linux_CVEs/CVE-2017-11055/0.patch new file mode 100644 index 00000000..b152eb98 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11055/0.patch @@ -0,0 +1,30 @@ +From 708633ca627031373f5cc3ca2e8994e7d694905a Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Thu, 15 Jun 2017 09:24:17 -0700 +Subject: qcacld-2.0: Apply policy to fine time measurement + +Currently QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT is not +properly represented in the wlan_hdd_wifi_config_policy table, so add +a proper initializer. + +Change-Id: I95ba66337c30cae67b23c9942b9360522ad60df0 +CRs-Fixed: 2061241 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 6624176..1ac1fc1 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -9612,6 +9612,7 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32}, + [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_RATE] = {.type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 }, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11055/1.patch b/Patches/Linux_CVEs/CVE-2017-11055/1.patch new file mode 100644 index 00000000..1521b173 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11055/1.patch @@ -0,0 +1,30 @@ +From 9f5af4954a048f408f70c7dfeef0d8f655abca10 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Thu, 15 Jun 2017 09:24:17 -0700 +Subject: [PATCH] qcacld-2.0: Apply policy to fine time measurement + +Currently QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT is not +properly represented in the wlan_hdd_wifi_config_policy table, so add +a proper initializer. + +Bug: 37721426 + +Change-Id: I95ba66337c30cae67b23c9942b9360522ad60df0 +CRs-Fixed: 2061241 +Signed-off-by: Ecco Park +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 9338b4b98ed5e..af3ab9bc4bd57 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -8051,6 +8051,7 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32}, + [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_RATE] = {.type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 }, diff --git a/Patches/Linux_CVEs/CVE-2017-11056/0.patch b/Patches/Linux_CVEs/CVE-2017-11056/0.patch new file mode 100644 index 00000000..306f3fe5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11056/0.patch @@ -0,0 +1,93 @@ +From d5481967f73c5448b9b2ae528a75faa0b040bc42 Mon Sep 17 00:00:00 2001 +From: mohamed sunfeer +Date: Wed, 21 Jun 2017 15:21:58 +0530 +Subject: [PATCH] compat_qcedev: Fix accessing userspace memory in kernel space + +Use put_user API to write the data to userspace from kernel +space to avoid accessing userspace memory directly in +kernel space. + +Bug: 37893116 +Change-Id: I3f0b0f13e720c052c8c23dfb36ffaccc484369ec +Signed-off-by: mohamed sunfeer +--- + drivers/crypto/msm/compat_qcedev.c | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +diff --git a/drivers/crypto/msm/compat_qcedev.c b/drivers/crypto/msm/compat_qcedev.c +index 97ae990b5378b..4b36e7343aff6 100644 +--- a/drivers/crypto/msm/compat_qcedev.c ++++ b/drivers/crypto/msm/compat_qcedev.c +@@ -1,7 +1,7 @@ + /* + * QTI CE 32-bit compatibility syscall for 64-bit systems + * +- * Copyright (c) 2014, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2015, 2017, The 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 +@@ -97,7 +97,6 @@ static int compat_get_qcedev_vbuf_info( + + for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { + err |= get_user(vaddr, &vbuf32->src[i].vaddr); +- vbuf->src[i].vaddr = NULL; + err |= put_user(vaddr, (compat_uptr_t *)&vbuf->src[i].vaddr); + err |= get_user(len, &vbuf32->src[i].len); + err |= put_user(len, &vbuf->src[i].len); +@@ -105,7 +104,6 @@ static int compat_get_qcedev_vbuf_info( + + for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { + err |= get_user(vaddr, &vbuf32->dst[i].vaddr); +- vbuf->dst[i].vaddr = NULL; + err |= put_user(vaddr, (compat_uptr_t *)&vbuf->dst[i].vaddr); + err |= get_user(len, &vbuf32->dst[i].len); + err |= put_user(len, &vbuf->dst[i].len); +@@ -123,7 +121,6 @@ static int compat_put_qcedev_vbuf_info( + + for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { + err |= get_user(vaddr, (compat_uptr_t *)&vbuf->src[i].vaddr); +- vbuf32->src[i].vaddr = 0; + err |= put_user(vaddr, &vbuf32->src[i].vaddr); + err |= get_user(len, &vbuf->src[i].len); + err |= put_user(len, &vbuf32->src[i].len); +@@ -131,7 +128,6 @@ static int compat_put_qcedev_vbuf_info( + + for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { + err |= get_user(vaddr, (compat_uptr_t *)&vbuf->dst[i].vaddr); +- vbuf32->dst[i].vaddr = 0; + err |= put_user(vaddr, &vbuf32->dst[i].vaddr); + err |= get_user(len, &vbuf->dst[i].len); + err |= put_user(len, &vbuf32->dst[i].len); +@@ -276,7 +272,6 @@ static int compat_get_qcedev_sha_op_req( + + for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { + err |= get_user(vaddr, &data32->data[i].vaddr); +- data->data[i].vaddr = 0; + err |= put_user(vaddr, (compat_uptr_t *)&data->data[i].vaddr); + err |= get_user(len, &data32->data[i].len); + err |= put_user(len, &data->data[i].len); +@@ -295,7 +290,6 @@ static int compat_get_qcedev_sha_op_req( + err |= get_user(diglen, &data32->diglen); + err |= put_user(diglen, &data->diglen); + err |= get_user(authkey, &data32->authkey); +- data->authkey = NULL; + err |= put_user(authkey, (compat_uptr_t *)&data->authkey); + err |= get_user(authklen, &data32->authklen); + err |= put_user(authklen, &data->authklen); +@@ -322,7 +316,6 @@ static int compat_put_qcedev_sha_op_req( + + for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) { + err |= get_user(vaddr, (compat_uptr_t *)&data->data[i].vaddr); +- data32->data[i].vaddr = 0; + err |= put_user(vaddr, &data32->data[i].vaddr); + err |= get_user(len, &data->data[i].len); + err |= put_user(len, &data32->data[i].len); +@@ -341,7 +334,6 @@ static int compat_put_qcedev_sha_op_req( + err |= get_user(diglen, &data->diglen); + err |= put_user(diglen, &data32->diglen); + err |= get_user(authkey, (compat_uptr_t *)&data->authkey); +- data32->authkey = 0; + err |= put_user(authkey, &data32->authkey); + err |= get_user(authklen, &data->authklen); + err |= put_user(authklen, &data32->authklen); diff --git a/Patches/Linux_CVEs/CVE-2017-11057/0.patch b/Patches/Linux_CVEs/CVE-2017-11057/0.patch new file mode 100644 index 00000000..8d6e9bd5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11057/0.patch @@ -0,0 +1,84 @@ +From 270bb9351889878dbfc87a6797886cb3caf42430 Mon Sep 17 00:00:00 2001 +From: kaiwang +Date: Tue, 27 Jun 2017 19:29:03 +0800 +Subject: [PATCH] msm: camera: sensor:validating the flash initialization + parameters + +Copying the flash initialization parameters from userspace memory to +kernel memory and in turn checking for the validity of the flash +initialization parameters pointer sent from userspace + +CRs-Fixed: 2059812 +Bug: 37949660 +Change-Id: I957c10959108eb08b263d439a9a449b90338b6db +Signed-off-by: kaiwang +--- + .../msm/camera_v2/sensor/flash/msm_flash.c | 38 +++++++++++++++++----- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +index 4a13ef87898d7..0390e0e60deab 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +@@ -498,22 +498,44 @@ static int32_t msm_flash_init( + return 0; + } + +-#ifdef CONFIG_COMPAT + static int32_t msm_flash_init_prepare( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) + { ++#ifdef CONFIG_COMPAT ++ struct msm_flash_cfg_data_t flash_data_k; ++ struct msm_flash_init_info_t flash_init_info; ++ int32_t i = 0; ++ if(!is_compat_task()) { ++ /*for 64-bit usecase,it need copy the data to local memory*/ ++ flash_data_k.cfg_type = flash_data->cfg_type; ++ for (i = 0; i < MAX_LED_TRIGGERS; i++) { ++ flash_data_k.flash_current[i] = ++ flash_data->flash_current[i]; ++ flash_data_k.flash_duration[i] = ++ flash_data->flash_duration[i]; ++ } ++ ++ flash_data_k.cfg.flash_init_info = &flash_init_info; ++ if (copy_from_user(&flash_init_info, ++ (void *)(flash_data->cfg.flash_init_info), ++ sizeof(struct msm_flash_init_info_t))) { ++ pr_err("%s copy_from_user failed %d\n", ++ __func__, __LINE__); ++ return -EFAULT; ++ } ++ return msm_flash_init(flash_ctrl, &flash_data_k); ++ } ++ /* ++ * for 32-bit usecase,it already copy the userspace ++ * data to local memory in msm_flash_subdev_do_ioctl() ++ * so here do not need copy from user ++ */ + return msm_flash_init(flash_ctrl, flash_data); +-} + #else +-static int32_t msm_flash_init_prepare( +- struct msm_flash_ctrl_t *flash_ctrl, +- struct msm_flash_cfg_data_t *flash_data) +-{ + struct msm_flash_cfg_data_t flash_data_k; + struct msm_flash_init_info_t flash_init_info; + int32_t i = 0; +- + flash_data_k.cfg_type = flash_data->cfg_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_data_k.flash_current[i] = +@@ -531,8 +553,8 @@ static int32_t msm_flash_init_prepare( + return -EFAULT; + } + return msm_flash_init(flash_ctrl, &flash_data_k); +-} + #endif ++} + + static int32_t msm_flash_low( + struct msm_flash_ctrl_t *flash_ctrl, diff --git a/Patches/Linux_CVEs/CVE-2017-11059/0.patch b/Patches/Linux_CVEs/CVE-2017-11059/0.patch new file mode 100644 index 00000000..6458e65d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11059/0.patch @@ -0,0 +1,83 @@ +From be632ce97422dfe533944186e2f4420b87b87ad5 Mon Sep 17 00:00:00 2001 +From: Oleg Matcovschi +Date: Wed, 9 Aug 2017 23:18:19 -0700 +Subject: [PATCH] crypto: msm: Fix several race condition issues in crypto + drivers + +Check areq before referencing, replace xchg to automic_xchg and +verify return values of set key during SHA operations. + +Bug: 37284397 +Signed-off-by: Brahmaji K +Signed-off-by: Paresh Purabhiya +Change-Id: I98a9541a1d3a8c8d5e974348c76b92da1d5102e6 +--- + drivers/crypto/msm/qce50.c | 4 ++++ + drivers/crypto/msm/qcrypto.c | 14 ++++++++++---- + 2 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c +index 0e017b3c0c3ff..6bd9d56b13566 100644 +--- a/drivers/crypto/msm/qce50.c ++++ b/drivers/crypto/msm/qce50.c +@@ -2055,6 +2055,10 @@ static int _sha_complete(struct qce_device *pce_dev) + uint32_t status; + + areq = (struct ahash_request *) pce_dev->areq; ++ if (!areq) { ++ pr_err("sha operation error. areq is NULL\n"); ++ return -ENXIO; ++ } + qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents, + DMA_TO_DEVICE); + memcpy(digest, (char *)(&pce_dev->ce_sps.result->auth_iv[0]), +diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c +index 04b28a58e38bd..e64d1dd51cb5f 100644 +--- a/drivers/crypto/msm/qcrypto.c ++++ b/drivers/crypto/msm/qcrypto.c +@@ -3514,6 +3514,7 @@ static int _sha1_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int len) + { + struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base); ++ int ret = 0; + memset(&sha_ctx->authkey[0], 0, SHA1_BLOCK_SIZE); + if (len <= SHA1_BLOCK_SIZE) { + memcpy(&sha_ctx->authkey[0], key, len); +@@ -3521,16 +3522,19 @@ static int _sha1_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, + } else { + sha_ctx->alg = QCE_HASH_SHA1; + sha_ctx->diglen = SHA1_DIGEST_SIZE; +- _sha_hmac_setkey(tfm, key, len); ++ ret = _sha_hmac_setkey(tfm, key, len); ++ if (ret) ++ pr_err("SHA1 hmac setkey failed\n"); + sha_ctx->authkey_in_len = SHA1_BLOCK_SIZE; + } +- return 0; ++ return ret; + } + + static int _sha256_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int len) + { + struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base); ++ int ret = 0; + + memset(&sha_ctx->authkey[0], 0, SHA256_BLOCK_SIZE); + if (len <= SHA256_BLOCK_SIZE) { +@@ -3539,11 +3543,13 @@ static int _sha256_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, + } else { + sha_ctx->alg = QCE_HASH_SHA256; + sha_ctx->diglen = SHA256_DIGEST_SIZE; +- _sha_hmac_setkey(tfm, key, len); ++ ret = _sha_hmac_setkey(tfm, key, len); ++ if (ret) ++ pr_err("SHA256 hmac setkey failed\n"); + sha_ctx->authkey_in_len = SHA256_BLOCK_SIZE; + } + +- return 0; ++ return ret; + } + + static int _sha_hmac_init_ihash(struct ahash_request *req, diff --git a/Patches/Linux_CVEs/CVE-2017-11060/0.patch b/Patches/Linux_CVEs/CVE-2017-11060/0.patch new file mode 100644 index 00000000..2000cbb1 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11060/0.patch @@ -0,0 +1,116 @@ +From 657bb41463b837b2681e1fed310bd97970b09b83 Mon Sep 17 00:00:00 2001 +From: Mukul Sharma +Date: Mon, 19 Jun 2017 19:21:42 +0530 +Subject: qcacld-2.0: Avoid buffer overread when parsing PNO commands + +Propagation from qcacld-3.0 to qcacld-2.0 + +There are currently three issues which can result in a buffer overread +when processing PNO vendor commands: +1) __wlan_hdd_cfg80211_set_passpoint_list() specifies the wrong policy + when invoking nla_parse(). +2) hdd_extscan_passpoint_fill_network_list() does not specify a policy + when invoking nla_parse(). +3) __wlan_hdd_cfg80211_set_epno_list() specifies a policy but not all + of the attributes that are parsed are present in the policy. +To prevent buffer overread: +1) Update __wlan_hdd_cfg80211_set_passpoint_list() and + hdd_extscan_passpoint_fill_network_list() to use the policy + wlan_hdd_pno_config_policy. +2) Update wlan_hdd_pno_config_policy to contain all the fixed-length + attributes needed by __wlan_hdd_cfg80211_set_passpoint_list(), + hdd_extscan_passpoint_fill_network_list(), and + __wlan_hdd_cfg80211_set_epno_list(). + +Change-Id: I4a20e77ce87967ae78323b83a2aa9085fed2647f +CRs-Fixed: 2058447 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 58 +++++++++++++++++++++++++++++----------- + 1 file changed, 43 insertions(+), 15 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index cae8b45..20f127b 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -868,19 +868,46 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + + static const struct nla_policy + wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = { +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = { +- .type = NLA_U32 +- }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = { +- .type = NLA_BINARY, +- .len = IEEE80211_MAX_SSID_LEN + 1 +- }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = { +- .type = NLA_U8 +- }, +- [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = { +- .type = NLA_U8 +- }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = { ++ .type = NLA_BINARY, ++ .len = IEEE80211_MAX_SSID_LEN + 1 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = { ++ .type = NLA_U8 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = { ++ .type = NLA_U8 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS] = { ++ .type = NLA_U32 ++ }, + }; + + static const struct nla_policy +@@ -4914,7 +4941,8 @@ static int hdd_extscan_passpoint_fill_network_list( + + if (nla_parse(network, + QCA_WLAN_VENDOR_ATTR_PNO_MAX, +- nla_data(networks), nla_len(networks), NULL)) { ++ nla_data(networks), nla_len(networks), ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } +@@ -5015,7 +5043,7 @@ static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len, +- wlan_hdd_extscan_config_policy)) { ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11060/1.patch b/Patches/Linux_CVEs/CVE-2017-11060/1.patch new file mode 100644 index 00000000..99dd14b9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11060/1.patch @@ -0,0 +1,97 @@ +From 5204ea3cae1b07aad76d9d831e46dfaea492f488 Mon Sep 17 00:00:00 2001 +From: Mukul Sharma +Date: Mon, 19 Jun 2017 19:21:42 +0530 +Subject: [PATCH] qcacld-2.0: Avoid buffer overread when parsing PNO commands + +Propagation from qcacld-3.0 to qcacld-2.0 + +There are currently three issues which can result in a buffer overread +when processing PNO vendor commands: +1) __wlan_hdd_cfg80211_set_passpoint_list() specifies the wrong policy + when invoking nla_parse(). +2) hdd_extscan_passpoint_fill_network_list() does not specify a policy + when invoking nla_parse(). +3) __wlan_hdd_cfg80211_set_epno_list() specifies a policy but not all + of the attributes that are parsed are present in the policy. +To prevent buffer overread: +1) Update __wlan_hdd_cfg80211_set_passpoint_list() and + hdd_extscan_passpoint_fill_network_list() to use the policy + wlan_hdd_pno_config_policy. +2) Update wlan_hdd_pno_config_policy to contain all the fixed-length + attributes needed by __wlan_hdd_cfg80211_set_passpoint_list(), + hdd_extscan_passpoint_fill_network_list(), and + __wlan_hdd_cfg80211_set_epno_list(). + +Bug: 36817548 +Bug: 36815952 +Change-Id: I4a20e77ce87967ae78323b83a2aa9085fed2647f +CRs-Fixed: 2058447 +Signed-off-by: Ecco Park +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 32 ++++++++++++++++++++-- + 1 file changed, 30 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 94b161e37a59a..c7d271f91ceb9 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -857,6 +857,12 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + + static const struct nla_policy + wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID] = { ++ .type = NLA_U32 ++ }, + [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = { + .type = NLA_U32 + }, +@@ -870,6 +876,27 @@ wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = { + .type = NLA_U8 + }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS] = { ++ .type = NLA_U32 ++ }, ++ [QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS] = { ++ .type = NLA_U32 ++ }, + }; + + static const struct nla_policy +@@ -4696,7 +4723,8 @@ static int hdd_extscan_passpoint_fill_network_list( + + if (nla_parse(network, + QCA_WLAN_VENDOR_ATTR_PNO_MAX, +- nla_data(networks), nla_len(networks), NULL)) { ++ nla_data(networks), nla_len(networks), ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } +@@ -4918,7 +4946,7 @@ static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy, + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len, +- wlan_hdd_extscan_config_policy)) { ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } diff --git a/Patches/Linux_CVEs/CVE-2017-11060/2.patch b/Patches/Linux_CVEs/CVE-2017-11060/2.patch new file mode 100644 index 00000000..2de4d635 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11060/2.patch @@ -0,0 +1,36 @@ +From 49eec96af9448e23a8fc2e41f67db948983b8427 Mon Sep 17 00:00:00 2001 +From: Ecco Park +Date: Wed, 16 Aug 2017 16:45:03 -0700 +Subject: [PATCH] qcacld-2.0: Avoid buffer overread when parsing PNO commands + +fix merge of 5204ea3cae1b07aad76d9d831e46dfaea492f488 + +Bug: 36817548 +Change-Id: Ie5abe6ed5797588688f3a83cf12a964429ed11d3 +Signed-off-by: Ecco Park +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index da139cf225ce2..9029ef3b9e4a3 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -4873,7 +4873,7 @@ static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy, + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len, +- wlan_hdd_extscan_config_policy)) { ++ wlan_hdd_pno_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } +@@ -4994,7 +4994,7 @@ static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy, + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len, +- wlan_hdd_pno_config_policy)) { ++ wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } diff --git a/Patches/Linux_CVEs/CVE-2017-11061/0.patch b/Patches/Linux_CVEs/CVE-2017-11061/0.patch new file mode 100644 index 00000000..3e8a5fac --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11061/0.patch @@ -0,0 +1,110 @@ +From e08628a3cfe039bc4bdd7fc66f5ec7a59a97b404 Mon Sep 17 00:00:00 2001 +From: Ravi Kumar Bokka +Date: Mon, 12 Jun 2017 21:34:30 +0530 +Subject: qcacld-2.0: Validate vendor set roaming params command + +Currently there is no nl policy defined for vendor sub command +QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX which may result in +buffer overread error. + +To resolve this, add nl policy. + +Change-Id: Ib5d3c34dbcec29a98766753efc4e9c4ecf748c2e +CRs-Fixed: 2059701 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 51 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 47 insertions(+), 4 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 57ba680..313de1e 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1870,6 +1870,49 @@ wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + return ret; + } + ++#define MAX_ROAMING_PARAM \ ++ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX ++ ++static const struct nla_policy ++wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD] = { ++ .type = NLA_S32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD] = { ++ .type = NLA_S32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS] = { ++ .type = NLA_S32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE] = { ++ .type = NLA_S32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID] = { ++ .type = NLA_BINARY, ++ .len = MAC_ADDRESS_STR_LEN}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID] = { ++ .type = NLA_BINARY, ++ .len = MAC_ADDRESS_STR_LEN}, ++}; ++ + static int + __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct wireless_dev *wdev, +@@ -1901,7 +1944,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + data, data_len, +- NULL)) { ++ wlan_hdd_set_roam_param_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } +@@ -1940,7 +1983,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX, + nla_data(curr_attr), nla_len(curr_attr), +- NULL)) { ++ wlan_hdd_set_roam_param_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } +@@ -2104,7 +2147,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +- NULL)) { ++ wlan_hdd_set_roam_param_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } +@@ -2166,7 +2209,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +- NULL)) { ++ wlan_hdd_set_roam_param_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11061/1.patch b/Patches/Linux_CVEs/CVE-2017-11061/1.patch new file mode 100644 index 00000000..22bcd96e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11061/1.patch @@ -0,0 +1,109 @@ +From 42a28a93ef19863c39ade86843efb83efc845344 Mon Sep 17 00:00:00 2001 +From: Ravi Kumar Bokka +Date: Mon, 12 Jun 2017 21:34:30 +0530 +Subject: [PATCH] qcacld-2.0: Validate vendor set roaming params command + +Currently there is no nl policy defined for vendor sub command +QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX which may result in +buffer overread error. + +To resolve this, add nl policy. + +Bug: 36816726 +Change-Id: Ib5d3c34dbcec29a98766753efc4e9c4ecf748c2e +CRs-Fixed: 2059701 +Signed-off-by: Ecco Park +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 51 ++++++++++++++++++++-- + 1 file changed, 47 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index b788566363d87..5ca269bab9cf6 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -1809,6 +1809,49 @@ wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy, + return ret; + } + ++#define MAX_ROAMING_PARAM \ ++ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX ++ ++static const struct nla_policy ++wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = { ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD] = { ++ .type = NLA_S32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD] = { ++ .type = NLA_S32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS] = { ++ .type = NLA_S32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE] = { ++ .type = NLA_S32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID] = { ++ .type = NLA_BINARY, ++ .len = MAC_ADDRESS_STR_LEN}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID] = { ++ .type = NLA_U32}, ++ [QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID] = { ++ .type = NLA_BINARY, ++ .len = MAC_ADDRESS_STR_LEN}, ++}; ++ + static int + __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + struct wireless_dev *wdev, +@@ -1840,7 +1883,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + data, data_len, +- NULL)) { ++ wlan_hdd_set_roam_param_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } +@@ -1869,7 +1912,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX, + nla_data(curr_attr), nla_len(curr_attr), +- NULL)) { ++ wlan_hdd_set_roam_param_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } +@@ -2024,7 +2067,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +- NULL)) { ++ wlan_hdd_set_roam_param_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } +@@ -2086,7 +2129,7 @@ __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy, + if (nla_parse(tb2, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX, + nla_data(curr_attr), nla_len(curr_attr), +- NULL)) { ++ wlan_hdd_set_roam_param_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + goto fail; + } diff --git a/Patches/Linux_CVEs/CVE-2017-11062/0.patch b/Patches/Linux_CVEs/CVE-2017-11062/0.patch new file mode 100644 index 00000000..7f64a118 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11062/0.patch @@ -0,0 +1,74 @@ +From 954bdf216ce56a860092fd9549229b036e08c97b Mon Sep 17 00:00:00 2001 +From: Ashish Kumar Dhanotiya +Date: Tue, 13 Jun 2017 18:41:49 +0530 +Subject: qcacld-2.0: Validate vendor command do_acs + +Currently attributes are not validated in __wlan_hdd_cfg80211_do_acs, +this can lead to a buffer overread. + +To resolve this issue, Define an nla_policy and validate the +attributes. + +CRs-Fixed: 2058448 +Change-Id: Ic1bd5abbef09407f925625b709f10cf9cb7c3d7f +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 27 +++++++++++++-------------- + 1 file changed, 13 insertions(+), 14 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 2ec3d68..c87f7c0 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -9170,9 +9170,20 @@ static void + wlan_hdd_set_mcc_to_scc_switch(hdd_adapter_t *adapter) + {} + #endif ++static const struct nla_policy ++wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = { ++ [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC }, ++}; ++ + + /** +- * __wlan_hdd_cfg80211_do_acs : CFG80211 handler fucntion for DO_ACS Vendor CMD ++ * __wlan_hdd_cfg80211_do_acs() : CFG80211 handler fucntion for DO_ACS ++ * Vendor CMD + * @wiphy: Linux wiphy struct pointer + * @wdev: Linux wireless device struct pointer + * @data: ACS information from hostapd +@@ -9216,18 +9227,6 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, + * config shall be set only from start_acs. + */ + +- /* nla_policy Policy template. Policy not applied as some attributes are +- * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length +- * +- * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED }, +- */ +- +- + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + return status; +@@ -9257,7 +9256,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, + vos_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg)); + + status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len, +- NULL); ++ wlan_hdd_cfg80211_do_acs_policy); + if (status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + goto out; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11062/1.patch b/Patches/Linux_CVEs/CVE-2017-11062/1.patch new file mode 100644 index 00000000..f517a6f9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11062/1.patch @@ -0,0 +1,68 @@ +From 6d19d7d4e0ff7e7e4c80c49414a016035ac70a3c Mon Sep 17 00:00:00 2001 +From: Ashish Kumar Dhanotiya +Date: Tue, 13 Jun 2017 18:41:49 +0530 +Subject: [PATCH] qcacld-2.0: Validate vendor command do_acs + +Currently attributes are not validated in __wlan_hdd_cfg80211_do_acs, +this can lead to a buffer overread. + +To resolve this issue, Define an nla_policy and validate the +attributes. + +Bug: 37720349 +CRs-Fixed: 2058448 +Change-Id: Ic1bd5abbef09407f925625b709f10cf9cb7c3d7f +Signed-off-by: Ecco Park +--- + .../qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 24 ++++++++++------------ + 1 file changed, 11 insertions(+), 13 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index af3ab9bc4bd57..6849a6c82f821 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -7665,6 +7665,16 @@ static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter) + return 0; + } + ++static const struct nla_policy ++wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = { ++ [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 }, ++ [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC }, ++}; ++ + /** + * __wlan_hdd_cfg80211_do_acs : CFG80211 handler fucntion for DO_ACS Vendor CMD + * @wiphy: Linux wiphy struct pointer +@@ -7710,18 +7720,6 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, + * config shall be set only from start_acs. + */ + +- /* nla_policy Policy template. Policy not applied as some attributes are +- * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length +- * +- * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 }, +- * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED }, +- */ +- +- + status = wlan_hdd_validate_context(hdd_ctx); + if (0 != status) + return status; +@@ -7730,7 +7728,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, + vos_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg)); + + status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len, +- NULL); ++ wlan_hdd_cfg80211_do_acs_policy); + if (status) { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Invalid ATTR")); + goto out; diff --git a/Patches/Linux_CVEs/CVE-2017-11064/0.patch b/Patches/Linux_CVEs/CVE-2017-11064/0.patch new file mode 100644 index 00000000..7cf55ffb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11064/0.patch @@ -0,0 +1,63 @@ +From 38d6f16b8583bae6a1881c744ae08d609c99cb7e Mon Sep 17 00:00:00 2001 +From: Ashish Kumar Dhanotiya +Date: Fri, 14 Jul 2017 15:25:52 +0530 +Subject: qcacld-2.0: Add an attribute to represent PNO/EPNO Request ID + +This request ID was wrongly referred from the REQUEST_ID in +enum qca_wlan_vendor_attr_gscan_config_params which is mapped to +QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM in PNO Config. +Hence define a different attribute to represent the request ID +for the PNO Config. + +CRs-Fixed: 2066628 +Change-Id: I2b5efe78605d07d92db564a987ea0ae4ff0a2cc8 +--- + CORE/HDD/inc/wlan_hdd_cfg80211.h | 2 ++ + CORE/HDD/src/wlan_hdd_cfg80211.c | 7 +++++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h +index 2a2f7d9..291ebd6 100644 +--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h ++++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h +@@ -1417,6 +1417,8 @@ enum qca_wlan_vendor_attr_pno_config_params { + */ + QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS = 22, + ++ /* Unsigned 32-bit value, representing the PNO Request ID */ ++ QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID = 23, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST, +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 2ec4ca3..8279b8f 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -908,6 +908,9 @@ wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS] = { + .type = NLA_U32 + }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID] = { ++ .type = NLA_U32 ++ }, + }; + + static const struct nla_policy +@@ -4772,12 +4775,12 @@ static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, + req_msg->num_networks = num_networks; + + /* Parse and fetch request Id */ +- if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { ++ if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + req_msg->request_id = nla_get_u32( +- tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); ++ tb[QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID]); + + req_msg->session_id = adapter->sessionId; + hddLog(LOG1, FL("Req Id %u Session Id %d"), +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11064/1.patch b/Patches/Linux_CVEs/CVE-2017-11064/1.patch new file mode 100644 index 00000000..39b5f6b8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11064/1.patch @@ -0,0 +1,62 @@ +From 856abd9ad16d9d69e688d06a1f548c2f8df67c02 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Fri, 11 Aug 2017 12:58:11 -0700 +Subject: [PATCH] qcacld-2.0: Add an attribute to represent PNO/EPNO Request ID + +This request ID was wrongly referred from the REQUEST_ID in +enum qca_wlan_vendor_attr_gscan_config_params which is mapped to +QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM in PNO Config. +Hence define a different attribute to represent the request ID +for the PNO Config. + +CRs-Fixed: 2066628 +Change-Id: I2b5efe78605d07d92db564a987ea0ae4ff0a2cc8 +Bug: 36815952 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h | 2 ++ + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 7 +++++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h +index 23770788afd2a..bf3b4fe65d961 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h +@@ -1285,6 +1285,8 @@ enum qca_wlan_vendor_attr_pno_config_params { + */ + QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS = 22, + ++ /* Unsigned 32-bit value, representing the PNO Request ID */ ++ QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID = 23, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST, +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 9029ef3b9e4a3..178cf32975efb 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -901,6 +901,9 @@ wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS] = { + .type = NLA_U32 + }, ++ [QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID] = { ++ .type = NLA_U32 ++ }, + }; + + static const struct nla_policy +@@ -4607,12 +4610,12 @@ static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy, + req_msg->num_networks = num_networks; + + /* Parse and fetch request Id */ +- if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) { ++ if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID]) { + hddLog(LOGE, FL("attr request id failed")); + goto fail; + } + req_msg->request_id = nla_get_u32( +- tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]); ++ tb[QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID]); + + req_msg->session_id = adapter->sessionId; + hddLog(LOG1, FL("Req Id %u Session Id %d"), diff --git a/Patches/Linux_CVEs/CVE-2017-11067/0.patch b/Patches/Linux_CVEs/CVE-2017-11067/0.patch new file mode 100644 index 00000000..1cf5d43b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11067/0.patch @@ -0,0 +1,147 @@ +From a172c24c714b118cd15a5295d11e992216785a82 Mon Sep 17 00:00:00 2001 +From: Govind Singh +Date: Fri, 2 Dec 2016 15:31:18 +0530 +Subject: qcacld-2.0: Check target address boundary before access + +LTP tests each procfs entry with random address, as athdiag +procfs does not have address sanity check. This is resulting in +invalid ioread32/iowrite32. + +Fix this by checking address with in PCIE BAR range. + +Change-Id: I8365eacca7ccc4f489b7d0bda6c998384d0fec7b +CRs-Fixed: 1097111 +--- + CORE/SERVICES/COMMON/hif.h | 8 ++++++++ + CORE/SERVICES/HIF/PCIe/hif_pci.c | 26 ++++++++++++++++++++++++++ + CORE/SERVICES/HIF/PCIe/if_pci.c | 1 + + CORE/SERVICES/HIF/PCIe/if_pci.h | 2 +- + CORE/SERVICES/HIF/ath_procfs.c | 11 ++++++++--- + 5 files changed, 44 insertions(+), 4 deletions(-) + +diff --git a/CORE/SERVICES/COMMON/hif.h b/CORE/SERVICES/COMMON/hif.h +index a3c31af..06a02ee 100644 +--- a/CORE/SERVICES/COMMON/hif.h ++++ b/CORE/SERVICES/COMMON/hif.h +@@ -880,4 +880,12 @@ static inline void hif_request_runtime_pm_resume(void *ol_sc) + + A_BOOL HIFIsMailBoxSwapped(HIF_DEVICE *hd); + ++#ifdef HIF_PCI ++int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset); ++#else ++static inline int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset) ++{ ++ return 0; ++} ++#endif + #endif /* _HIF_H_ */ +diff --git a/CORE/SERVICES/HIF/PCIe/hif_pci.c b/CORE/SERVICES/HIF/PCIe/hif_pci.c +index 2e1d580..e640b45 100644 +--- a/CORE/SERVICES/HIF/PCIe/hif_pci.c ++++ b/CORE/SERVICES/HIF/PCIe/hif_pci.c +@@ -3627,3 +3627,29 @@ bool hif_is_80211_fw_wow_required(void) + { + return false; + } ++ ++/* hif_addr_in_boundary() - API to check if addr is with in PCIE BAR range ++ * @hif_device: context of cd ++ * @offset: offset from PCI BAR mapped base address. ++ * ++ * API determines if address to be accessed is with in range or out ++ * of bound. ++ * ++ * Return: success if address is with in PCI BAR range. ++ */ ++int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset) ++{ ++ struct HIF_CE_state *hif_state; ++ struct hif_pci_softc *sc; ++ ++ hif_state = (struct HIF_CE_state *)hif_device; ++ sc = hif_state->sc; ++ if (unlikely(offset + sizeof(unsigned int) > sc->mem_len)) { ++ VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, ++ "refusing to read mmio out of bounds at 0x%08x - 0x%08zx (max 0x%08zx)\n", ++ offset, offset + sizeof(unsigned int), sc->mem_len); ++ return -EINVAL; ++ } ++ ++ return 0; ++} +diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c +index 018855c..f4988c7 100644 +--- a/CORE/SERVICES/HIF/PCIe/if_pci.c ++++ b/CORE/SERVICES/HIF/PCIe/if_pci.c +@@ -1682,6 +1682,7 @@ again: + + OS_MEMZERO(sc, sizeof(*sc)); + sc->mem = mem; ++ sc->mem_len = pci_resource_len(pdev, BAR_NUM); + sc->pdev = pdev; + sc->dev = &pdev->dev; + +diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.h b/CORE/SERVICES/HIF/PCIe/if_pci.h +index ffb4df9..0abd26a 100644 +--- a/CORE/SERVICES/HIF/PCIe/if_pci.h ++++ b/CORE/SERVICES/HIF/PCIe/if_pci.h +@@ -82,7 +82,7 @@ struct hif_pci_pm_stats { + struct hif_pci_softc { + void __iomem *mem; /* PCI address. */ + /* For efficiency, should be first in struct */ +- ++ size_t mem_len; + struct device *dev; + struct pci_dev *pdev; + struct _NIC_DEV aps_osdev; +diff --git a/CORE/SERVICES/HIF/ath_procfs.c b/CORE/SERVICES/HIF/ath_procfs.c +index 7b653a1..cfdf97a 100644 +--- a/CORE/SERVICES/HIF/ath_procfs.c ++++ b/CORE/SERVICES/HIF/ath_procfs.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013, 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -90,13 +90,16 @@ static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf, + int rv; + A_UINT8 *read_buffer = NULL; + ++ hif_hdl = get_hif_hdl_from_file(file); ++ if (hif_addr_in_boundary(hif_hdl, (A_UINT32)(*pos))) ++ return -EINVAL; ++ + read_buffer = (A_UINT8 *)vos_mem_malloc(count); + if (NULL == read_buffer) { + pr_debug("%s: vos_mem_alloc failed\n", __func__); + return -EINVAL; + } + +- hif_hdl = get_hif_hdl_from_file(file); + pr_debug("rd buff 0x%p cnt %zu offset 0x%x buf 0x%p\n", + read_buffer,count, + (int)*pos, buf); +@@ -130,6 +133,9 @@ static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, + int rv; + A_UINT8 *write_buffer = NULL; + ++ hif_hdl = get_hif_hdl_from_file(file); ++ if (hif_addr_in_boundary(hif_hdl, (A_UINT32)(*pos))) ++ return -EINVAL; + write_buffer = (A_UINT8 *)vos_mem_malloc(count); + if (NULL == write_buffer) { + pr_debug("%s: vos_mem_alloc failed\n", __func__); +@@ -140,7 +146,6 @@ static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, + return -EFAULT; + } + +- hif_hdl = get_hif_hdl_from_file(file); + pr_debug("wr buff 0x%p buf 0x%p cnt %zu offset 0x%x value 0x%x\n", + write_buffer, buf, count, + (int)*pos, *((A_UINT32 *)write_buffer)); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-11067/1.patch b/Patches/Linux_CVEs/CVE-2017-11067/1.patch new file mode 100644 index 00000000..c5527abc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11067/1.patch @@ -0,0 +1,139 @@ +From 3fabdcba3a09ce8f3cc757bf6240e53421a1e363 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Fri, 4 Aug 2017 15:51:34 -0700 +Subject: [PATCH] qcacld-2.0: Check target address boundary before access + +Athdiag procfs entry does not have address sanity check, this is +resulting in invalid ioread32/iowrite32 if out of PCIE BAR address +is used. + +Fix this by allowing address with in PCIE BAR range. + +Change-Id: I8365eacca7ccc4f489b7d0bda6c998384d0fec7b +CRs-Fixed: 2062012 +Bug: 62058746 +Signed-off-by: Srinivas Girigowda +--- + .../staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h | 8 +++++++ + .../qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c | 26 ++++++++++++++++++++++ + .../qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c | 1 + + .../qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h | 2 +- + .../qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c | 9 ++++++-- + 5 files changed, 43 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h +index a3c31afe3bd67..06a02eebc1be5 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/hif.h +@@ -880,4 +880,12 @@ static inline void hif_request_runtime_pm_resume(void *ol_sc) + + A_BOOL HIFIsMailBoxSwapped(HIF_DEVICE *hd); + ++#ifdef HIF_PCI ++int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset); ++#else ++static inline int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset) ++{ ++ return 0; ++} ++#endif + #endif /* _HIF_H_ */ +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c +index 3a1de9d23d07a..ba33ac976305a 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/hif_pci.c +@@ -3628,3 +3628,29 @@ bool hif_is_80211_fw_wow_required(void) + { + return false; + } ++ ++/* hif_addr_in_boundary() - API to check if addr is with in PCIE BAR range ++ * @hif_device: context of cd ++ * @offset: offset from PCI BAR mapped base address. ++ * ++ * API determines if address to be accessed is with in range or out ++ * of bound. ++ * ++ * Return: success if address is with in PCI BAR range. ++ */ ++int hif_addr_in_boundary(HIF_DEVICE *hif_device, A_UINT32 offset) ++{ ++ struct HIF_CE_state *hif_state; ++ struct hif_pci_softc *sc; ++ ++ hif_state = (struct HIF_CE_state *)hif_device; ++ sc = hif_state->sc; ++ if (unlikely(offset + sizeof(unsigned int) > sc->mem_len)) { ++ VOS_TRACE(VOS_MODULE_ID_HIF, VOS_TRACE_LEVEL_ERROR, ++ "refusing to read mmio out of bounds at 0x%08x - 0x%08zx (max 0x%08zx)\n", ++ offset, offset + sizeof(unsigned int), sc->mem_len); ++ return -EINVAL; ++ } ++ ++ return 0; ++} +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c +index 17792cd6460e4..0d5fd226f5275 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c +@@ -1589,6 +1589,7 @@ hif_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + OS_MEMZERO(sc, sizeof(*sc)); + sc->mem = mem; ++ sc->mem_len = pci_resource_len(pdev, BAR_NUM); + sc->pdev = pdev; + sc->dev = &pdev->dev; + +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h +index 3204f6101eb9d..ea0e22d3d1a80 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.h +@@ -82,7 +82,7 @@ struct hif_pci_pm_stats { + struct hif_pci_softc { + void __iomem *mem; /* PCI address. */ + /* For efficiency, should be first in struct */ +- ++ size_t mem_len; + struct device *dev; + struct pci_dev *pdev; + struct _NIC_DEV aps_osdev; +diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c +index ed0cfd69d7228..d1a34dd6c3966 100644 +--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c ++++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/ath_procfs.c +@@ -90,13 +90,16 @@ static ssize_t ath_procfs_diag_read(struct file *file, char __user *buf, + int rv; + A_UINT8 *read_buffer = NULL; + ++ hif_hdl = get_hif_hdl_from_file(file); ++ if (hif_addr_in_boundary(hif_hdl, (A_UINT32)(*pos))) ++ return -EINVAL; ++ + read_buffer = (A_UINT8 *)vos_mem_malloc(count); + if (NULL == read_buffer) { + pr_debug("%s: vos_mem_alloc failed\n", __func__); + return -EINVAL; + } + +- hif_hdl = get_hif_hdl_from_file(file); + pr_debug("rd buff 0x%p cnt %zu offset 0x%x buf 0x%p\n", + read_buffer,count, + (int)*pos, buf); +@@ -129,6 +132,9 @@ static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, + int rv; + A_UINT8 *write_buffer = NULL; + ++ hif_hdl = get_hif_hdl_from_file(file); ++ if (hif_addr_in_boundary(hif_hdl, (A_UINT32)(*pos))) ++ return -EINVAL; + write_buffer = (A_UINT8 *)vos_mem_malloc(count); + if (NULL == write_buffer) { + pr_debug("%s: vos_mem_alloc failed\n", __func__); +@@ -139,7 +145,6 @@ static ssize_t ath_procfs_diag_write(struct file *file, const char __user *buf, + return -EFAULT; + } + +- hif_hdl = get_hif_hdl_from_file(file); + pr_debug("wr buff 0x%p buf 0x%p cnt %zu offset 0x%x value 0x%x\n", + write_buffer, buf, count, + (int)*pos, *((A_UINT32 *)write_buffer)); diff --git a/Patches/Linux_CVEs/CVE-2017-11600/0.patch b/Patches/Linux_CVEs/CVE-2017-11600/0.patch new file mode 100644 index 00000000..61187e6f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-11600/0.patch @@ -0,0 +1,44 @@ +From 7bab09631c2a303f87a7eb7e3d69e888673b9b7e Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Wed, 2 Aug 2017 19:50:14 +0200 +Subject: xfrm: policy: check policy direction value + +The 'dir' parameter in xfrm_migrate() is a user-controlled byte which is used +as an array index. This can lead to an out-of-bound access, kernel lockup and +DoS. Add a check for the 'dir' value. + +This fixes CVE-2017-11600. + +References: https://bugzilla.redhat.com/show_bug.cgi?id=1474928 +Fixes: 80c9abaabf42 ("[XFRM]: Extension for dynamic update of endpoint address(es)") +Cc: # v2.6.21-rc1 +Reported-by: "bo Zhang" +Signed-off-by: Vladis Dronov +Signed-off-by: Steffen Klassert +--- + net/xfrm/xfrm_policy.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index ff61d85..6f5a0dad 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -3308,9 +3308,15 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, + struct xfrm_state *x_new[XFRM_MAX_DEPTH]; + struct xfrm_migrate *mp; + ++ /* Stage 0 - sanity checks */ + if ((err = xfrm_migrate_check(m, num_migrate)) < 0) + goto out; + ++ if (dir >= XFRM_POLICY_MAX) { ++ err = -EINVAL; ++ goto out; ++ } ++ + /* Stage 1 - find policy */ + if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) { + err = -ENOENT; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-12146/0.patch b/Patches/Linux_CVEs/CVE-2017-12146/0.patch new file mode 100644 index 00000000..2ae4f16e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-12146/0.patch @@ -0,0 +1,63 @@ +From 6265539776a0810b7ce6398c27866ddb9c6bd154 Mon Sep 17 00:00:00 2001 +From: Adrian Salido +Date: Tue, 25 Apr 2017 16:55:26 -0700 +Subject: driver core: platform: fix race condition with driver_override + +The driver_override implementation is susceptible to race condition when +different threads are reading vs storing a different driver override. +Add locking to avoid race condition. + +Fixes: 3d713e0e382e ("driver core: platform: add device binding path 'driver_override'") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Salido +Signed-off-by: Greg Kroah-Hartman +--- + drivers/base/platform.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index a102152..97332d0 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -866,7 +866,7 @@ static ssize_t driver_override_store(struct device *dev, + const char *buf, size_t count) + { + struct platform_device *pdev = to_platform_device(dev); +- char *driver_override, *old = pdev->driver_override, *cp; ++ char *driver_override, *old, *cp; + + if (count > PATH_MAX) + return -EINVAL; +@@ -879,12 +879,15 @@ static ssize_t driver_override_store(struct device *dev, + if (cp) + *cp = '\0'; + ++ device_lock(dev); ++ old = pdev->driver_override; + if (strlen(driver_override)) { + pdev->driver_override = driver_override; + } else { + kfree(driver_override); + pdev->driver_override = NULL; + } ++ device_unlock(dev); + + kfree(old); + +@@ -895,8 +898,12 @@ static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct platform_device *pdev = to_platform_device(dev); ++ ssize_t len; + +- return sprintf(buf, "%s\n", pdev->driver_override); ++ device_lock(dev); ++ len = sprintf(buf, "%s\n", pdev->driver_override); ++ device_unlock(dev); ++ return len; + } + static DEVICE_ATTR_RW(driver_override); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-12153/0.patch b/Patches/Linux_CVEs/CVE-2017-12153/0.patch new file mode 100644 index 00000000..4cc324ad --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-12153/0.patch @@ -0,0 +1,43 @@ +From 082d8a6a55d2b6583d9e93ac9796efdf4c412658 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Wed, 13 Sep 2017 00:21:21 +0200 +Subject: nl80211: check for the required netlink attributes presence + +commit e785fa0a164aa11001cba931367c7f94ffaff888 upstream. + +nl80211_set_rekey_data() does not check if the required attributes +NL80211_REKEY_DATA_{REPLAY_CTR,KEK,KCK} are present when processing +NL80211_CMD_SET_REKEY_OFFLOAD request. This request can be issued by +users with CAP_NET_ADMIN privilege and may result in NULL dereference +and a system crash. Add a check for the required attributes presence. +This patch is based on the patch by bo Zhang. + +This fixes CVE-2017-12153. + +References: https://bugzilla.redhat.com/show_bug.cgi?id=1491046 +Fixes: e5497d766ad ("cfg80211/nl80211: support GTK rekey offload") +Reported-by: bo Zhang +Signed-off-by: Vladis Dronov +Signed-off-by: Johannes Berg +Signed-off-by: Ben Hutchings +--- + net/wireless/nl80211.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 19a3c87..41a0ebb 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5823,6 +5823,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) + if (err) + return err; + ++ if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] || ++ !tb[NL80211_REKEY_DATA_KCK]) ++ return -EINVAL; + if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN) + return -ERANGE; + if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-15265/0.patch b/Patches/Linux_CVEs/CVE-2017-15265/0.patch new file mode 100644 index 00000000..496d1dea --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-15265/0.patch @@ -0,0 +1,142 @@ +From 035e6d0b5b192ff5e168ed322304d29db108d790 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 9 Oct 2017 11:09:20 +0200 +Subject: ALSA: seq: Fix use-after-free at creating a port + +commit 71105998845fb012937332fe2e806d443c09e026 upstream. + +There is a potential race window opened at creating and deleting a +port via ioctl, as spotted by fuzzing. snd_seq_create_port() creates +a port object and returns its pointer, but it doesn't take the +refcount, thus it can be deleted immediately by another thread. +Meanwhile, snd_seq_ioctl_create_port() still calls the function +snd_seq_system_client_ev_port_start() with the created port object +that is being deleted, and this triggers use-after-free like: + + BUG: KASAN: use-after-free in snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] at addr ffff8801f2241cb1 + ============================================================================= + BUG kmalloc-512 (Tainted: G B ): kasan: bad access detected + ----------------------------------------------------------------------------- + INFO: Allocated in snd_seq_create_port+0x94/0x9b0 [snd_seq] age=1 cpu=3 pid=4511 + ___slab_alloc+0x425/0x460 + __slab_alloc+0x20/0x40 + kmem_cache_alloc_trace+0x150/0x190 + snd_seq_create_port+0x94/0x9b0 [snd_seq] + snd_seq_ioctl_create_port+0xd1/0x630 [snd_seq] + snd_seq_do_ioctl+0x11c/0x190 [snd_seq] + snd_seq_ioctl+0x40/0x80 [snd_seq] + do_vfs_ioctl+0x54b/0xda0 + SyS_ioctl+0x79/0x90 + entry_SYSCALL_64_fastpath+0x16/0x75 + INFO: Freed in port_delete+0x136/0x1a0 [snd_seq] age=1 cpu=2 pid=4717 + __slab_free+0x204/0x310 + kfree+0x15f/0x180 + port_delete+0x136/0x1a0 [snd_seq] + snd_seq_delete_port+0x235/0x350 [snd_seq] + snd_seq_ioctl_delete_port+0xc8/0x180 [snd_seq] + snd_seq_do_ioctl+0x11c/0x190 [snd_seq] + snd_seq_ioctl+0x40/0x80 [snd_seq] + do_vfs_ioctl+0x54b/0xda0 + SyS_ioctl+0x79/0x90 + entry_SYSCALL_64_fastpath+0x16/0x75 + Call Trace: + [] dump_stack+0x63/0x82 + [] print_trailer+0xfb/0x160 + [] object_err+0x34/0x40 + [] kasan_report.part.2+0x223/0x520 + [] ? snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] + [] __asan_report_load1_noabort+0x2e/0x30 + [] snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] + [] ? snd_seq_ioctl_delete_port+0x180/0x180 [snd_seq] + [] ? taskstats_exit+0xbc0/0xbc0 + [] snd_seq_do_ioctl+0x11c/0x190 [snd_seq] + [] snd_seq_ioctl+0x40/0x80 [snd_seq] + [] ? acct_account_cputime+0x63/0x80 + [] do_vfs_ioctl+0x54b/0xda0 + ..... + +We may fix this in a few different ways, and in this patch, it's fixed +simply by taking the refcount properly at snd_seq_create_port() and +letting the caller unref the object after use. Also, there is another +potential use-after-free by sprintf() call in snd_seq_create_port(), +and this is moved inside the lock. + +This fix covers CVE-2017-15265. + +Reported-and-tested-by: Michael23 Yu +Suggested-by: Linus Torvalds +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/seq/seq_clientmgr.c | 6 +++++- + sound/core/seq/seq_ports.c | 7 +++++-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index 4a24041..41347ad 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1260,6 +1260,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, + struct snd_seq_client_port *port; + struct snd_seq_port_info info; + struct snd_seq_port_callback *callback; ++ int port_idx; + + if (copy_from_user(&info, arg, sizeof(info))) + return -EFAULT; +@@ -1273,7 +1274,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, + return -ENOMEM; + + if (client->type == USER_CLIENT && info.kernel) { +- snd_seq_delete_port(client, port->addr.port); ++ port_idx = port->addr.port; ++ snd_seq_port_unlock(port); ++ snd_seq_delete_port(client, port_idx); + return -EINVAL; + } + if (client->type == KERNEL_CLIENT) { +@@ -1295,6 +1298,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, + + snd_seq_set_port_info(port, &info); + snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); ++ snd_seq_port_unlock(port); + + if (copy_to_user(arg, &info, sizeof(info))) + return -EFAULT; +diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c +index 9c1c8d5..1ddae91 100644 +--- a/sound/core/seq/seq_ports.c ++++ b/sound/core/seq/seq_ports.c +@@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp) + } + + +-/* create a port, port number is returned (-1 on failure) */ ++/* create a port, port number is returned (-1 on failure); ++ * the caller needs to unref the port via snd_seq_port_unlock() appropriately ++ */ + struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, + int port) + { +@@ -151,6 +153,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, + snd_use_lock_init(&new_port->use_lock); + port_subs_info_init(&new_port->c_src); + port_subs_info_init(&new_port->c_dest); ++ snd_use_lock_use(&new_port->use_lock); + + num = port >= 0 ? port : 0; + mutex_lock(&client->ports_mutex); +@@ -165,9 +168,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, + list_add_tail(&new_port->list, &p->list); + client->num_ports++; + new_port->addr.port = num; /* store the port number in the port */ ++ sprintf(new_port->name, "port-%d", num); + write_unlock_irqrestore(&client->ports_lock, flags); + mutex_unlock(&client->ports_mutex); +- sprintf(new_port->name, "port-%d", num); + + return new_port; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-2618/0.patch b/Patches/Linux_CVEs/CVE-2017-2618/0.patch new file mode 100644 index 00000000..657ed90d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-2618/0.patch @@ -0,0 +1,67 @@ +From a71b4196a72f09ed223d8140de7fd47ccdaf6e2b Mon Sep 17 00:00:00 2001 +From: Stephen Smalley +Date: Tue, 31 Jan 2017 11:54:04 -0500 +Subject: selinux: fix off-by-one in setprocattr + +commit 0c461cb727d146c9ef2d3e86214f498b78b7d125 upstream. + +SELinux tries to support setting/clearing of /proc/pid/attr attributes +from the shell by ignoring terminating newlines and treating an +attribute value that begins with a NUL or newline as an attempt to +clear the attribute. However, the test for clearing attributes has +always been wrong; it has an off-by-one error, and this could further +lead to reading past the end of the allocated buffer since commit +bb646cdb12e75d82258c2f2e7746d5952d3e321a ("proc_pid_attr_write(): +switch to memdup_user()"). Fix the off-by-one error. + +Even with this fix, setting and clearing /proc/pid/attr attributes +from the shell is not straightforward since the interface does not +support multiple write() calls (so shells that write the value and +newline separately will set and then immediately clear the attribute, +requiring use of echo -n to set the attribute), whereas trying to use +echo -n "" to clear the attribute causes the shell to skip the +write() call altogether since POSIX says that a zero-length write +causes no side effects. Thus, one must use echo -n to set and echo +without -n to clear, as in the following example: +$ echo -n unconfined_u:object_r:user_home_t:s0 > /proc/$$/attr/fscreate +$ cat /proc/$$/attr/fscreate +unconfined_u:object_r:user_home_t:s0 +$ echo "" > /proc/$$/attr/fscreate +$ cat /proc/$$/attr/fscreate + +Note the use of /proc/$$ rather than /proc/self, as otherwise +the cat command will read its own attribute value, not that of the shell. + +There are no users of this facility to my knowledge; possibly we +should just get rid of it. + +UPDATE: Upon further investigation it appears that a local process +with the process:setfscreate permission can cause a kernel panic as a +result of this bug. This patch fixes CVE-2017-2618. + +Signed-off-by: Stephen Smalley +[PM: added the update about CVE-2017-2618 to the commit description] +Signed-off-by: Paul Moore +Signed-off-by: Jiri Slaby +Signed-off-by: James Morris +Signed-off-by: Willy Tarreau +--- + security/selinux/hooks.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index fdd6e4f..c08d4a1 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -5442,7 +5442,7 @@ static int selinux_setprocattr(struct task_struct *p, + return error; + + /* Obtain a SID for the context, if one was specified. */ +- if (size && str[1] && str[1] != '\n') { ++ if (size && str[0] && str[0] != '\n') { + if (str[size-1] == '\n') { + str[size-1] = 0; + size--; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-2636/0.patch b/Patches/Linux_CVEs/CVE-2017-2636/0.patch new file mode 100644 index 00000000..92d13d14 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-2636/0.patch @@ -0,0 +1,313 @@ +From 82f2341c94d270421f383641b7cd670e474db56b Mon Sep 17 00:00:00 2001 +From: Alexander Popov +Date: Tue, 28 Feb 2017 19:54:40 +0300 +Subject: tty: n_hdlc: get rid of racy n_hdlc.tbuf + +Currently N_HDLC line discipline uses a self-made singly linked list for +data buffers and has n_hdlc.tbuf pointer for buffer retransmitting after +an error. + +The commit be10eb7589337e5defbe214dae038a53dd21add8 +("tty: n_hdlc add buffer flushing") introduced racy access to n_hdlc.tbuf. +After tx error concurrent flush_tx_queue() and n_hdlc_send_frames() can put +one data buffer to tx_free_buf_list twice. That causes double free in +n_hdlc_release(). + +Let's use standard kernel linked list and get rid of n_hdlc.tbuf: +in case of tx error put current data buffer after the head of tx_buf_list. + +Signed-off-by: Alexander Popov +Cc: stable +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_hdlc.c | 132 +++++++++++++++++++++++++++------------------------ + 1 file changed, 69 insertions(+), 63 deletions(-) + +diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c +index 1bacbc3..e94aea8 100644 +--- a/drivers/tty/n_hdlc.c ++++ b/drivers/tty/n_hdlc.c +@@ -114,7 +114,7 @@ + #define DEFAULT_TX_BUF_COUNT 3 + + struct n_hdlc_buf { +- struct n_hdlc_buf *link; ++ struct list_head list_item; + int count; + char buf[1]; + }; +@@ -122,8 +122,7 @@ struct n_hdlc_buf { + #define N_HDLC_BUF_SIZE (sizeof(struct n_hdlc_buf) + maxframe) + + struct n_hdlc_buf_list { +- struct n_hdlc_buf *head; +- struct n_hdlc_buf *tail; ++ struct list_head list; + int count; + spinlock_t spinlock; + }; +@@ -136,7 +135,6 @@ struct n_hdlc_buf_list { + * @backup_tty - TTY to use if tty gets closed + * @tbusy - reentrancy flag for tx wakeup code + * @woke_up - FIXME: describe this field +- * @tbuf - currently transmitting tx buffer + * @tx_buf_list - list of pending transmit frame buffers + * @rx_buf_list - list of received frame buffers + * @tx_free_buf_list - list unused transmit frame buffers +@@ -149,7 +147,6 @@ struct n_hdlc { + struct tty_struct *backup_tty; + int tbusy; + int woke_up; +- struct n_hdlc_buf *tbuf; + struct n_hdlc_buf_list tx_buf_list; + struct n_hdlc_buf_list rx_buf_list; + struct n_hdlc_buf_list tx_free_buf_list; +@@ -159,6 +156,8 @@ struct n_hdlc { + /* + * HDLC buffer list manipulation functions + */ ++static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list, ++ struct n_hdlc_buf *buf); + static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, + struct n_hdlc_buf *buf); + static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); +@@ -208,16 +207,9 @@ static void flush_tx_queue(struct tty_struct *tty) + { + struct n_hdlc *n_hdlc = tty2n_hdlc(tty); + struct n_hdlc_buf *buf; +- unsigned long flags; + + while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list))) + n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf); +- spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); +- if (n_hdlc->tbuf) { +- n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, n_hdlc->tbuf); +- n_hdlc->tbuf = NULL; +- } +- spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); + } + + static struct tty_ldisc_ops n_hdlc_ldisc = { +@@ -283,7 +275,6 @@ static void n_hdlc_release(struct n_hdlc *n_hdlc) + } else + break; + } +- kfree(n_hdlc->tbuf); + kfree(n_hdlc); + + } /* end of n_hdlc_release() */ +@@ -402,13 +393,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) + n_hdlc->woke_up = 0; + spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); + +- /* get current transmit buffer or get new transmit */ +- /* buffer from list of pending transmit buffers */ +- +- tbuf = n_hdlc->tbuf; +- if (!tbuf) +- tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); +- ++ tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); + while (tbuf) { + if (debuglevel >= DEBUG_LEVEL_INFO) + printk("%s(%d)sending frame %p, count=%d\n", +@@ -420,7 +405,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) + + /* rollback was possible and has been done */ + if (actual == -ERESTARTSYS) { +- n_hdlc->tbuf = tbuf; ++ n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); + break; + } + /* if transmit error, throw frame away by */ +@@ -435,10 +420,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) + + /* free current transmit buffer */ + n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf); +- +- /* this tx buffer is done */ +- n_hdlc->tbuf = NULL; +- ++ + /* wait up sleeping writers */ + wake_up_interruptible(&tty->write_wait); + +@@ -448,10 +430,12 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) + if (debuglevel >= DEBUG_LEVEL_INFO) + printk("%s(%d)frame %p pending\n", + __FILE__,__LINE__,tbuf); +- +- /* buffer not accepted by driver */ +- /* set this buffer as pending buffer */ +- n_hdlc->tbuf = tbuf; ++ ++ /* ++ * the buffer was not accepted by driver, ++ * return it back into tx queue ++ */ ++ n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); + break; + } + } +@@ -749,7 +733,8 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, + int error = 0; + int count; + unsigned long flags; +- ++ struct n_hdlc_buf *buf = NULL; ++ + if (debuglevel >= DEBUG_LEVEL_INFO) + printk("%s(%d)n_hdlc_tty_ioctl() called %d\n", + __FILE__,__LINE__,cmd); +@@ -763,8 +748,10 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, + /* report count of read data available */ + /* in next available frame (if any) */ + spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags); +- if (n_hdlc->rx_buf_list.head) +- count = n_hdlc->rx_buf_list.head->count; ++ buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list, ++ struct n_hdlc_buf, list_item); ++ if (buf) ++ count = buf->count; + else + count = 0; + spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags); +@@ -776,8 +763,10 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, + count = tty_chars_in_buffer(tty); + /* add size of next output frame in queue */ + spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags); +- if (n_hdlc->tx_buf_list.head) +- count += n_hdlc->tx_buf_list.head->count; ++ buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list, ++ struct n_hdlc_buf, list_item); ++ if (buf) ++ count += buf->count; + spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags); + error = put_user(count, (int __user *)arg); + break; +@@ -825,14 +814,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, + poll_wait(filp, &tty->write_wait, wait); + + /* set bits for operations that won't block */ +- if (n_hdlc->rx_buf_list.head) ++ if (!list_empty(&n_hdlc->rx_buf_list.list)) + mask |= POLLIN | POLLRDNORM; /* readable */ + if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) + mask |= POLLHUP; + if (tty_hung_up_p(filp)) + mask |= POLLHUP; + if (!tty_is_writelocked(tty) && +- n_hdlc->tx_free_buf_list.head) ++ !list_empty(&n_hdlc->tx_free_buf_list.list)) + mask |= POLLOUT | POLLWRNORM; /* writable */ + } + return mask; +@@ -856,7 +845,12 @@ static struct n_hdlc *n_hdlc_alloc(void) + spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock); + spin_lock_init(&n_hdlc->rx_buf_list.spinlock); + spin_lock_init(&n_hdlc->tx_buf_list.spinlock); +- ++ ++ INIT_LIST_HEAD(&n_hdlc->rx_free_buf_list.list); ++ INIT_LIST_HEAD(&n_hdlc->tx_free_buf_list.list); ++ INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list); ++ INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list); ++ + /* allocate free rx buffer list */ + for(i=0;ispinlock, flags); ++ ++ list_add(&buf->list_item, &buf_list->list); ++ buf_list->count++; ++ ++ spin_unlock_irqrestore(&buf_list->spinlock, flags); ++} ++ ++/** + * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list +- * @list - pointer to buffer list ++ * @buf_list - pointer to buffer list + * @buf - pointer to buffer + */ +-static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, ++static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list, + struct n_hdlc_buf *buf) + { + unsigned long flags; +- spin_lock_irqsave(&list->spinlock,flags); +- +- buf->link=NULL; +- if (list->tail) +- list->tail->link = buf; +- else +- list->head = buf; +- list->tail = buf; +- (list->count)++; +- +- spin_unlock_irqrestore(&list->spinlock,flags); +- ++ ++ spin_lock_irqsave(&buf_list->spinlock, flags); ++ ++ list_add_tail(&buf->list_item, &buf_list->list); ++ buf_list->count++; ++ ++ spin_unlock_irqrestore(&buf_list->spinlock, flags); + } /* end of n_hdlc_buf_put() */ + + /** + * n_hdlc_buf_get - remove and return an HDLC buffer from list +- * @list - pointer to HDLC buffer list ++ * @buf_list - pointer to HDLC buffer list + * + * Remove and return an HDLC buffer from the head of the specified HDLC buffer + * list. + * Returns a pointer to HDLC buffer if available, otherwise %NULL. + */ +-static struct n_hdlc_buf* n_hdlc_buf_get(struct n_hdlc_buf_list *list) ++static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list) + { + unsigned long flags; + struct n_hdlc_buf *buf; +- spin_lock_irqsave(&list->spinlock,flags); +- +- buf = list->head; ++ ++ spin_lock_irqsave(&buf_list->spinlock, flags); ++ ++ buf = list_first_entry_or_null(&buf_list->list, ++ struct n_hdlc_buf, list_item); + if (buf) { +- list->head = buf->link; +- (list->count)--; ++ list_del(&buf->list_item); ++ buf_list->count--; + } +- if (!list->head) +- list->tail = NULL; +- +- spin_unlock_irqrestore(&list->spinlock,flags); ++ ++ spin_unlock_irqrestore(&buf_list->spinlock, flags); + return buf; +- + } /* end of n_hdlc_buf_get() */ + + static char hdlc_banner[] __initdata = +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-2671/0.patch b/Patches/Linux_CVEs/CVE-2017-2671/0.patch new file mode 100644 index 00000000..ec1a087b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-2671/0.patch @@ -0,0 +1,55 @@ +From 43a6684519ab0a6c52024b5e25322476cabad893 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 24 Mar 2017 19:36:13 -0700 +Subject: ping: implement proper locking + +We got a report of yet another bug in ping + +http://www.openwall.com/lists/oss-security/2017/03/24/6 + +->disconnect() is not called with socket lock held. + +Fix this by acquiring ping rwlock earlier. + +Thanks to Daniel, Alexander and Andrey for letting us know this problem. + +Fixes: c319b4d76b9e ("net: ipv4: add IPPROTO_ICMP socket kind") +Signed-off-by: Eric Dumazet +Reported-by: Daniel Jiang +Reported-by: Solar Designer +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +--- + net/ipv4/ping.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +(limited to 'net/ipv4/ping.c') + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index 2af6244..ccfbce1 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -156,17 +156,18 @@ int ping_hash(struct sock *sk) + void ping_unhash(struct sock *sk) + { + struct inet_sock *isk = inet_sk(sk); ++ + pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); ++ write_lock_bh(&ping_table.lock); + if (sk_hashed(sk)) { +- write_lock_bh(&ping_table.lock); + hlist_nulls_del(&sk->sk_nulls_node); + sk_nulls_node_init(&sk->sk_nulls_node); + sock_put(sk); + isk->inet_num = 0; + isk->inet_sport = 0; + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); +- write_unlock_bh(&ping_table.lock); + } ++ write_unlock_bh(&ping_table.lock); + } + EXPORT_SYMBOL_GPL(ping_unhash); + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5546/0.patch b/Patches/Linux_CVEs/CVE-2017-5546/0.patch new file mode 100644 index 00000000..284c3e9b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5546/0.patch @@ -0,0 +1,64 @@ +From c4e490cf148e85ead0d1b1c2caaba833f1d5b29f Mon Sep 17 00:00:00 2001 +From: John Sperbeck +Date: Tue, 10 Jan 2017 16:58:24 -0800 +Subject: mm/slab.c: fix SLAB freelist randomization duplicate entries + +This patch fixes a bug in the freelist randomization code. When a high +random number is used, the freelist will contain duplicate entries. It +will result in different allocations sharing the same chunk. + +It will result in odd behaviours and crashes. It should be uncommon but +it depends on the machines. We saw it happening more often on some +machines (every few hours of running tests). + +Fixes: c7ce4f60ac19 ("mm: SLAB freelist randomization") +Link: http://lkml.kernel.org/r/20170103181908.143178-1-thgarnie@google.com +Signed-off-by: John Sperbeck +Signed-off-by: Thomas Garnier +Cc: Christoph Lameter +Cc: Pekka Enberg +Cc: David Rientjes +Cc: Joonsoo Kim +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + mm/slab.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/mm/slab.c b/mm/slab.c +index 29bc6c0..4f2ec6b 100644 +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -2457,7 +2457,6 @@ union freelist_init_state { + unsigned int pos; + unsigned int *list; + unsigned int count; +- unsigned int rand; + }; + struct rnd_state rnd_state; + }; +@@ -2483,8 +2482,7 @@ static bool freelist_state_initialize(union freelist_init_state *state, + } else { + state->list = cachep->random_seq; + state->count = count; +- state->pos = 0; +- state->rand = rand; ++ state->pos = rand % count; + ret = true; + } + return ret; +@@ -2493,7 +2491,9 @@ static bool freelist_state_initialize(union freelist_init_state *state, + /* Get the next entry on the list and randomize it using a random shift */ + static freelist_idx_t next_random_slot(union freelist_init_state *state) + { +- return (state->list[state->pos++] + state->rand) % state->count; ++ if (state->pos >= state->count) ++ state->pos = 0; ++ return state->list[state->pos++]; + } + + /* Swap two freelist entries */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5547/0.patch b/Patches/Linux_CVEs/CVE-2017-5547/0.patch new file mode 100644 index 00000000..f4ad8521 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5547/0.patch @@ -0,0 +1,144 @@ +From 6d104af38b570d37aa32a5803b04c354f8ed513d Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 12 Jan 2017 18:17:42 +0100 +Subject: HID: corsair: fix DMA buffers on stack + +Not all platforms support DMA to the stack, and specifically since v4.9 +this is no longer supported on x86 with VMAP_STACK either. + +Note that the macro-mode buffer was larger than necessary. + +Fixes: 6f78193ee9ea ("HID: corsair: Add Corsair Vengeance K90 driver") +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Jiri Kosina +--- + drivers/hid/hid-corsair.c | 54 ++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 42 insertions(+), 12 deletions(-) + +diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c +index 717704e..5971907 100644 +--- a/drivers/hid/hid-corsair.c ++++ b/drivers/hid/hid-corsair.c +@@ -148,7 +148,11 @@ static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev) + struct usb_interface *usbif = to_usb_interface(dev->parent); + struct usb_device *usbdev = interface_to_usbdev(usbif); + int brightness; +- char data[8]; ++ char *data; ++ ++ data = kmalloc(8, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; + + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), + K90_REQUEST_STATUS, +@@ -158,16 +162,22 @@ static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev) + if (ret < 0) { + dev_warn(dev, "Failed to get K90 initial state (error %d).\n", + ret); +- return -EIO; ++ ret = -EIO; ++ goto out; + } + brightness = data[4]; + if (brightness < 0 || brightness > 3) { + dev_warn(dev, + "Read invalid backlight brightness: %02hhx.\n", + data[4]); +- return -EIO; ++ ret = -EIO; ++ goto out; + } +- return brightness; ++ ret = brightness; ++out: ++ kfree(data); ++ ++ return ret; + } + + static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev) +@@ -253,7 +263,11 @@ static ssize_t k90_show_macro_mode(struct device *dev, + struct usb_interface *usbif = to_usb_interface(dev->parent); + struct usb_device *usbdev = interface_to_usbdev(usbif); + const char *macro_mode; +- char data[8]; ++ char *data; ++ ++ data = kmalloc(2, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; + + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), + K90_REQUEST_GET_MODE, +@@ -263,7 +277,8 @@ static ssize_t k90_show_macro_mode(struct device *dev, + if (ret < 0) { + dev_warn(dev, "Failed to get K90 initial mode (error %d).\n", + ret); +- return -EIO; ++ ret = -EIO; ++ goto out; + } + + switch (data[0]) { +@@ -277,10 +292,15 @@ static ssize_t k90_show_macro_mode(struct device *dev, + default: + dev_warn(dev, "K90 in unknown mode: %02hhx.\n", + data[0]); +- return -EIO; ++ ret = -EIO; ++ goto out; + } + +- return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode); ++ ret = snprintf(buf, PAGE_SIZE, "%s\n", macro_mode); ++out: ++ kfree(data); ++ ++ return ret; + } + + static ssize_t k90_store_macro_mode(struct device *dev, +@@ -320,7 +340,11 @@ static ssize_t k90_show_current_profile(struct device *dev, + struct usb_interface *usbif = to_usb_interface(dev->parent); + struct usb_device *usbdev = interface_to_usbdev(usbif); + int current_profile; +- char data[8]; ++ char *data; ++ ++ data = kmalloc(8, GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; + + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), + K90_REQUEST_STATUS, +@@ -330,16 +354,22 @@ static ssize_t k90_show_current_profile(struct device *dev, + if (ret < 0) { + dev_warn(dev, "Failed to get K90 initial state (error %d).\n", + ret); +- return -EIO; ++ ret = -EIO; ++ goto out; + } + current_profile = data[7]; + if (current_profile < 1 || current_profile > 3) { + dev_warn(dev, "Read invalid current profile: %02hhx.\n", + data[7]); +- return -EIO; ++ ret = -EIO; ++ goto out; + } + +- return snprintf(buf, PAGE_SIZE, "%d\n", current_profile); ++ ret = snprintf(buf, PAGE_SIZE, "%d\n", current_profile); ++out: ++ kfree(data); ++ ++ return ret; + } + + static ssize_t k90_store_current_profile(struct device *dev, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5550/0.patch b/Patches/Linux_CVEs/CVE-2017-5550/0.patch new file mode 100644 index 00000000..9ed0c9ba --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5550/0.patch @@ -0,0 +1,108 @@ +From b9dc6f65bc5e232d1c05fe34b5daadc7e8bbf1fb Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sat, 14 Jan 2017 19:33:08 -0500 +Subject: fix a fencepost error in pipe_advance() + +The logics in pipe_advance() used to release all buffers past the new +position failed in cases when the number of buffers to release was equal +to pipe->buffers. If that happened, none of them had been released, +leaving pipe full. Worse, it was trivial to trigger and we end up with +pipe full of uninitialized pages. IOW, it's an infoleak. + +Cc: stable@vger.kernel.org # v4.9 +Reported-by: "Alan J. Wylie" +Tested-by: "Alan J. Wylie" +Signed-off-by: Al Viro +--- + lib/iov_iter.c | 54 +++++++++++++++++++++++++++++++----------------------- + 1 file changed, 31 insertions(+), 23 deletions(-) + +diff --git a/lib/iov_iter.c b/lib/iov_iter.c +index 25f5723..e68604a 100644 +--- a/lib/iov_iter.c ++++ b/lib/iov_iter.c +@@ -730,43 +730,50 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, + } + EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); + ++static inline void pipe_truncate(struct iov_iter *i) ++{ ++ struct pipe_inode_info *pipe = i->pipe; ++ if (pipe->nrbufs) { ++ size_t off = i->iov_offset; ++ int idx = i->idx; ++ int nrbufs = (idx - pipe->curbuf) & (pipe->buffers - 1); ++ if (off) { ++ pipe->bufs[idx].len = off - pipe->bufs[idx].offset; ++ idx = next_idx(idx, pipe); ++ nrbufs++; ++ } ++ while (pipe->nrbufs > nrbufs) { ++ pipe_buf_release(pipe, &pipe->bufs[idx]); ++ idx = next_idx(idx, pipe); ++ pipe->nrbufs--; ++ } ++ } ++} ++ + static void pipe_advance(struct iov_iter *i, size_t size) + { + struct pipe_inode_info *pipe = i->pipe; +- struct pipe_buffer *buf; +- int idx = i->idx; +- size_t off = i->iov_offset, orig_sz; +- + if (unlikely(i->count < size)) + size = i->count; +- orig_sz = size; +- + if (size) { ++ struct pipe_buffer *buf; ++ size_t off = i->iov_offset, left = size; ++ int idx = i->idx; + if (off) /* make it relative to the beginning of buffer */ +- size += off - pipe->bufs[idx].offset; ++ left += off - pipe->bufs[idx].offset; + while (1) { + buf = &pipe->bufs[idx]; +- if (size <= buf->len) ++ if (left <= buf->len) + break; +- size -= buf->len; ++ left -= buf->len; + idx = next_idx(idx, pipe); + } +- buf->len = size; + i->idx = idx; +- off = i->iov_offset = buf->offset + size; +- } +- if (off) +- idx = next_idx(idx, pipe); +- if (pipe->nrbufs) { +- int unused = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1); +- /* [curbuf,unused) is in use. Free [idx,unused) */ +- while (idx != unused) { +- pipe_buf_release(pipe, &pipe->bufs[idx]); +- idx = next_idx(idx, pipe); +- pipe->nrbufs--; +- } ++ i->iov_offset = buf->offset + left; + } +- i->count -= orig_sz; ++ i->count -= size; ++ /* ... and discard everything past that point */ ++ pipe_truncate(i); + } + + void iov_iter_advance(struct iov_iter *i, size_t size) +@@ -826,6 +833,7 @@ void iov_iter_pipe(struct iov_iter *i, int direction, + size_t count) + { + BUG_ON(direction != ITER_PIPE); ++ WARN_ON(pipe->nrbufs == pipe->buffers); + i->type = direction; + i->pipe = pipe; + i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5551/0.patch b/Patches/Linux_CVEs/CVE-2017-5551/0.patch new file mode 100644 index 00000000..9da68329 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5551/0.patch @@ -0,0 +1,45 @@ +From 497de07d89c1410d76a15bec2bb41f24a2a89f31 Mon Sep 17 00:00:00 2001 +From: Gu Zheng +Date: Mon, 9 Jan 2017 09:34:48 +0800 +Subject: tmpfs: clear S_ISGID when setting posix ACLs + +This change was missed the tmpfs modification in In CVE-2016-7097 +commit 073931017b49 ("posix_acl: Clear SGID bit when setting +file permissions") +It can test by xfstest generic/375, which failed to clear +setgid bit in the following test case on tmpfs: + + touch $testfile + chown 100:100 $testfile + chmod 2755 $testfile + _runas -u 100 -g 101 -- setfacl -m u::rwx,g::rwx,o::rwx $testfile + +Signed-off-by: Gu Zheng +Signed-off-by: Al Viro +--- + fs/posix_acl.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/fs/posix_acl.c b/fs/posix_acl.c +index 5955220..c9d48dc 100644 +--- a/fs/posix_acl.c ++++ b/fs/posix_acl.c +@@ -922,11 +922,10 @@ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type) + int error; + + if (type == ACL_TYPE_ACCESS) { +- error = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (error < 0) +- return 0; +- if (error == 0) +- acl = NULL; ++ error = posix_acl_update_mode(inode, ++ &inode->i_mode, &acl); ++ if (error) ++ return error; + } + + inode->i_ctime = current_time(inode); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5669/0.patch b/Patches/Linux_CVEs/CVE-2017-5669/0.patch new file mode 100644 index 00000000..6ee31aef --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5669/0.patch @@ -0,0 +1,70 @@ +From e1d35d4dc7f089e6c9c080d556feedf9c706f0c7 Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Wed, 8 Feb 2017 10:28:24 +1100 +Subject: [PATCH] ipc/shm: Fix shmat mmap nil-page protection + +The issue is described here, with a nice testcase: + + https://bugzilla.kernel.org/show_bug.cgi?id=192931 + +The problem is that shmat() calls do_mmap_pgoff() with MAP_FIXED, and the +address rounded down to 0. For the regular mmap case, the protection +mentioned above is that the kernel gets to generate the address -- +arch_get_unmapped_area() will always check for MAP_FIXED and return that +address. So by the time we do security_mmap_addr(0) things get funky for +shmat(). + +The testcase itself shows that while a regular user crashes, root will not +have a problem attaching a nil-page. There are two possible fixes to +this. The first, and which this patch does, is to simply allow root to +crash as well -- this is also regular mmap behavior, ie when hacking up +the testcase and adding mmap(... |MAP_FIXED). While this approach is the +safer option, the second alternative is to ignore SHM_RND if the rounded +address is 0, thus only having MAP_SHARED flags. This makes the behavior +of shmat() identical to the mmap() case. The downside of this is +obviously user visible, but does make sense in that it maintains semantics +after the round-down wrt 0 address and mmap. + +Passes shm related ltp tests. + +Link: http://lkml.kernel.org/r/1486050195-18629-1-git-send-email-dave@stgolabs.net +Signed-off-by: Davidlohr Bueso +Reported-by: Gareth Evans +Cc: Manfred Spraul +Cc: Michael Kerrisk +Signed-off-by: Andrew Morton +--- + ipc/shm.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/ipc/shm.c b/ipc/shm.c +index d7805acb44fd4..06ea9ef7f54a7 100644 +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -1091,8 +1091,8 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) + * "raddr" thing points to kernel space, and there has to be a wrapper around + * this. + */ +-long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, +- unsigned long shmlba) ++long do_shmat(int shmid, char __user *shmaddr, int shmflg, ++ ulong *raddr, unsigned long shmlba) + { + struct shmid_kernel *shp; + unsigned long addr; +@@ -1113,8 +1113,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, + goto out; + else if ((addr = (ulong)shmaddr)) { + if (addr & (shmlba - 1)) { +- if (shmflg & SHM_RND) +- addr &= ~(shmlba - 1); /* round down */ ++ /* ++ * Round down to the nearest multiple of shmlba. ++ * For sane do_mmap_pgoff() parameters, avoid ++ * round downs that trigger nil-page and MAP_FIXED. ++ */ ++ if ((shmflg & SHM_RND) && addr >= shmlba) ++ addr &= ~(shmlba - 1); + else + #ifndef __ARCH_FORCE_SHMLBA + if (addr & ~PAGE_MASK) diff --git a/Patches/Linux_CVEs/CVE-2017-5669/1.patch b/Patches/Linux_CVEs/CVE-2017-5669/1.patch new file mode 100644 index 00000000..151b9470 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5669/1.patch @@ -0,0 +1,75 @@ +From 95e91b831f87ac8e1f8ed50c14d709089b4e01b8 Mon Sep 17 00:00:00 2001 +From: Davidlohr Bueso +Date: Mon, 27 Feb 2017 14:28:24 -0800 +Subject: ipc/shm: Fix shmat mmap nil-page protection + +The issue is described here, with a nice testcase: + + https://bugzilla.kernel.org/show_bug.cgi?id=192931 + +The problem is that shmat() calls do_mmap_pgoff() with MAP_FIXED, and +the address rounded down to 0. For the regular mmap case, the +protection mentioned above is that the kernel gets to generate the +address -- arch_get_unmapped_area() will always check for MAP_FIXED and +return that address. So by the time we do security_mmap_addr(0) things +get funky for shmat(). + +The testcase itself shows that while a regular user crashes, root will +not have a problem attaching a nil-page. There are two possible fixes +to this. The first, and which this patch does, is to simply allow root +to crash as well -- this is also regular mmap behavior, ie when hacking +up the testcase and adding mmap(... |MAP_FIXED). While this approach +is the safer option, the second alternative is to ignore SHM_RND if the +rounded address is 0, thus only having MAP_SHARED flags. This makes the +behavior of shmat() identical to the mmap() case. The downside of this +is obviously user visible, but does make sense in that it maintains +semantics after the round-down wrt 0 address and mmap. + +Passes shm related ltp tests. + +Link: http://lkml.kernel.org/r/1486050195-18629-1-git-send-email-dave@stgolabs.net +Signed-off-by: Davidlohr Bueso +Reported-by: Gareth Evans +Cc: Manfred Spraul +Cc: Michael Kerrisk +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + ipc/shm.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/ipc/shm.c b/ipc/shm.c +index d7805ac..06ea9ef 100644 +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -1091,8 +1091,8 @@ out_unlock1: + * "raddr" thing points to kernel space, and there has to be a wrapper around + * this. + */ +-long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, +- unsigned long shmlba) ++long do_shmat(int shmid, char __user *shmaddr, int shmflg, ++ ulong *raddr, unsigned long shmlba) + { + struct shmid_kernel *shp; + unsigned long addr; +@@ -1113,8 +1113,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, + goto out; + else if ((addr = (ulong)shmaddr)) { + if (addr & (shmlba - 1)) { +- if (shmflg & SHM_RND) +- addr &= ~(shmlba - 1); /* round down */ ++ /* ++ * Round down to the nearest multiple of shmlba. ++ * For sane do_mmap_pgoff() parameters, avoid ++ * round downs that trigger nil-page and MAP_FIXED. ++ */ ++ if ((shmflg & SHM_RND) && addr >= shmlba) ++ addr &= ~(shmlba - 1); + else + #ifndef __ARCH_FORCE_SHMLBA + if (addr & ~PAGE_MASK) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5897/0.patch b/Patches/Linux_CVEs/CVE-2017-5897/0.patch new file mode 100644 index 00000000..c4d5a3ce --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5897/0.patch @@ -0,0 +1,91 @@ +From 7892032cfe67f4bde6fc2ee967e45a8fbaf33756 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 4 Feb 2017 23:18:55 -0800 +Subject: ip6_gre: fix ip6gre_err() invalid reads + +Andrey Konovalov reported out of bound accesses in ip6gre_err() + +If GRE flags contains GRE_KEY, the following expression +*(((__be32 *)p) + (grehlen / 4) - 1) + +accesses data ~40 bytes after the expected point, since +grehlen includes the size of IPv6 headers. + +Let's use a "struct gre_base_hdr *greh" pointer to make this +code more readable. + +p[1] becomes greh->protocol. +grhlen is the GRE header length. + +Fixes: c12b395a4664 ("gre: Support GRE over IPv6") +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_gre.c | 40 +++++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 19 deletions(-) + +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 5586318..630b73b 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -367,35 +367,37 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) + + + static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, +- u8 type, u8 code, int offset, __be32 info) ++ u8 type, u8 code, int offset, __be32 info) + { +- const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data; +- __be16 *p = (__be16 *)(skb->data + offset); +- int grehlen = offset + 4; ++ const struct gre_base_hdr *greh; ++ const struct ipv6hdr *ipv6h; ++ int grehlen = sizeof(*greh); + struct ip6_tnl *t; ++ int key_off = 0; + __be16 flags; ++ __be32 key; + +- flags = p[0]; +- if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { +- if (flags&(GRE_VERSION|GRE_ROUTING)) +- return; +- if (flags&GRE_KEY) { +- grehlen += 4; +- if (flags&GRE_CSUM) +- grehlen += 4; +- } ++ if (!pskb_may_pull(skb, offset + grehlen)) ++ return; ++ greh = (const struct gre_base_hdr *)(skb->data + offset); ++ flags = greh->flags; ++ if (flags & (GRE_VERSION | GRE_ROUTING)) ++ return; ++ if (flags & GRE_CSUM) ++ grehlen += 4; ++ if (flags & GRE_KEY) { ++ key_off = grehlen + offset; ++ grehlen += 4; + } + +- /* If only 8 bytes returned, keyed message will be dropped here */ +- if (!pskb_may_pull(skb, grehlen)) ++ if (!pskb_may_pull(skb, offset + grehlen)) + return; + ipv6h = (const struct ipv6hdr *)skb->data; +- p = (__be16 *)(skb->data + offset); ++ greh = (const struct gre_base_hdr *)(skb->data + offset); ++ key = key_off ? *(__be32 *)(skb->data + key_off) : 0; + + t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, +- flags & GRE_KEY ? +- *(((__be32 *)p) + (grehlen / 4) - 1) : 0, +- p[1]); ++ key, greh->protocol); + if (!t) + return; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5967/0.patch b/Patches/Linux_CVEs/CVE-2017-5967/0.patch new file mode 100644 index 00000000..b7bd1067 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5967/0.patch @@ -0,0 +1,939 @@ +From dfb4357da6ddbdf57d583ba64361c9d792b0e0b1 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 8 Feb 2017 11:26:59 -0800 +Subject: time: Remove CONFIG_TIMER_STATS + +Currently CONFIG_TIMER_STATS exposes process information across namespaces: + +kernel/time/timer_list.c print_timer(): + + SEQ_printf(m, ", %s/%d", tmp, timer->start_pid); + +/proc/timer_list: + + #11: <0000000000000000>, hrtimer_wakeup, S:01, do_nanosleep, cron/2570 + +Given that the tracer can give the same information, this patch entirely +removes CONFIG_TIMER_STATS. + +Suggested-by: Thomas Gleixner +Signed-off-by: Kees Cook +Acked-by: John Stultz +Cc: Nicolas Pitre +Cc: linux-doc@vger.kernel.org +Cc: Lai Jiangshan +Cc: Shuah Khan +Cc: Xing Gao +Cc: Jonathan Corbet +Cc: Jessica Frazelle +Cc: kernel-hardening@lists.openwall.com +Cc: Nicolas Iooss +Cc: "Paul E. McKenney" +Cc: Petr Mladek +Cc: Richard Cochran +Cc: Tejun Heo +Cc: Michal Marek +Cc: Josh Poimboeuf +Cc: Dmitry Vyukov +Cc: Oleg Nesterov +Cc: "Eric W. Biederman" +Cc: Olof Johansson +Cc: Andrew Morton +Cc: linux-api@vger.kernel.org +Cc: Arjan van de Ven +Link: http://lkml.kernel.org/r/20170208192659.GA32582@beast +Signed-off-by: Thomas Gleixner +--- + Documentation/timers/timer_stats.txt | 73 ------ + include/linux/hrtimer.h | 11 - + include/linux/timer.h | 45 ---- + kernel/kthread.c | 1 - + kernel/time/Makefile | 1 - + kernel/time/hrtimer.c | 38 ---- + kernel/time/timer.c | 48 +--- + kernel/time/timer_list.c | 10 - + kernel/time/timer_stats.c | 425 ----------------------------------- + kernel/workqueue.c | 2 - + lib/Kconfig.debug | 14 -- + 11 files changed, 2 insertions(+), 666 deletions(-) + delete mode 100644 Documentation/timers/timer_stats.txt + delete mode 100644 kernel/time/timer_stats.c + +diff --git a/Documentation/timers/timer_stats.txt b/Documentation/timers/timer_stats.txt +deleted file mode 100644 +index de835ee..0000000 +--- a/Documentation/timers/timer_stats.txt ++++ /dev/null +@@ -1,73 +0,0 @@ +-timer_stats - timer usage statistics +------------------------------------- +- +-timer_stats is a debugging facility to make the timer (ab)usage in a Linux +-system visible to kernel and userspace developers. If enabled in the config +-but not used it has almost zero runtime overhead, and a relatively small +-data structure overhead. Even if collection is enabled runtime all the +-locking is per-CPU and lookup is hashed. +- +-timer_stats should be used by kernel and userspace developers to verify that +-their code does not make unduly use of timers. This helps to avoid unnecessary +-wakeups, which should be avoided to optimize power consumption. +- +-It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration +-section. +- +-timer_stats collects information about the timer events which are fired in a +-Linux system over a sample period: +- +-- the pid of the task(process) which initialized the timer +-- the name of the process which initialized the timer +-- the function where the timer was initialized +-- the callback function which is associated to the timer +-- the number of events (callbacks) +- +-timer_stats adds an entry to /proc: /proc/timer_stats +- +-This entry is used to control the statistics functionality and to read out the +-sampled information. +- +-The timer_stats functionality is inactive on bootup. +- +-To activate a sample period issue: +-# echo 1 >/proc/timer_stats +- +-To stop a sample period issue: +-# echo 0 >/proc/timer_stats +- +-The statistics can be retrieved by: +-# cat /proc/timer_stats +- +-While sampling is enabled, each readout from /proc/timer_stats will see +-newly updated statistics. Once sampling is disabled, the sampled information +-is kept until a new sample period is started. This allows multiple readouts. +- +-Sample output of /proc/timer_stats: +- +-Timerstats sample period: 3.888770 s +- 12, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) +- 15, 1 swapper hcd_submit_urb (rh_timer_func) +- 4, 959 kedac schedule_timeout (process_timeout) +- 1, 0 swapper page_writeback_init (wb_timer_fn) +- 28, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) +- 22, 2948 IRQ 4 tty_flip_buffer_push (delayed_work_timer_fn) +- 3, 3100 bash schedule_timeout (process_timeout) +- 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) +- 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) +- 1, 1 swapper neigh_table_init_no_netlink (neigh_periodic_timer) +- 1, 2292 ip __netdev_watchdog_up (dev_watchdog) +- 1, 23 events/1 do_cache_clean (delayed_work_timer_fn) +-90 total events, 30.0 events/sec +- +-The first column is the number of events, the second column the pid, the third +-column is the name of the process. The forth column shows the function which +-initialized the timer and in parenthesis the callback function which was +-executed on expiry. +- +- Thomas, Ingo +- +-Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable +-timer will appear as follows +- 10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) +- +diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h +index cdab81b..e52b427 100644 +--- a/include/linux/hrtimer.h ++++ b/include/linux/hrtimer.h +@@ -88,12 +88,6 @@ enum hrtimer_restart { + * @base: pointer to the timer base (per cpu and per clock) + * @state: state information (See bit values above) + * @is_rel: Set if the timer was armed relative +- * @start_pid: timer statistics field to store the pid of the task which +- * started the timer +- * @start_site: timer statistics field to store the site where the timer +- * was started +- * @start_comm: timer statistics field to store the name of the process which +- * started the timer + * + * The hrtimer structure must be initialized by hrtimer_init() + */ +@@ -104,11 +98,6 @@ struct hrtimer { + struct hrtimer_clock_base *base; + u8 state; + u8 is_rel; +-#ifdef CONFIG_TIMER_STATS +- int start_pid; +- void *start_site; +- char start_comm[16]; +-#endif + }; + + /** +diff --git a/include/linux/timer.h b/include/linux/timer.h +index 51d601f..5a209b8 100644 +--- a/include/linux/timer.h ++++ b/include/linux/timer.h +@@ -20,11 +20,6 @@ struct timer_list { + unsigned long data; + u32 flags; + +-#ifdef CONFIG_TIMER_STATS +- int start_pid; +- void *start_site; +- char start_comm[16]; +-#endif + #ifdef CONFIG_LOCKDEP + struct lockdep_map lockdep_map; + #endif +@@ -197,46 +192,6 @@ extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); + */ + #define NEXT_TIMER_MAX_DELTA ((1UL << 30) - 1) + +-/* +- * Timer-statistics info: +- */ +-#ifdef CONFIG_TIMER_STATS +- +-extern int timer_stats_active; +- +-extern void init_timer_stats(void); +- +-extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, +- void *timerf, char *comm, u32 flags); +- +-extern void __timer_stats_timer_set_start_info(struct timer_list *timer, +- void *addr); +- +-static inline void timer_stats_timer_set_start_info(struct timer_list *timer) +-{ +- if (likely(!timer_stats_active)) +- return; +- __timer_stats_timer_set_start_info(timer, __builtin_return_address(0)); +-} +- +-static inline void timer_stats_timer_clear_start_info(struct timer_list *timer) +-{ +- timer->start_site = NULL; +-} +-#else +-static inline void init_timer_stats(void) +-{ +-} +- +-static inline void timer_stats_timer_set_start_info(struct timer_list *timer) +-{ +-} +- +-static inline void timer_stats_timer_clear_start_info(struct timer_list *timer) +-{ +-} +-#endif +- + extern void add_timer(struct timer_list *timer); + + extern int try_to_del_timer_sync(struct timer_list *timer); +diff --git a/kernel/kthread.c b/kernel/kthread.c +index 2318fba..8461a43 100644 +--- a/kernel/kthread.c ++++ b/kernel/kthread.c +@@ -850,7 +850,6 @@ void __kthread_queue_delayed_work(struct kthread_worker *worker, + + list_add(&work->node, &worker->delayed_work_list); + work->worker = worker; +- timer_stats_timer_set_start_info(&dwork->timer); + timer->expires = jiffies + delay; + add_timer(timer); + } +diff --git a/kernel/time/Makefile b/kernel/time/Makefile +index 976840d..938dbf3 100644 +--- a/kernel/time/Makefile ++++ b/kernel/time/Makefile +@@ -15,6 +15,5 @@ ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y) + endif + obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o + obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o tick-sched.o +-obj-$(CONFIG_TIMER_STATS) += timer_stats.o + obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o + obj-$(CONFIG_TEST_UDELAY) += test_udelay.o +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index c6ecedd..edabde6 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -766,34 +766,6 @@ void hrtimers_resume(void) + clock_was_set_delayed(); + } + +-static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) +-{ +-#ifdef CONFIG_TIMER_STATS +- if (timer->start_site) +- return; +- timer->start_site = __builtin_return_address(0); +- memcpy(timer->start_comm, current->comm, TASK_COMM_LEN); +- timer->start_pid = current->pid; +-#endif +-} +- +-static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer) +-{ +-#ifdef CONFIG_TIMER_STATS +- timer->start_site = NULL; +-#endif +-} +- +-static inline void timer_stats_account_hrtimer(struct hrtimer *timer) +-{ +-#ifdef CONFIG_TIMER_STATS +- if (likely(!timer_stats_active)) +- return; +- timer_stats_update_stats(timer, timer->start_pid, timer->start_site, +- timer->function, timer->start_comm, 0); +-#endif +-} +- + /* + * Counterpart to lock_hrtimer_base above: + */ +@@ -932,7 +904,6 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool rest + * rare case and less expensive than a smp call. + */ + debug_deactivate(timer); +- timer_stats_hrtimer_clear_start_info(timer); + reprogram = base->cpu_base == this_cpu_ptr(&hrtimer_bases); + + if (!restart) +@@ -990,8 +961,6 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, + /* Switch the timer base, if necessary: */ + new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED); + +- timer_stats_hrtimer_set_start_info(timer); +- + leftmost = enqueue_hrtimer(timer, new_base); + if (!leftmost) + goto unlock; +@@ -1128,12 +1097,6 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id, + base = hrtimer_clockid_to_base(clock_id); + timer->base = &cpu_base->clock_base[base]; + timerqueue_init(&timer->node); +- +-#ifdef CONFIG_TIMER_STATS +- timer->start_site = NULL; +- timer->start_pid = -1; +- memset(timer->start_comm, 0, TASK_COMM_LEN); +-#endif + } + + /** +@@ -1217,7 +1180,6 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base, + raw_write_seqcount_barrier(&cpu_base->seq); + + __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 0); +- timer_stats_account_hrtimer(timer); + fn = timer->function; + + /* +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index ec33a69..82a6bfa 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -571,38 +571,6 @@ internal_add_timer(struct timer_base *base, struct timer_list *timer) + trigger_dyntick_cpu(base, timer); + } + +-#ifdef CONFIG_TIMER_STATS +-void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr) +-{ +- if (timer->start_site) +- return; +- +- timer->start_site = addr; +- memcpy(timer->start_comm, current->comm, TASK_COMM_LEN); +- timer->start_pid = current->pid; +-} +- +-static void timer_stats_account_timer(struct timer_list *timer) +-{ +- void *site; +- +- /* +- * start_site can be concurrently reset by +- * timer_stats_timer_clear_start_info() +- */ +- site = READ_ONCE(timer->start_site); +- if (likely(!site)) +- return; +- +- timer_stats_update_stats(timer, timer->start_pid, site, +- timer->function, timer->start_comm, +- timer->flags); +-} +- +-#else +-static void timer_stats_account_timer(struct timer_list *timer) {} +-#endif +- + #ifdef CONFIG_DEBUG_OBJECTS_TIMERS + + static struct debug_obj_descr timer_debug_descr; +@@ -789,11 +757,6 @@ static void do_init_timer(struct timer_list *timer, unsigned int flags, + { + timer->entry.pprev = NULL; + timer->flags = flags | raw_smp_processor_id(); +-#ifdef CONFIG_TIMER_STATS +- timer->start_site = NULL; +- timer->start_pid = -1; +- memset(timer->start_comm, 0, TASK_COMM_LEN); +-#endif + lockdep_init_map(&timer->lockdep_map, name, key, 0); + } + +@@ -1001,8 +964,6 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only) + base = lock_timer_base(timer, &flags); + } + +- timer_stats_timer_set_start_info(timer); +- + ret = detach_if_pending(timer, base, false); + if (!ret && pending_only) + goto out_unlock; +@@ -1130,7 +1091,6 @@ void add_timer_on(struct timer_list *timer, int cpu) + struct timer_base *new_base, *base; + unsigned long flags; + +- timer_stats_timer_set_start_info(timer); + BUG_ON(timer_pending(timer) || !timer->function); + + new_base = get_timer_cpu_base(timer->flags, cpu); +@@ -1176,7 +1136,6 @@ int del_timer(struct timer_list *timer) + + debug_assert_init(timer); + +- timer_stats_timer_clear_start_info(timer); + if (timer_pending(timer)) { + base = lock_timer_base(timer, &flags); + ret = detach_if_pending(timer, base, true); +@@ -1204,10 +1163,9 @@ int try_to_del_timer_sync(struct timer_list *timer) + + base = lock_timer_base(timer, &flags); + +- if (base->running_timer != timer) { +- timer_stats_timer_clear_start_info(timer); ++ if (base->running_timer != timer) + ret = detach_if_pending(timer, base, true); +- } ++ + spin_unlock_irqrestore(&base->lock, flags); + + return ret; +@@ -1331,7 +1289,6 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head) + unsigned long data; + + timer = hlist_entry(head->first, struct timer_list, entry); +- timer_stats_account_timer(timer); + + base->running_timer = timer; + detach_timer(timer, true); +@@ -1868,7 +1825,6 @@ static void __init init_timer_cpus(void) + void __init init_timers(void) + { + init_timer_cpus(); +- init_timer_stats(); + open_softirq(TIMER_SOFTIRQ, run_timer_softirq); + } + +diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c +index afe6cd1..387a3a5 100644 +--- a/kernel/time/timer_list.c ++++ b/kernel/time/timer_list.c +@@ -62,21 +62,11 @@ static void + print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer, + int idx, u64 now) + { +-#ifdef CONFIG_TIMER_STATS +- char tmp[TASK_COMM_LEN + 1]; +-#endif + SEQ_printf(m, " #%d: ", idx); + print_name_offset(m, taddr); + SEQ_printf(m, ", "); + print_name_offset(m, timer->function); + SEQ_printf(m, ", S:%02x", timer->state); +-#ifdef CONFIG_TIMER_STATS +- SEQ_printf(m, ", "); +- print_name_offset(m, timer->start_site); +- memcpy(tmp, timer->start_comm, TASK_COMM_LEN); +- tmp[TASK_COMM_LEN] = 0; +- SEQ_printf(m, ", %s/%d", tmp, timer->start_pid); +-#endif + SEQ_printf(m, "\n"); + SEQ_printf(m, " # expires at %Lu-%Lu nsecs [in %Ld to %Ld nsecs]\n", + (unsigned long long)ktime_to_ns(hrtimer_get_softexpires(timer)), +diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c +deleted file mode 100644 +index afddded..0000000 +--- a/kernel/time/timer_stats.c ++++ /dev/null +@@ -1,425 +0,0 @@ +-/* +- * kernel/time/timer_stats.c +- * +- * Collect timer usage statistics. +- * +- * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar +- * Copyright(C) 2006 Timesys Corp., Thomas Gleixner +- * +- * timer_stats is based on timer_top, a similar functionality which was part of +- * Con Kolivas dyntick patch set. It was developed by Daniel Petrini at the +- * Instituto Nokia de Tecnologia - INdT - Manaus. timer_top's design was based +- * on dynamic allocation of the statistics entries and linear search based +- * lookup combined with a global lock, rather than the static array, hash +- * and per-CPU locking which is used by timer_stats. It was written for the +- * pre hrtimer kernel code and therefore did not take hrtimers into account. +- * Nevertheless it provided the base for the timer_stats implementation and +- * was a helpful source of inspiration. Kudos to Daniel and the Nokia folks +- * for this effort. +- * +- * timer_top.c is +- * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus +- * Written by Daniel Petrini +- * timer_top.c was released under the GNU General Public License version 2 +- * +- * We export the addresses and counting of timer functions being called, +- * the pid and cmdline from the owner process if applicable. +- * +- * Start/stop data collection: +- * # echo [1|0] >/proc/timer_stats +- * +- * Display the information collected so far: +- * # cat /proc/timer_stats +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-/* +- * This is our basic unit of interest: a timer expiry event identified +- * by the timer, its start/expire functions and the PID of the task that +- * started the timer. We count the number of times an event happens: +- */ +-struct entry { +- /* +- * Hash list: +- */ +- struct entry *next; +- +- /* +- * Hash keys: +- */ +- void *timer; +- void *start_func; +- void *expire_func; +- pid_t pid; +- +- /* +- * Number of timeout events: +- */ +- unsigned long count; +- u32 flags; +- +- /* +- * We save the command-line string to preserve +- * this information past task exit: +- */ +- char comm[TASK_COMM_LEN + 1]; +- +-} ____cacheline_aligned_in_smp; +- +-/* +- * Spinlock protecting the tables - not taken during lookup: +- */ +-static DEFINE_RAW_SPINLOCK(table_lock); +- +-/* +- * Per-CPU lookup locks for fast hash lookup: +- */ +-static DEFINE_PER_CPU(raw_spinlock_t, tstats_lookup_lock); +- +-/* +- * Mutex to serialize state changes with show-stats activities: +- */ +-static DEFINE_MUTEX(show_mutex); +- +-/* +- * Collection status, active/inactive: +- */ +-int __read_mostly timer_stats_active; +- +-/* +- * Beginning/end timestamps of measurement: +- */ +-static ktime_t time_start, time_stop; +- +-/* +- * tstat entry structs only get allocated while collection is +- * active and never freed during that time - this simplifies +- * things quite a bit. +- * +- * They get freed when a new collection period is started. +- */ +-#define MAX_ENTRIES_BITS 10 +-#define MAX_ENTRIES (1UL << MAX_ENTRIES_BITS) +- +-static unsigned long nr_entries; +-static struct entry entries[MAX_ENTRIES]; +- +-static atomic_t overflow_count; +- +-/* +- * The entries are in a hash-table, for fast lookup: +- */ +-#define TSTAT_HASH_BITS (MAX_ENTRIES_BITS - 1) +-#define TSTAT_HASH_SIZE (1UL << TSTAT_HASH_BITS) +-#define TSTAT_HASH_MASK (TSTAT_HASH_SIZE - 1) +- +-#define __tstat_hashfn(entry) \ +- (((unsigned long)(entry)->timer ^ \ +- (unsigned long)(entry)->start_func ^ \ +- (unsigned long)(entry)->expire_func ^ \ +- (unsigned long)(entry)->pid ) & TSTAT_HASH_MASK) +- +-#define tstat_hashentry(entry) (tstat_hash_table + __tstat_hashfn(entry)) +- +-static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly; +- +-static void reset_entries(void) +-{ +- nr_entries = 0; +- memset(entries, 0, sizeof(entries)); +- memset(tstat_hash_table, 0, sizeof(tstat_hash_table)); +- atomic_set(&overflow_count, 0); +-} +- +-static struct entry *alloc_entry(void) +-{ +- if (nr_entries >= MAX_ENTRIES) +- return NULL; +- +- return entries + nr_entries++; +-} +- +-static int match_entries(struct entry *entry1, struct entry *entry2) +-{ +- return entry1->timer == entry2->timer && +- entry1->start_func == entry2->start_func && +- entry1->expire_func == entry2->expire_func && +- entry1->pid == entry2->pid; +-} +- +-/* +- * Look up whether an entry matching this item is present +- * in the hash already. Must be called with irqs off and the +- * lookup lock held: +- */ +-static struct entry *tstat_lookup(struct entry *entry, char *comm) +-{ +- struct entry **head, *curr, *prev; +- +- head = tstat_hashentry(entry); +- curr = *head; +- +- /* +- * The fastpath is when the entry is already hashed, +- * we do this with the lookup lock held, but with the +- * table lock not held: +- */ +- while (curr) { +- if (match_entries(curr, entry)) +- return curr; +- +- curr = curr->next; +- } +- /* +- * Slowpath: allocate, set up and link a new hash entry: +- */ +- prev = NULL; +- curr = *head; +- +- raw_spin_lock(&table_lock); +- /* +- * Make sure we have not raced with another CPU: +- */ +- while (curr) { +- if (match_entries(curr, entry)) +- goto out_unlock; +- +- prev = curr; +- curr = curr->next; +- } +- +- curr = alloc_entry(); +- if (curr) { +- *curr = *entry; +- curr->count = 0; +- curr->next = NULL; +- memcpy(curr->comm, comm, TASK_COMM_LEN); +- +- smp_mb(); /* Ensure that curr is initialized before insert */ +- +- if (prev) +- prev->next = curr; +- else +- *head = curr; +- } +- out_unlock: +- raw_spin_unlock(&table_lock); +- +- return curr; +-} +- +-/** +- * timer_stats_update_stats - Update the statistics for a timer. +- * @timer: pointer to either a timer_list or a hrtimer +- * @pid: the pid of the task which set up the timer +- * @startf: pointer to the function which did the timer setup +- * @timerf: pointer to the timer callback function of the timer +- * @comm: name of the process which set up the timer +- * @tflags: The flags field of the timer +- * +- * When the timer is already registered, then the event counter is +- * incremented. Otherwise the timer is registered in a free slot. +- */ +-void timer_stats_update_stats(void *timer, pid_t pid, void *startf, +- void *timerf, char *comm, u32 tflags) +-{ +- /* +- * It doesn't matter which lock we take: +- */ +- raw_spinlock_t *lock; +- struct entry *entry, input; +- unsigned long flags; +- +- if (likely(!timer_stats_active)) +- return; +- +- lock = &per_cpu(tstats_lookup_lock, raw_smp_processor_id()); +- +- input.timer = timer; +- input.start_func = startf; +- input.expire_func = timerf; +- input.pid = pid; +- input.flags = tflags; +- +- raw_spin_lock_irqsave(lock, flags); +- if (!timer_stats_active) +- goto out_unlock; +- +- entry = tstat_lookup(&input, comm); +- if (likely(entry)) +- entry->count++; +- else +- atomic_inc(&overflow_count); +- +- out_unlock: +- raw_spin_unlock_irqrestore(lock, flags); +-} +- +-static void print_name_offset(struct seq_file *m, unsigned long addr) +-{ +- char symname[KSYM_NAME_LEN]; +- +- if (lookup_symbol_name(addr, symname) < 0) +- seq_printf(m, "<%p>", (void *)addr); +- else +- seq_printf(m, "%s", symname); +-} +- +-static int tstats_show(struct seq_file *m, void *v) +-{ +- struct timespec64 period; +- struct entry *entry; +- unsigned long ms; +- long events = 0; +- ktime_t time; +- int i; +- +- mutex_lock(&show_mutex); +- /* +- * If still active then calculate up to now: +- */ +- if (timer_stats_active) +- time_stop = ktime_get(); +- +- time = ktime_sub(time_stop, time_start); +- +- period = ktime_to_timespec64(time); +- ms = period.tv_nsec / 1000000; +- +- seq_puts(m, "Timer Stats Version: v0.3\n"); +- seq_printf(m, "Sample period: %ld.%03ld s\n", (long)period.tv_sec, ms); +- if (atomic_read(&overflow_count)) +- seq_printf(m, "Overflow: %d entries\n", atomic_read(&overflow_count)); +- seq_printf(m, "Collection: %s\n", timer_stats_active ? "active" : "inactive"); +- +- for (i = 0; i < nr_entries; i++) { +- entry = entries + i; +- if (entry->flags & TIMER_DEFERRABLE) { +- seq_printf(m, "%4luD, %5d %-16s ", +- entry->count, entry->pid, entry->comm); +- } else { +- seq_printf(m, " %4lu, %5d %-16s ", +- entry->count, entry->pid, entry->comm); +- } +- +- print_name_offset(m, (unsigned long)entry->start_func); +- seq_puts(m, " ("); +- print_name_offset(m, (unsigned long)entry->expire_func); +- seq_puts(m, ")\n"); +- +- events += entry->count; +- } +- +- ms += period.tv_sec * 1000; +- if (!ms) +- ms = 1; +- +- if (events && period.tv_sec) +- seq_printf(m, "%ld total events, %ld.%03ld events/sec\n", +- events, events * 1000 / ms, +- (events * 1000000 / ms) % 1000); +- else +- seq_printf(m, "%ld total events\n", events); +- +- mutex_unlock(&show_mutex); +- +- return 0; +-} +- +-/* +- * After a state change, make sure all concurrent lookup/update +- * activities have stopped: +- */ +-static void sync_access(void) +-{ +- unsigned long flags; +- int cpu; +- +- for_each_online_cpu(cpu) { +- raw_spinlock_t *lock = &per_cpu(tstats_lookup_lock, cpu); +- +- raw_spin_lock_irqsave(lock, flags); +- /* nothing */ +- raw_spin_unlock_irqrestore(lock, flags); +- } +-} +- +-static ssize_t tstats_write(struct file *file, const char __user *buf, +- size_t count, loff_t *offs) +-{ +- char ctl[2]; +- +- if (count != 2 || *offs) +- return -EINVAL; +- +- if (copy_from_user(ctl, buf, count)) +- return -EFAULT; +- +- mutex_lock(&show_mutex); +- switch (ctl[0]) { +- case '0': +- if (timer_stats_active) { +- timer_stats_active = 0; +- time_stop = ktime_get(); +- sync_access(); +- } +- break; +- case '1': +- if (!timer_stats_active) { +- reset_entries(); +- time_start = ktime_get(); +- smp_mb(); +- timer_stats_active = 1; +- } +- break; +- default: +- count = -EINVAL; +- } +- mutex_unlock(&show_mutex); +- +- return count; +-} +- +-static int tstats_open(struct inode *inode, struct file *filp) +-{ +- return single_open(filp, tstats_show, NULL); +-} +- +-static const struct file_operations tstats_fops = { +- .open = tstats_open, +- .read = seq_read, +- .write = tstats_write, +- .llseek = seq_lseek, +- .release = single_release, +-}; +- +-void __init init_timer_stats(void) +-{ +- int cpu; +- +- for_each_possible_cpu(cpu) +- raw_spin_lock_init(&per_cpu(tstats_lookup_lock, cpu)); +-} +- +-static int __init init_tstats_procfs(void) +-{ +- struct proc_dir_entry *pe; +- +- pe = proc_create("timer_stats", 0644, NULL, &tstats_fops); +- if (!pe) +- return -ENOMEM; +- return 0; +-} +-__initcall(init_tstats_procfs); +diff --git a/kernel/workqueue.c b/kernel/workqueue.c +index 1d9fb65..072cbc9 100644 +--- a/kernel/workqueue.c ++++ b/kernel/workqueue.c +@@ -1523,8 +1523,6 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq, + return; + } + +- timer_stats_timer_set_start_info(&dwork->timer); +- + dwork->wq = wq; + dwork->cpu = cpu; + timer->expires = jiffies + delay; +diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug +index eb9e9a7..132af33 100644 +--- a/lib/Kconfig.debug ++++ b/lib/Kconfig.debug +@@ -980,20 +980,6 @@ config DEBUG_TIMEKEEPING + + If unsure, say N. + +-config TIMER_STATS +- bool "Collect kernel timers statistics" +- depends on DEBUG_KERNEL && PROC_FS +- help +- If you say Y here, additional code will be inserted into the +- timer routines to collect statistics about kernel timers being +- reprogrammed. The statistics can be read from /proc/timer_stats. +- The statistics collection is started by writing 1 to /proc/timer_stats, +- writing 0 stops it. This feature is useful to collect information +- about timer usage patterns in kernel and userspace. This feature +- is lightweight if enabled in the kernel config but not activated +- (it defaults to deactivated on bootup and will only be activated +- if some application like powertop activates it explicitly). +- + config DEBUG_PREEMPT + bool "Debug preemptible kernel" + depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5970/0.patch b/Patches/Linux_CVEs/CVE-2017-5970/0.patch new file mode 100644 index 00000000..4ba73cae --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5970/0.patch @@ -0,0 +1,47 @@ +From 34b2cef20f19c87999fff3da4071e66937db9644 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 4 Feb 2017 11:16:52 -0800 +Subject: ipv4: keep skb->dst around in presence of IP options + +Andrey Konovalov got crashes in __ip_options_echo() when a NULL skb->dst +is accessed. + +ipv4_pktinfo_prepare() should not drop the dst if (evil) IP options +are present. + +We could refine the test to the presence of ts_needtime or srr, +but IP options are not often used, so let's be conservative. + +Thanks to syzkaller team for finding this bug. + +Fixes: d826eb14ecef ("ipv4: PKTINFO doesnt need dst reference") +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +--- + net/ipv4/ip_sockglue.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index 53ae0c6..9000117 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -1238,7 +1238,14 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb) + pktinfo->ipi_ifindex = 0; + pktinfo->ipi_spec_dst.s_addr = 0; + } +- skb_dst_drop(skb); ++ /* We need to keep the dst for __ip_options_echo() ++ * We could restrict the test to opt.ts_needtime || opt.srr, ++ * but the following is good enough as IP options are not often used. ++ */ ++ if (unlikely(IPCB(skb)->opt.optlen)) ++ skb_dst_force(skb); ++ else ++ skb_dst_drop(skb); + } + + int ip_setsockopt(struct sock *sk, int level, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-5972/0.patch b/Patches/Linux_CVEs/CVE-2017-5972/0.patch new file mode 100644 index 00000000..fc2e7e02 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5972/0.patch @@ -0,0 +1,112 @@ +From e994b2f0fb9229aeff5eea9541320bd7b2ca8714 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 2 Oct 2015 11:43:39 -0700 +Subject: [PATCH] tcp: do not lock listener to process SYN packets + +Everything should now be ready to finally allow SYN +packets processing without holding listener lock. + +Tested: + +3.5 Mpps SYNFLOOD. Plenty of cpu cycles available. + +Next bottleneck is the refcount taken on listener, +that could be avoided if we remove SLAB_DESTROY_BY_RCU +strict semantic for listeners, and use regular RCU. + + 13.18% [kernel] [k] __inet_lookup_listener + 9.61% [kernel] [k] tcp_conn_request + 8.16% [kernel] [k] sha_transform + 5.30% [kernel] [k] inet_reqsk_alloc + 4.22% [kernel] [k] sock_put + 3.74% [kernel] [k] tcp_make_synack + 2.88% [kernel] [k] ipt_do_table + 2.56% [kernel] [k] memcpy_erms + 2.53% [kernel] [k] sock_wfree + 2.40% [kernel] [k] tcp_v4_rcv + 2.08% [kernel] [k] fib_table_lookup + 1.84% [kernel] [k] tcp_openreq_init_rwin + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_ipv4.c | 11 +++++++++-- + net/ipv6/tcp_ipv6.c | 11 +++++++++-- + 2 files changed, 18 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index ac2ea73e9aafc..34310748a3655 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1355,7 +1355,7 @@ static struct sock *tcp_v4_cookie_check(struct sock *sk, struct sk_buff *skb) + } + + /* The socket must have it's spinlock held when we get +- * here. ++ * here, unless it is a TCP_LISTEN socket. + * + * We have a potential double-lock case here, so even when + * doing backlog processing we use the BH locking scheme. +@@ -1619,9 +1619,15 @@ int tcp_v4_rcv(struct sk_buff *skb) + if (sk_filter(sk, skb)) + goto discard_and_relse; + +- sk_incoming_cpu_update(sk); + skb->dev = NULL; + ++ if (sk->sk_state == TCP_LISTEN) { ++ ret = tcp_v4_do_rcv(sk, skb); ++ goto put_and_return; ++ } ++ ++ sk_incoming_cpu_update(sk); ++ + bh_lock_sock_nested(sk); + tcp_sk(sk)->segs_in += max_t(u16, 1, skb_shinfo(skb)->gso_segs); + ret = 0; +@@ -1636,6 +1642,7 @@ int tcp_v4_rcv(struct sk_buff *skb) + } + bh_unlock_sock(sk); + ++put_and_return: + sock_put(sk); + + return ret; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 3d18571811c5e..33334f0c217de 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1161,7 +1161,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * + } + + /* The socket must have it's spinlock held when we get +- * here. ++ * here, unless it is a TCP_LISTEN socket. + * + * We have a potential double-lock case here, so even when + * doing backlog processing we use the BH locking scheme. +@@ -1415,9 +1415,15 @@ static int tcp_v6_rcv(struct sk_buff *skb) + if (sk_filter(sk, skb)) + goto discard_and_relse; + +- sk_incoming_cpu_update(sk); + skb->dev = NULL; + ++ if (sk->sk_state == TCP_LISTEN) { ++ ret = tcp_v6_do_rcv(sk, skb); ++ goto put_and_return; ++ } ++ ++ sk_incoming_cpu_update(sk); ++ + bh_lock_sock_nested(sk); + tcp_sk(sk)->segs_in += max_t(u16, 1, skb_shinfo(skb)->gso_segs); + ret = 0; +@@ -1432,6 +1438,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) + } + bh_unlock_sock(sk); + ++put_and_return: + sock_put(sk); + return ret ? -1 : 0; + diff --git a/Patches/Linux_CVEs/CVE-2017-5986/0.patch b/Patches/Linux_CVEs/CVE-2017-5986/0.patch new file mode 100644 index 00000000..8dfe30ea --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-5986/0.patch @@ -0,0 +1,39 @@ +From 2dcab598484185dea7ec22219c76dcdd59e3cb90 Mon Sep 17 00:00:00 2001 +From: Marcelo Ricardo Leitner +Date: Mon, 6 Feb 2017 18:10:31 -0200 +Subject: sctp: avoid BUG_ON on sctp_wait_for_sndbuf + +Alexander Popov reported that an application may trigger a BUG_ON in +sctp_wait_for_sndbuf if the socket tx buffer is full, a thread is +waiting on it to queue more data and meanwhile another thread peels off +the association being used by the first thread. + +This patch replaces the BUG_ON call with a proper error handling. It +will return -EPIPE to the original sendmsg call, similarly to what would +have been done if the association wasn't found in the first place. + +Acked-by: Alexander Popov +Signed-off-by: Marcelo Ricardo Leitner +Reviewed-by: Xin Long +Signed-off-by: David S. Miller +--- + net/sctp/socket.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 37eeab7..e214d2e 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -7426,7 +7426,8 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, + */ + release_sock(sk); + current_timeo = schedule_timeout(current_timeo); +- BUG_ON(sk != asoc->base.sk); ++ if (sk != asoc->base.sk) ++ goto do_error; + lock_sock(sk); + + *timeo_p = current_timeo; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6001/0.patch b/Patches/Linux_CVEs/CVE-2017-6001/0.patch new file mode 100644 index 00000000..a9442471 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6001/0.patch @@ -0,0 +1,159 @@ +From 9eb0e01be831d0f37ea6278a92c32424141f55fb Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra +Date: Wed, 11 Jan 2017 21:09:50 +0100 +Subject: perf/core: Fix concurrent sys_perf_event_open() vs. 'move_group' race + +commit 321027c1fe77f892f4ea07846aeae08cefbbb290 upstream. + +Di Shen reported a race between two concurrent sys_perf_event_open() +calls where both try and move the same pre-existing software group +into a hardware context. + +The problem is exactly that described in commit: + + f63a8daa5812 ("perf: Fix event->ctx locking") + +... where, while we wait for a ctx->mutex acquisition, the event->ctx +relation can have changed under us. + +That very same commit failed to recognise sys_perf_event_context() as an +external access vector to the events and thereby didn't apply the +established locking rules correctly. + +So while one sys_perf_event_open() call is stuck waiting on +mutex_lock_double(), the other (which owns said locks) moves the group +about. So by the time the former sys_perf_event_open() acquires the +locks, the context we've acquired is stale (and possibly dead). + +Apply the established locking rules as per perf_event_ctx_lock_nested() +to the mutex_lock_double() for the 'move_group' case. This obviously means +we need to validate state after we acquire the locks. + +Reported-by: Di Shen (Keen Lab) +Tested-by: John Dias +Signed-off-by: Peter Zijlstra (Intel) +Cc: Alexander Shishkin +Cc: Arnaldo Carvalho de Melo +Cc: Arnaldo Carvalho de Melo +Cc: Jiri Olsa +Cc: Kees Cook +Cc: Linus Torvalds +Cc: Min Chong +Cc: Peter Zijlstra +Cc: Stephane Eranian +Cc: Thomas Gleixner +Cc: Vince Weaver +Fixes: f63a8daa5812 ("perf: Fix event->ctx locking") +Link: http://lkml.kernel.org/r/20170106131444.GZ3174@twins.programming.kicks-ass.net +Signed-off-by: Ingo Molnar +[bwh: Backported to 3.2: + - Use ACCESS_ONCE() instead of READ_ONCE() + - Test perf_event::group_flags instead of group_caps + - Add the err_locked cleanup block, which we didn't need before + - Adjust context] +Signed-off-by: Ben Hutchings +--- + kernel/events/core.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 57 insertions(+), 4 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index a301c68..49a1db4 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -6474,6 +6474,37 @@ static void mutex_lock_double(struct mutex *a, struct mutex *b) + mutex_lock_nested(b, SINGLE_DEPTH_NESTING); + } + ++/* ++ * Variation on perf_event_ctx_lock_nested(), except we take two context ++ * mutexes. ++ */ ++static struct perf_event_context * ++__perf_event_ctx_lock_double(struct perf_event *group_leader, ++ struct perf_event_context *ctx) ++{ ++ struct perf_event_context *gctx; ++ ++again: ++ rcu_read_lock(); ++ gctx = ACCESS_ONCE(group_leader->ctx); ++ if (!atomic_inc_not_zero(&gctx->refcount)) { ++ rcu_read_unlock(); ++ goto again; ++ } ++ rcu_read_unlock(); ++ ++ mutex_lock_double(&gctx->mutex, &ctx->mutex); ++ ++ if (group_leader->ctx != gctx) { ++ mutex_unlock(&ctx->mutex); ++ mutex_unlock(&gctx->mutex); ++ put_ctx(gctx); ++ goto again; ++ } ++ ++ return gctx; ++} ++ + /** + * sys_perf_event_open - open a performance event, associate it to a task/cpu + * +@@ -6661,14 +6692,31 @@ SYSCALL_DEFINE5(perf_event_open, + } + + if (move_group) { +- gctx = group_leader->ctx; ++ gctx = __perf_event_ctx_lock_double(group_leader, ctx); ++ ++ /* ++ * Check if we raced against another sys_perf_event_open() call ++ * moving the software group underneath us. ++ */ ++ if (!(group_leader->group_flags & PERF_GROUP_SOFTWARE)) { ++ /* ++ * If someone moved the group out from under us, check ++ * if this new event wound up on the same ctx, if so ++ * its the regular !move_group case, otherwise fail. ++ */ ++ if (gctx != ctx) { ++ err = -EINVAL; ++ goto err_locked; ++ } else { ++ perf_event_ctx_unlock(group_leader, gctx); ++ move_group = 0; ++ } ++ } + + /* + * See perf_event_ctx_lock() for comments on the details + * of swizzling perf_event::ctx. + */ +- mutex_lock_double(&gctx->mutex, &ctx->mutex); +- + perf_remove_from_context(group_leader, false); + + /* +@@ -6710,7 +6758,7 @@ SYSCALL_DEFINE5(perf_event_open, + perf_unpin_context(ctx); + + if (move_group) { +- mutex_unlock(&gctx->mutex); ++ perf_event_ctx_unlock(group_leader, gctx); + put_ctx(gctx); + } + mutex_unlock(&ctx->mutex); +@@ -6737,6 +6785,11 @@ SYSCALL_DEFINE5(perf_event_open, + fd_install(event_fd, event_file); + return event_fd; + ++err_locked: ++ if (move_group) ++ perf_event_ctx_unlock(group_leader, gctx); ++ mutex_unlock(&ctx->mutex); ++ fput(event_file); + err_context: + perf_unpin_context(ctx); + put_ctx(ctx); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6074/0.patch b/Patches/Linux_CVEs/CVE-2017-6074/0.patch new file mode 100644 index 00000000..e833c55a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6074/0.patch @@ -0,0 +1,44 @@ +From 5edabca9d4cff7f1f2b68f0bac55ef99d9798ba4 Mon Sep 17 00:00:00 2001 +From: Andrey Konovalov +Date: Thu, 16 Feb 2017 17:22:46 +0100 +Subject: [PATCH] dccp: fix freeing skb too early for IPV6_RECVPKTINFO + +In the current DCCP implementation an skb for a DCCP_PKT_REQUEST packet +is forcibly freed via __kfree_skb in dccp_rcv_state_process if +dccp_v6_conn_request successfully returns. + +However, if IPV6_RECVPKTINFO is set on a socket, the address of the skb +is saved to ireq->pktopts and the ref count for skb is incremented in +dccp_v6_conn_request, so skb is still in use. Nevertheless, it gets freed +in dccp_rcv_state_process. + +Fix by calling consume_skb instead of doing goto discard and therefore +calling __kfree_skb. + +Similar fixes for TCP: + +fb7e2399ec17f1004c0e0ccfd17439f8759ede01 [TCP]: skb is unexpectedly freed. +0aea76d35c9651d55bbaf746e7914e5f9ae5a25d tcp: SYN packets are now +simply consumed + +Signed-off-by: Andrey Konovalov +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/dccp/input.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/dccp/input.c b/net/dccp/input.c +index ba347184bda9b..8fedc2d497709 100644 +--- a/net/dccp/input.c ++++ b/net/dccp/input.c +@@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, + if (inet_csk(sk)->icsk_af_ops->conn_request(sk, + skb) < 0) + return 1; +- goto discard; ++ consume_skb(skb); ++ return 0; + } + if (dh->dccph_type == DCCP_PKT_RESET) + goto discard; diff --git a/Patches/Linux_CVEs/CVE-2017-6074/1.patch b/Patches/Linux_CVEs/CVE-2017-6074/1.patch new file mode 100644 index 00000000..79c6a180 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6074/1.patch @@ -0,0 +1,47 @@ +From 5edabca9d4cff7f1f2b68f0bac55ef99d9798ba4 Mon Sep 17 00:00:00 2001 +From: Andrey Konovalov +Date: Thu, 16 Feb 2017 17:22:46 +0100 +Subject: dccp: fix freeing skb too early for IPV6_RECVPKTINFO + +In the current DCCP implementation an skb for a DCCP_PKT_REQUEST packet +is forcibly freed via __kfree_skb in dccp_rcv_state_process if +dccp_v6_conn_request successfully returns. + +However, if IPV6_RECVPKTINFO is set on a socket, the address of the skb +is saved to ireq->pktopts and the ref count for skb is incremented in +dccp_v6_conn_request, so skb is still in use. Nevertheless, it gets freed +in dccp_rcv_state_process. + +Fix by calling consume_skb instead of doing goto discard and therefore +calling __kfree_skb. + +Similar fixes for TCP: + +fb7e2399ec17f1004c0e0ccfd17439f8759ede01 [TCP]: skb is unexpectedly freed. +0aea76d35c9651d55bbaf746e7914e5f9ae5a25d tcp: SYN packets are now +simply consumed + +Signed-off-by: Andrey Konovalov +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/dccp/input.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/dccp/input.c b/net/dccp/input.c +index ba34718..8fedc2d 100644 +--- a/net/dccp/input.c ++++ b/net/dccp/input.c +@@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, + if (inet_csk(sk)->icsk_af_ops->conn_request(sk, + skb) < 0) + return 1; +- goto discard; ++ consume_skb(skb); ++ return 0; + } + if (dh->dccph_type == DCCP_PKT_RESET) + goto discard; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6214/0.patch b/Patches/Linux_CVEs/CVE-2017-6214/0.patch new file mode 100644 index 00000000..81b25ec3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6214/0.patch @@ -0,0 +1,42 @@ +From ccf7abb93af09ad0868ae9033d1ca8108bdaec82 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 3 Feb 2017 14:59:38 -0800 +Subject: [PATCH] tcp: avoid infinite loop in tcp_splice_read() + +Splicing from TCP socket is vulnerable when a packet with URG flag is +received and stored into receive queue. + +__tcp_splice_read() returns 0, and sk_wait_data() immediately +returns since there is the problematic skb in queue. + +This is a nice way to burn cpu (aka infinite loop) and trigger +soft lockups. + +Again, this gem was found by syzkaller tool. + +Fixes: 9c55e01c0cc8 ("[TCP]: Splice receive support.") +Signed-off-by: Eric Dumazet +Reported-by: Dmitry Vyukov +Cc: Willy Tarreau +Signed-off-by: David S. Miller +--- + net/ipv4/tcp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 4a044964da667..0efb4c7f6704f 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -770,6 +770,12 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, + ret = -EAGAIN; + break; + } ++ /* if __tcp_splice_read() got nothing while we have ++ * an skb in receive queue, we do not want to loop. ++ * This might happen with URG data. ++ */ ++ if (!skb_queue_empty(&sk->sk_receive_queue)) ++ break; + sk_wait_data(sk, &timeo, NULL); + if (signal_pending(current)) { + ret = sock_intr_errno(timeo); diff --git a/Patches/Linux_CVEs/CVE-2017-6214/1.patch b/Patches/Linux_CVEs/CVE-2017-6214/1.patch new file mode 100644 index 00000000..f5a8edac --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6214/1.patch @@ -0,0 +1,45 @@ +From ccf7abb93af09ad0868ae9033d1ca8108bdaec82 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 3 Feb 2017 14:59:38 -0800 +Subject: tcp: avoid infinite loop in tcp_splice_read() + +Splicing from TCP socket is vulnerable when a packet with URG flag is +received and stored into receive queue. + +__tcp_splice_read() returns 0, and sk_wait_data() immediately +returns since there is the problematic skb in queue. + +This is a nice way to burn cpu (aka infinite loop) and trigger +soft lockups. + +Again, this gem was found by syzkaller tool. + +Fixes: 9c55e01c0cc8 ("[TCP]: Splice receive support.") +Signed-off-by: Eric Dumazet +Reported-by: Dmitry Vyukov +Cc: Willy Tarreau +Signed-off-by: David S. Miller +--- + net/ipv4/tcp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 4a04496..0efb4c7 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -770,6 +770,12 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, + ret = -EAGAIN; + break; + } ++ /* if __tcp_splice_read() got nothing while we have ++ * an skb in receive queue, we do not want to loop. ++ * This might happen with URG data. ++ */ ++ if (!skb_queue_empty(&sk->sk_receive_queue)) ++ break; + sk_wait_data(sk, &timeo, NULL); + if (signal_pending(current)) { + ret = sock_intr_errno(timeo); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6345/0.patch b/Patches/Linux_CVEs/CVE-2017-6345/0.patch new file mode 100644 index 00000000..57b5bbc9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6345/0.patch @@ -0,0 +1,58 @@ +From 8b74d439e1697110c5e5c600643e823eb1dd0762 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 12 Feb 2017 14:03:52 -0800 +Subject: net/llc: avoid BUG_ON() in skb_orphan() + +It seems nobody used LLC since linux-3.12. + +Fortunately fuzzers like syzkaller still know how to run this code, +otherwise it would be no fun. + +Setting skb->sk without skb->destructor leads to all kinds of +bugs, we now prefer to be very strict about it. + +Ideally here we would use skb_set_owner() but this helper does not exist yet, +only CAN seems to have a private helper for that. + +Fixes: 376c7311bdb6 ("net: add a temporary sanity check in skb_orphan()") +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +--- + net/llc/llc_conn.c | 3 +++ + net/llc/llc_sap.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c +index 3e821da..8bc5a1b 100644 +--- a/net/llc/llc_conn.c ++++ b/net/llc/llc_conn.c +@@ -821,7 +821,10 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) + * another trick required to cope with how the PROCOM state + * machine works. -acme + */ ++ skb_orphan(skb); ++ sock_hold(sk); + skb->sk = sk; ++ skb->destructor = sock_efree; + } + if (!sock_owned_by_user(sk)) + llc_conn_rcv(sk, skb); +diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c +index d0e1e80..5404d0d 100644 +--- a/net/llc/llc_sap.c ++++ b/net/llc/llc_sap.c +@@ -290,7 +290,10 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, + + ev->type = LLC_SAP_EV_TYPE_PDU; + ev->reason = 0; ++ skb_orphan(skb); ++ sock_hold(sk); + skb->sk = sk; ++ skb->destructor = sock_efree; + llc_sap_state_process(sap, skb); + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6346/0.patch b/Patches/Linux_CVEs/CVE-2017-6346/0.patch new file mode 100644 index 00000000..c92194d5 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6346/0.patch @@ -0,0 +1,126 @@ +From d199fab63c11998a602205f7ee7ff7c05c97164b Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 14 Feb 2017 09:03:51 -0800 +Subject: packet: fix races in fanout_add() + +Multiple threads can call fanout_add() at the same time. + +We need to grab fanout_mutex earlier to avoid races that could +lead to one thread freeing po->rollover that was set by another thread. + +Do the same in fanout_release(), for peace of mind, and to help us +finding lockdep issues earlier. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Fixes: 0648ab70afe6 ("packet: rollover prepare: per-socket state") +Signed-off-by: Eric Dumazet +Cc: Willem de Bruijn +Signed-off-by: David S. Miller +--- + net/packet/af_packet.c | 55 +++++++++++++++++++++++++++----------------------- + 1 file changed, 30 insertions(+), 25 deletions(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index d56ee46..0f03f6a 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1619,6 +1619,7 @@ static void fanout_release_data(struct packet_fanout *f) + + static int fanout_add(struct sock *sk, u16 id, u16 type_flags) + { ++ struct packet_rollover *rollover = NULL; + struct packet_sock *po = pkt_sk(sk); + struct packet_fanout *f, *match; + u8 type = type_flags & 0xff; +@@ -1641,23 +1642,28 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) + return -EINVAL; + } + ++ mutex_lock(&fanout_mutex); ++ ++ err = -EINVAL; + if (!po->running) +- return -EINVAL; ++ goto out; + ++ err = -EALREADY; + if (po->fanout) +- return -EALREADY; ++ goto out; + + if (type == PACKET_FANOUT_ROLLOVER || + (type_flags & PACKET_FANOUT_FLAG_ROLLOVER)) { +- po->rollover = kzalloc(sizeof(*po->rollover), GFP_KERNEL); +- if (!po->rollover) +- return -ENOMEM; +- atomic_long_set(&po->rollover->num, 0); +- atomic_long_set(&po->rollover->num_huge, 0); +- atomic_long_set(&po->rollover->num_failed, 0); ++ err = -ENOMEM; ++ rollover = kzalloc(sizeof(*rollover), GFP_KERNEL); ++ if (!rollover) ++ goto out; ++ atomic_long_set(&rollover->num, 0); ++ atomic_long_set(&rollover->num_huge, 0); ++ atomic_long_set(&rollover->num_failed, 0); ++ po->rollover = rollover; + } + +- mutex_lock(&fanout_mutex); + match = NULL; + list_for_each_entry(f, &fanout_list, list) { + if (f->id == id && +@@ -1704,11 +1710,11 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) + } + } + out: +- mutex_unlock(&fanout_mutex); +- if (err) { +- kfree(po->rollover); ++ if (err && rollover) { ++ kfree(rollover); + po->rollover = NULL; + } ++ mutex_unlock(&fanout_mutex); + return err; + } + +@@ -1717,23 +1723,22 @@ static void fanout_release(struct sock *sk) + struct packet_sock *po = pkt_sk(sk); + struct packet_fanout *f; + +- f = po->fanout; +- if (!f) +- return; +- + mutex_lock(&fanout_mutex); +- po->fanout = NULL; ++ f = po->fanout; ++ if (f) { ++ po->fanout = NULL; ++ ++ if (atomic_dec_and_test(&f->sk_ref)) { ++ list_del(&f->list); ++ dev_remove_pack(&f->prot_hook); ++ fanout_release_data(f); ++ kfree(f); ++ } + +- if (atomic_dec_and_test(&f->sk_ref)) { +- list_del(&f->list); +- dev_remove_pack(&f->prot_hook); +- fanout_release_data(f); +- kfree(f); ++ if (po->rollover) ++ kfree_rcu(po->rollover, rcu); + } + mutex_unlock(&fanout_mutex); +- +- if (po->rollover) +- kfree_rcu(po->rollover, rcu); + } + + static bool packet_extra_vlan_len_allowed(const struct net_device *dev, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6347/0.patch b/Patches/Linux_CVEs/CVE-2017-6347/0.patch new file mode 100644 index 00000000..e0251c6e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6347/0.patch @@ -0,0 +1,48 @@ +From ca4ef4574f1ee5252e2cd365f8f5d5bafd048f32 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Tue, 21 Feb 2017 09:33:18 +0100 +Subject: ip: fix IP_CHECKSUM handling + +The skbs processed by ip_cmsg_recv() are not guaranteed to +be linear e.g. when sending UDP packets over loopback with +MSGMORE. +Using csum_partial() on [potentially] the whole skb len +is dangerous; instead be on the safe side and use skb_checksum(). + +Thanks to syzkaller team to detect the issue and provide the +reproducer. + +v1 -> v2: + - move the variable declaration in a tighter scope + +Fixes: ad6f939ab193 ("ip: Add offset parameter to ip_cmsg_recv") +Reported-by: Andrey Konovalov +Signed-off-by: Paolo Abeni +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/ip_sockglue.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index ce1386a..ebd953b 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -116,10 +116,10 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb, + if (skb->ip_summed != CHECKSUM_COMPLETE) + return; + +- if (offset != 0) +- csum = csum_sub(csum, +- csum_partial(skb_transport_header(skb) + tlen, +- offset, 0)); ++ if (offset != 0) { ++ int tend_off = skb_transport_offset(skb) + tlen; ++ csum = csum_sub(csum, skb_checksum(skb, tend_off, offset, 0)); ++ } + + put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6348/0.patch b/Patches/Linux_CVEs/CVE-2017-6348/0.patch new file mode 100644 index 00000000..edc7e72f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6348/0.patch @@ -0,0 +1,87 @@ +From 4c03b862b12f980456f9de92db6d508a4999b788 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Fri, 17 Feb 2017 16:19:39 -0500 +Subject: irda: Fix lockdep annotations in hashbin_delete(). + +A nested lock depth was added to the hasbin_delete() code but it +doesn't actually work some well and results in tons of lockdep splats. + +Fix the code instead to properly drop the lock around the operation +and just keep peeking the head of the hashbin queue. + +Reported-by: Dmitry Vyukov +Tested-by: Dmitry Vyukov +Signed-off-by: David S. Miller +--- + net/irda/irqueue.c | 34 ++++++++++++++++------------------ + 1 file changed, 16 insertions(+), 18 deletions(-) + +diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c +index acbe61c..160dc89 100644 +--- a/net/irda/irqueue.c ++++ b/net/irda/irqueue.c +@@ -383,9 +383,6 @@ EXPORT_SYMBOL(hashbin_new); + * for deallocating this structure if it's complex. If not the user can + * just supply kfree, which should take care of the job. + */ +-#ifdef CONFIG_LOCKDEP +-static int hashbin_lock_depth = 0; +-#endif + int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) + { + irda_queue_t* queue; +@@ -396,22 +393,27 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) + IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;); + + /* Synchronize */ +- if ( hashbin->hb_type & HB_LOCK ) { +- spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags, +- hashbin_lock_depth++); +- } ++ if (hashbin->hb_type & HB_LOCK) ++ spin_lock_irqsave(&hashbin->hb_spinlock, flags); + + /* + * Free the entries in the hashbin, TODO: use hashbin_clear when + * it has been shown to work + */ + for (i = 0; i < HASHBIN_SIZE; i ++ ) { +- queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); +- while (queue ) { +- if (free_func) +- (*free_func)(queue); +- queue = dequeue_first( +- (irda_queue_t**) &hashbin->hb_queue[i]); ++ while (1) { ++ queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); ++ ++ if (!queue) ++ break; ++ ++ if (free_func) { ++ if (hashbin->hb_type & HB_LOCK) ++ spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); ++ free_func(queue); ++ if (hashbin->hb_type & HB_LOCK) ++ spin_lock_irqsave(&hashbin->hb_spinlock, flags); ++ } + } + } + +@@ -420,12 +422,8 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) + hashbin->magic = ~HB_MAGIC; + + /* Release lock */ +- if ( hashbin->hb_type & HB_LOCK) { ++ if (hashbin->hb_type & HB_LOCK) + spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); +-#ifdef CONFIG_LOCKDEP +- hashbin_lock_depth--; +-#endif +- } + + /* + * Free the hashbin structure +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6353/0.patch b/Patches/Linux_CVEs/CVE-2017-6353/0.patch new file mode 100644 index 00000000..a4a77489 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6353/0.patch @@ -0,0 +1,65 @@ +From dfcb9f4f99f1e9a49e43398a7bfbf56927544af1 Mon Sep 17 00:00:00 2001 +From: Marcelo Ricardo Leitner +Date: Thu, 23 Feb 2017 09:31:18 -0300 +Subject: sctp: deny peeloff operation on asocs with threads sleeping on it + +commit 2dcab5984841 ("sctp: avoid BUG_ON on sctp_wait_for_sndbuf") +attempted to avoid a BUG_ON call when the association being used for a +sendmsg() is blocked waiting for more sndbuf and another thread did a +peeloff operation on such asoc, moving it to another socket. + +As Ben Hutchings noticed, then in such case it would return without +locking back the socket and would cause two unlocks in a row. + +Further analysis also revealed that it could allow a double free if the +application managed to peeloff the asoc that is created during the +sendmsg call, because then sctp_sendmsg() would try to free the asoc +that was created only for that call. + +This patch takes another approach. It will deny the peeloff operation +if there is a thread sleeping on the asoc, so this situation doesn't +exist anymore. This avoids the issues described above and also honors +the syscalls that are already being handled (it can be multiple sendmsg +calls). + +Joint work with Xin Long. + +Fixes: 2dcab5984841 ("sctp: avoid BUG_ON on sctp_wait_for_sndbuf") +Cc: Alexander Popov +Cc: Ben Hutchings +Signed-off-by: Marcelo Ricardo Leitner +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +--- + net/sctp/socket.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index b532148..465a9c8 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -4862,6 +4862,12 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) + if (!asoc) + return -EINVAL; + ++ /* If there is a thread waiting on more sndbuf space for ++ * sending on this asoc, it cannot be peeled. ++ */ ++ if (waitqueue_active(&asoc->wait)) ++ return -EBUSY; ++ + /* An association cannot be branched off from an already peeled-off + * socket, nor is this supported for tcp style sockets. + */ +@@ -7599,8 +7605,6 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, + */ + release_sock(sk); + current_timeo = schedule_timeout(current_timeo); +- if (sk != asoc->base.sk) +- goto do_error; + lock_sock(sk); + + *timeo_p = current_timeo; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6421/0.patch b/Patches/Linux_CVEs/CVE-2017-6421/0.patch new file mode 100644 index 00000000..0b4c4ae4 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6421/0.patch @@ -0,0 +1,2398 @@ +From be42c7ff1f0396484882451fd18f47144c8f1b6b Mon Sep 17 00:00:00 2001 +From: Shantanu Jain +Date: Thu, 16 Feb 2017 11:39:44 +0530 +Subject: input: touchscreen: remove msg21xx mstar touch driver + +Remove msg21xx mstar touch driver from the kernel code +as it has never been used in any of the recent platforms. + +Change-Id: I0ac1f93d9736c402732b6c4a8d22b1bf3500e4c4 +Signed-off-by: Vevek Venkatesan +Signed-off-by: Shantanu Jain +--- + .../bindings/input/touchscreen/msg21xx-ts.txt | 71 - + drivers/input/touchscreen/Kconfig | 11 - + drivers/input/touchscreen/Makefile | 1 - + drivers/input/touchscreen/msg21xx_ts.c | 2260 -------------------- + 4 files changed, 2343 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt + delete mode 100644 drivers/input/touchscreen/msg21xx_ts.c + +diff --git a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt +deleted file mode 100644 +index 7315aef..0000000 +--- a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt ++++ /dev/null +@@ -1,71 +0,0 @@ +-Mstar touch controller +- +-The mstar controller is connected to host processor +-via i2c. The controller generates interrupts when the +-user touches the panel. The host controller is expected +-to read the touch coordinates over i2c and pass the coordinates +-to the rest of the system. +- +-Required properties: +- +- - compatible : should be "mstar,msg21xx". +- - reg : i2c slave address of the device. +- - interrupt-parent : parent of interrupt. +- - interrupts : touch sample interrupt to indicate presense or release +- of fingers on the panel. +- - vdd-supply : Power supply needed to power up the device. +- - vcc_i2c-supply : Power source required to power up i2c bus. +- - mstar,irq-gpio : irq gpio which is to provide interrupts to host, +- same as "interrupts" node. It will also +- contain active low or active high information. +- - mstar,reset-gpio : reset gpio to control the reset of chip. +- - mstar,display-coords : display coords in pixels. It is a four +- tuple consisting of min x, min y, max x and +- max y values. +- - pinctrl-names : This should be defined if a target uses pinctrl framework. +- See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt. +- Specify the names of the configs that pinctrl can install in driver. +- Following are the pinctrl configs that can be installed: +- "pmx_ts_active" : Active configuration of pins, this should specify active +- config defined in pin groups of interrupt and reset gpio. +- "pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep +- config defined in pin groups of interrupt and reset gpio. +- "pmx_ts_release" : Release configuration of pins, this should specify +- release config defined in pin groups of interrupt and reset gpio. +- - mstar,num-max-touches: It defines the maximum number of touch supported by the controller. +- - mstar,hard-reset-delay-ms : hard reset delay in ms +- - mstar,post-hard-reset-delay-ms : post hard reset delay in ms +- +-Optional properties: +- +- - mstar,button-map : button map of key codes. It is a three tuple consisting of key codes. +- - mstar,panel-coords : panel coords for the chip in pixels. +- It is a four tuple consisting of min x, +- min y, max x and max y values. +- - mstar,ic-type : It defines the ic-type of the controller. Values are as folows: +- 1 -> msg2133. +- 2 -> msg21xxA. +- 3 -> msg26xxM. +- +-Example: +- i2c@78b9000 { /* BLSP1 QUP5 */ +- mstar@26 { +- compatible = "mstar,msg21xx"; +- reg = <0x26>; +- interrupt-parent = <&msm_gpio>; +- interrupts = <13 0x2008>; +- mstar,irq-gpio = <&msm_gpio 13 0x00000001>; +- mstar,reset-gpio = <&msm_gpio 12 0x0>; +- vdd-supply = <&pm8916_l17>; +- vcc_i2c-supply = <&pm8916_l6>; +- mstar,display-coords = <0 0 480 854>; +- pinctrl-names = "pmx_ts_active","pmx_ts_suspend"; +- pinctrl-0 = <&ts_int_active &ts_reset_active>; +- pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; +- mstar,button-map = <172 139 158>; +- mstar,ic-type = <2>; +- mstar,num_max_touches = <2>; +- mstar,hard-reset-delay-ms = <100>; +- mstar,post-hard-reset-delay-ms = <100>; +- }; +- }; +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index 49df5e0..9044bb5 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -1128,17 +1128,6 @@ config TOUCHSCREEN_FT5X06_GESTURE + + If unsure, say N. + +-config TOUCHSCREEN_MSTAR21XX +- tristate "Mstar touchscreens" +- depends on I2C +- help +- Say Y here if you have a mstar touchscreen. +- +- If unsure, say N. +- +- To compile this driver as a module, choose M here: the +- module will be called msg21xx_ts. +- + config TOUCHSCREEN_ROHM_BU21023 + tristate "ROHM BU21023/24 Dual touch support resistive touchscreens" + depends on I2C +diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile +index 06953a6..1b6844b 100644 +--- a/drivers/input/touchscreen/Makefile ++++ b/drivers/input/touchscreen/Makefile +@@ -98,5 +98,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o + obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o + obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o + obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o +-obj-$(CONFIG_TOUCHSCREEN_MSTAR21XX) += msg21xx_ts.o + obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/ +diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c +deleted file mode 100644 +index fe8c6e164..0000000 +--- a/drivers/input/touchscreen/msg21xx_ts.c ++++ /dev/null +@@ -1,2260 +0,0 @@ +-/* +- * MStar MSG21XX touchscreen driver +- * +- * Copyright (c) 2006-2012 MStar Semiconductor, Inc. +- * +- * Copyright (C) 2012 Bruce Ding +- * +- * Copyright (c) 2014-2016, The 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 as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#if defined(CONFIG_FB) +-#include +-#include +-#endif +-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR +-#include +-#endif +- +-/* Macro Definition */ +- +-#define TOUCH_DRIVER_DEBUG 0 +-#if (TOUCH_DRIVER_DEBUG == 1) +-#define DBG(fmt, arg...) pr_info(fmt, ##arg) +-#else +-#define DBG(fmt, arg...) +-#endif +- +-/* Constant Value & Variable Definition */ +- +-#define MSTAR_VTG_MIN_UV 2800000 +-#define MSTAR_VTG_MAX_UV 3300000 +-#define MSTAR_I2C_VTG_MIN_UV 1800000 +-#define MSTAR_I2C_VTG_MAX_UV 1800000 +- +-#define MAX_BUTTONS 4 +-#define FT_COORDS_ARR_SIZE 4 +-#define MSTAR_FW_NAME_MAX_LEN 50 +- +-#define MSTAR_CHIPTOP_REGISTER_BANK 0x1E +-#define MSTAR_CHIPTOP_REGISTER_ICTYPE 0xCC +-#define MSTAR_INIT_SW_ID 0x7FF +-#define MSTAR_DEBUG_DIR_NAME "ts_debug" +- +-#define MSG_FW_FILE_MAJOR_VERSION(x) \ +- (((x)->data[0x7f4f] << 8) + ((x)->data[0x7f4e])) +- +-#define MSG_FW_FILE_MINOR_VERSION(x) \ +- (((x)->data[0x7f51] << 8) + ((x)->data[0x7f50])) +- +-/* +- * Note. +- * Please do not change the below setting. +- */ +-#define TPD_WIDTH (2048) +-#define TPD_HEIGHT (2048) +- +-#ifdef FIRMWARE_AUTOUPDATE +-enum { +- SWID_START = 1, +- SWID_TRULY = SWID_START, +- SWID_NULL, +-}; +- +-static unsigned char MSG_FIRMWARE[1][33*1024] = { { +- #include "msg21xx_truly_update_bin.h" +- } +-}; +-#endif +- +-#define CONFIG_TP_HAVE_KEY +-#define PINCTRL_STATE_ACTIVE "pmx_ts_active" +-#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" +-#define PINCTRL_STATE_RELEASE "pmx_ts_release" +- +-#define SLAVE_I2C_ID_DBBUS (0xC4>>1) +- +-#define DEMO_MODE_PACKET_LENGTH (8) +- +-#define TP_PRINT +- +-static char *fw_version; /* customer firmware version */ +-static unsigned short fw_version_major; +-static unsigned short fw_version_minor; +-static unsigned char temp[94][1024]; +-static unsigned int crc32_table[256]; +- +-static unsigned short fw_file_major, fw_file_minor; +-static unsigned short main_sw_id = MSTAR_INIT_SW_ID; +-static unsigned short info_sw_id = MSTAR_INIT_SW_ID; +-static unsigned int bin_conf_crc32; +- +-struct msg21xx_ts_platform_data { +- const char *name; +- char fw_name[MSTAR_FW_NAME_MAX_LEN]; +- u8 fw_version_major; +- u8 fw_version_minor; +- u32 irq_gpio; +- u32 irq_gpio_flags; +- u32 reset_gpio; +- u32 reset_gpio_flags; +- u32 x_max; +- u32 y_max; +- u32 x_min; +- u32 y_min; +- u32 panel_minx; +- u32 panel_miny; +- u32 panel_maxx; +- u32 panel_maxy; +- u32 num_max_touches; +- bool no_force_update; +- bool i2c_pull_up; +- bool ignore_id_check; +- int (*power_init)(bool); +- int (*power_on)(bool); +- int (*power_init)(bool); +- int (*power_on)(bool); +- u8 ic_type; +- u32 button_map[MAX_BUTTONS]; +- u32 num_buttons; +- u32 hard_reset_delay_ms; +- u32 post_hard_reset_delay_ms; +- bool updating_fw; +-}; +- +-/* Touch Data Type Definition */ +-struct touchPoint_t { +- unsigned short x; +- unsigned short y; +-}; +- +-struct touchInfo_t { +- struct touchPoint_t *point; +- unsigned char count; +- unsigned char keycode; +-}; +- +-struct msg21xx_ts_data { +- struct i2c_client *client; +- struct input_dev *input_dev; +- struct msg21xx_ts_platform_data *pdata; +- struct regulator *vdd; +- struct regulator *vcc_i2c; +- bool suspended; +-#if defined(CONFIG_FB) +- struct notifier_block fb_notif; +-#endif +- struct pinctrl *ts_pinctrl; +- struct pinctrl_state *pinctrl_state_active; +- struct pinctrl_state *pinctrl_state_suspend; +- struct pinctrl_state *pinctrl_state_release; +- struct mutex ts_mutex; +- struct touchInfo_t info; +-}; +- +-#if defined(CONFIG_FB) +-static int fb_notifier_callback(struct notifier_block *self, +- unsigned long event, void *data); +-#endif +- +-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR +-static unsigned char bEnableTpProximity; +-static unsigned char bFaceClosingTp; +-#endif +- +-#ifdef TP_PRINT +-static int tp_print_proc_read(struct msg21xx_ts_data *ts_data); +-static void tp_print_create_entry(struct msg21xx_ts_data *ts_data); +-#endif +- +-static void _ReadBinConfig(struct msg21xx_ts_data *ts_data); +-static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data); +- +-static struct mutex msg21xx_mutex; +- +-enum EMEM_TYPE_t { +- EMEM_ALL = 0, +- EMEM_MAIN, +- EMEM_INFO, +-}; +- +-/* Function Definition */ +- +-static unsigned int _CRC_doReflect(unsigned int ref, signed char ch) +-{ +- unsigned int value = 0; +- unsigned int i = 0; +- +- for (i = 1; i < (ch + 1); i++) { +- if (ref & 1) +- value |= 1 << (ch - i); +- ref >>= 1; +- } +- +- return value; +-} +- +-static unsigned int _CRC_getValue(unsigned int text, unsigned int prevCRC) +-{ +- unsigned int ulCRC = prevCRC; +- +- ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text]; +- +- return ulCRC; +-} +- +-static void _CRC_initTable(void) +-{ +- unsigned int magic_number = 0x04c11db7; +- unsigned int i, j; +- +- for (i = 0; i <= 0xFF; i++) { +- crc32_table[i] = _CRC_doReflect(i, 8) << 24; +- for (j = 0; j < 8; j++) +- crc32_table[i] = (crc32_table[i] << 1) ^ +- (crc32_table[i] & (0x80000000L) ? +- magic_number : 0); +- crc32_table[i] = _CRC_doReflect(crc32_table[i], 32); +- } +-} +- +-static void msg21xx_reset_hw(struct msg21xx_ts_platform_data *pdata) +-{ +- gpio_direction_output(pdata->reset_gpio, 1); +- gpio_set_value_cansleep(pdata->reset_gpio, 0); +- /* Note that the RST must be in LOW 10ms at least */ +- usleep(pdata->hard_reset_delay_ms * 1000); +- gpio_set_value_cansleep(pdata->reset_gpio, 1); +- /* Enable the interrupt service thread/routine for INT after 50ms */ +- usleep(pdata->post_hard_reset_delay_ms * 1000); +-} +- +-static int read_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr, +- unsigned char *buf, unsigned short size) +-{ +- int rc = 0; +- struct i2c_msg msgs[] = { +- { +- .addr = addr, +- .flags = I2C_M_RD, /* read flag */ +- .len = size, +- .buf = buf, +- }, +- }; +- +- /* If everything went ok (i.e. 1 msg transmitted), return #bytes +- * transmitted, else error code. +- */ +- if (ts_data->client != NULL) { +- rc = i2c_transfer(ts_data->client->adapter, msgs, 1); +- if (rc < 0) +- dev_err(&ts_data->client->dev, +- "%s error %d\n", __func__, rc); +- } else { +- dev_err(&ts_data->client->dev, "ts_data->client is NULL\n"); +- } +- +- return rc; +-} +- +-static int write_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr, +- unsigned char *buf, unsigned short size) +-{ +- int rc = 0; +- struct i2c_msg msgs[] = { +- { +- .addr = addr, +- /* +- * if read flag is undefined, +- * then it means write flag. +- */ +- .flags = 0, +- .len = size, +- .buf = buf, +- }, +- }; +- +- /* +- * If everything went ok (i.e. 1 msg transmitted), return #bytes +- * transmitted, else error code. +- */ +- if (ts_data->client != NULL) { +- rc = i2c_transfer(ts_data->client->adapter, msgs, 1); +- if (rc < 0) +- dev_err(&ts_data->client->dev, +- "%s error %d\n", __func__, rc); +- } else { +- dev_err(&ts_data->client->dev, "ts_data->client is NULL\n"); +- } +- +- return rc; +-} +- +-static unsigned short read_reg(struct msg21xx_ts_data *ts_data, +- unsigned char bank, unsigned char addr) +-{ +- unsigned char tx_data[3] = {0x10, bank, addr}; +- unsigned char rx_data[2] = {0}; +- +- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data)); +- read_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, rx_data, sizeof(rx_data)); +- +- return rx_data[1] << 8 | rx_data[0]; +-} +- +-static void write_reg(struct msg21xx_ts_data *ts_data, unsigned char bank, +- unsigned char addr, +- unsigned short data) +-{ +- unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8}; +- +- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5); +- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data)); +-} +- +-static void write_reg_8bit(struct msg21xx_ts_data *ts_data, unsigned char bank, +- unsigned char addr, +- unsigned char data) +-{ +- unsigned char tx_data[4] = {0x10, bank, addr, data}; +- +- write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4); +- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data)); +-} +- +-static void dbbusDWIICEnterSerialDebugMode(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char data[5]; +- +- /* Enter the Serial Debug Mode */ +- data[0] = 0x53; +- data[1] = 0x45; +- data[2] = 0x52; +- data[3] = 0x44; +- data[4] = 0x42; +- +- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data)); +-} +- +-static void dbbusDWIICStopMCU(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char data[1]; +- +- /* Stop the MCU */ +- data[0] = 0x37; +- +- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data)); +-} +- +-static void dbbusDWIICIICUseBus(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char data[1]; +- +- /* IIC Use Bus */ +- data[0] = 0x35; +- +- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data)); +-} +- +-static void dbbusDWIICIICReshape(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char data[1]; +- +- /* IIC Re-shape */ +- data[0] = 0x71; +- +- write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data)); +-} +- +-static unsigned char msg21xx_get_ic_type(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char ic_type = 0; +- unsigned char bank; +- unsigned char addr; +- +- msg21xx_reset_hw(ts_data->pdata); +- dbbusDWIICEnterSerialDebugMode(ts_data); +- dbbusDWIICStopMCU(ts_data); +- dbbusDWIICIICUseBus(ts_data); +- dbbusDWIICIICReshape(ts_data); +- msleep(300); +- +- /* stop mcu */ +- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01); +- /* disable watch dog */ +- write_reg(ts_data, 0x3C, 0x60, 0xAA55); +- /* get ic type */ +- bank = MSTAR_CHIPTOP_REGISTER_BANK; +- addr = MSTAR_CHIPTOP_REGISTER_ICTYPE; +- ic_type = (0xff)&(read_reg(ts_data, bank, addr)); +- +- if (ic_type != ts_data->pdata->ic_type) +- ic_type = 0; +- +- msg21xx_reset_hw(ts_data->pdata); +- +- return ic_type; +-} +- +-static int msg21xx_read_firmware_id(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char command[3] = { 0x53, 0x00, 0x2A}; +- unsigned char response[4] = { 0 }; +- +- mutex_lock(&msg21xx_mutex); +- write_i2c_seq(ts_data, ts_data->client->addr, command, sizeof(command)); +- read_i2c_seq(ts_data, ts_data->client->addr, response, +- sizeof(response)); +- mutex_unlock(&msg21xx_mutex); +- ts_data->pdata->fw_version_major = (response[1]<<8) + response[0]; +- ts_data->pdata->fw_version_minor = (response[3]<<8) + response[2]; +- +- dev_info(&ts_data->client->dev, "major num = %d, minor num = %d\n", +- ts_data->pdata->fw_version_major, +- ts_data->pdata->fw_version_minor); +- +- return 0; +-} +- +-static int firmware_erase_c33(struct msg21xx_ts_data *ts_data, +- enum EMEM_TYPE_t emem_type) +-{ +- /* stop mcu */ +- write_reg(ts_data, 0x0F, 0xE6, 0x0001); +- +- /* disable watch dog */ +- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55); +- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA); +- +- /* set PROGRAM password */ +- write_reg_8bit(ts_data, 0x16, 0x1A, 0xBA); +- write_reg_8bit(ts_data, 0x16, 0x1B, 0xAB); +- +- write_reg_8bit(ts_data, 0x16, 0x18, 0x80); +- +- if (emem_type == EMEM_ALL) +- write_reg_8bit(ts_data, 0x16, 0x08, 0x10); +- +- write_reg_8bit(ts_data, 0x16, 0x18, 0x40); +- msleep(20); +- +- /* clear pce */ +- write_reg_8bit(0x16, 0x18, 0x80); +- +- /* erase trigger */ +- if (emem_type == EMEM_MAIN) +- write_reg_8bit(ts_data, 0x16, 0x0E, 0x04); /* erase main */ +- else +- write_reg_8bit(0x16, 0x0E, 0x08); /* erase all block */ +- +- return 1; +-} +- +-static void _ReadBinConfig(void); +-static unsigned int _CalMainCRC32(void); +- +-static int check_fw_update(void) +-{ +- int ret = 0; +- +- msg21xx_read_firmware_id(); +- _ReadBinConfig(); +- if (main_sw_id == info_sw_id) { +- if (_CalMainCRC32() == bin_conf_crc32) { +- /*check upgrading*/ +- if ((update_bin_major == pdata->fw_version_major) && +- (update_bin_minor > pdata->fw_version_minor)) { +- ret = 1; +- } +- } +- } +- return ret; +- write_reg_8bit(ts_data, 0x16, 0x0E, 0x08); /* erase all block */ +- +- return 0; +-} +- +-static ssize_t firmware_update_c33(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t size, +- enum EMEM_TYPE_t emem_type, +- bool isForce) { +- unsigned int i, j; +- unsigned int crc_main, crc_main_tp; +- unsigned int crc_info, crc_info_tp; +- unsigned short reg_data = 0; +- int update_pass = 1; +- bool fw_upgrade = false; +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- crc_main = 0xffffffff; +- crc_info = 0xffffffff; +- +- msg21xx_reset_hw(ts_data->pdata); +- +- msg21xx_read_firmware_id(ts_data); +- _ReadBinConfig(ts_data); +- if ((main_sw_id == info_sw_id) && +- (_CalMainCRC32(ts_data) == bin_conf_crc32) && +- (fw_file_major == ts_data->pdata->fw_version_major) && +- (fw_file_minor > ts_data->pdata->fw_version_minor)) { +- fw_upgrade = true; +- } +- +- if (!fw_upgrade && !isForce) { +- dev_dbg(dev, "no need to update\n"); +- msg21xx_reset_hw(ts_data->pdata); +- return size; +- } +- msg21xx_reset_hw(ts_data->pdata); +- msleep(300); +- +- dbbusDWIICEnterSerialDebugMode(ts_data); +- dbbusDWIICStopMCU(ts_data); +- dbbusDWIICIICUseBus(ts_data); +- dbbusDWIICIICReshape(ts_data); +- msleep(300); +- +- /* erase main */ +- firmware_erase_c33(ts_data, EMEM_MAIN); +- msleep(1000); +- +- msg21xx_reset_hw(ts_data->pdata); +- dbbusDWIICEnterSerialDebugMode(ts_data); +- dbbusDWIICStopMCU(ts_data); +- dbbusDWIICIICUseBus(ts_data); +- dbbusDWIICIICReshape(ts_data); +- msleep(300); +- /* +- * Program +- */ +- /* polling 0x3CE4 is 0x1C70 */ +- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { +- do { +- reg_data = read_reg(ts_data, 0x3C, 0xE4); +- } while (reg_data != 0x1C70); +- } +- +- switch (emem_type) { +- case EMEM_ALL: +- write_reg(ts_data, 0x3C, 0xE4, 0xE38F); /* for all-blocks */ +- break; +- case EMEM_MAIN: +- write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for main block */ +- break; +- case EMEM_INFO: +- write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for info block */ +- +- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01); +- +- write_reg_8bit(ts_data, 0x3C, 0xE4, 0xC5); +- write_reg_8bit(ts_data, 0x3C, 0xE5, 0x78); +- +- write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, +- 0x04, 0x9F); +- write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, +- 0x05, 0x82); +- +- write_reg_8bit(ts_data, 0x0F, 0xE6, 0x00); +- msleep(100); +- break; +- } +- +- /* polling 0x3CE4 is 0x2F43 */ +- do { +- reg_data = read_reg(ts_data, 0x3C, 0xE4); +- } while (reg_data != 0x2F43); +- +- /* calculate CRC 32 */ +- _CRC_initTable(); +- +- /* total 32 KB : 2 byte per R/W */ +- for (i = 0; i < 32; i++) { +- if (i == 31) { +- fw_bin_data[i][1014] = 0x5A; +- fw_bin_data[i][1015] = 0xA5; +- +- for (j = 0; j < 1016; j++) +- crc_main = _CRC_getValue(fw_bin_data[i][j], +- crc_main); +- } else { +- for (j = 0; j < 1024; j++) +- crc_main = _CRC_getValue(fw_bin_data[i][j], +- crc_main); +- } +- +- for (j = 0; j < 8; j++) +- write_i2c_seq(ts_data, ts_data->client->addr, +- &fw_bin_data[i][j * 128], 128); +- msleep(100); +- +- /* polling 0x3CE4 is 0xD0BC */ +- do { +- reg_data = read_reg(ts_data, 0x3C, 0xE4); +- } while (reg_data != 0xD0BC); +- +- write_reg(ts_data, 0x3C, 0xE4, 0x2F43); +- } +- +- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { +- /* write file done and check crc */ +- write_reg(ts_data, 0x3C, 0xE4, 0x1380); +- } +- msleep(20); +- +- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { +- /* polling 0x3CE4 is 0x9432 */ +- do { +- reg_data = read_reg(ts_data, 0x3C, 0xE4); +- } while (reg_data != 0x9432); +- } +- +- crc_main = crc_main ^ 0xffffffff; +- crc_info = crc_info ^ 0xffffffff; +- +- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { +- /* CRC Main from TP */ +- crc_main_tp = read_reg(ts_data, 0x3C, 0x80); +- crc_main_tp = (crc_main_tp << 16) | +- read_reg(ts_data, 0x3C, 0x82); +- +- /* CRC Info from TP */ +- crc_info_tp = read_reg(ts_data, 0x3C, 0xA0); +- crc_info_tp = (crc_info_tp << 16) | +- read_reg(ts_data, 0x3C, 0xA2); +- } +- +- update_pass = 1; +- if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { +- if (crc_main_tp != crc_main) +- update_pass = 0; +- } +- +- if (!update_pass) { +- dev_err(dev, "update_C33 failed\n"); +- msg21xx_reset_hw(ts_data->pdata); +- return 0; +- } +- +- dev_dbg(dev, "update_C33 OK\n"); +- msg21xx_reset_hw(ts_data->pdata); +- return size; +-} +- +-static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data) +-{ +- unsigned int ret = 0; +- unsigned short reg_data = 0; +- +- msg21xx_reset_hw(ts_data->pdata); +- +- dbbusDWIICEnterSerialDebugMode(ts_data); +- dbbusDWIICStopMCU(ts_data); +- dbbusDWIICIICUseBus(ts_data); +- dbbusDWIICIICReshape(ts_data); +- msleep(100); +- +- /* Stop MCU */ +- write_reg(ts_data, 0x0F, 0xE6, 0x0001); +- +- /* Stop Watchdog */ +- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55); +- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA); +- +- /* cmd */ +- write_reg(ts_data, 0x3C, 0xE4, 0xDF4C); +- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60); +- /* TP SW reset */ +- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F); +- +- /* MCU run */ +- write_reg(ts_data, 0x0F, 0xE6, 0x0000); +- +- /* polling 0x3CE4 */ +- do { +- reg_data = read_reg(ts_data, 0x3C, 0xE4); +- } while (reg_data != 0x9432); +- +- /* Cal CRC Main from TP */ +- ret = read_reg(ts_data, 0x3C, 0x80); +- ret = (ret << 16) | read_reg(ts_data, 0x3C, 0x82); +- +- dev_dbg(&ts_data->client->dev, +- "[21xxA]:Current main crc32=0x%x\n", ret); +- return ret; +-} +- +-static void _ReadBinConfig(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char dbbus_tx_data[5] = {0}; +- unsigned char dbbus_rx_data[4] = {0}; +- unsigned short reg_data = 0; +- +- msg21xx_reset_hw(ts_data->pdata); +- +- dbbusDWIICEnterSerialDebugMode(ts_data); +- dbbusDWIICStopMCU(ts_data); +- dbbusDWIICIICUseBus(ts_data); +- dbbusDWIICIICReshape(ts_data); +- msleep(100); +- +- /* Stop MCU */ +- write_reg(ts_data, 0x0F, 0xE6, 0x0001); +- +- /* Stop Watchdog */ +- write_reg_8bit(ts_data, 0x3C, 0x60, 0x55); +- write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA); +- +- /* cmd */ +- write_reg(ts_data, 0x3C, 0xE4, 0xA4AB); +- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60); +- +- /* TP SW reset */ +- write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F); +- +- /* MCU run */ +- write_reg(ts_data, 0x0F, 0xE6, 0x0000); +- +- /* polling 0x3CE4 */ +- do { +- reg_data = read_reg(ts_data, 0x3C, 0xE4); +- } while (reg_data != 0x5B58); +- +- dbbus_tx_data[0] = 0x72; +- dbbus_tx_data[1] = 0x7F; +- dbbus_tx_data[2] = 0x55; +- dbbus_tx_data[3] = 0x00; +- dbbus_tx_data[4] = 0x04; +- write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5); +- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4); +- if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39) +- && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39) +- && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) { +- main_sw_id = (dbbus_rx_data[0] - 0x30) * 100 + +- (dbbus_rx_data[1] - 0x30) * 10 + +- (dbbus_rx_data[2] - 0x30); +- } +- +- dbbus_tx_data[0] = 0x72; +- dbbus_tx_data[1] = 0x7F; +- dbbus_tx_data[2] = 0xFC; +- dbbus_tx_data[3] = 0x00; +- dbbus_tx_data[4] = 0x04; +- write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5); +- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4); +- bin_conf_crc32 = (dbbus_rx_data[0] << 24) | +- (dbbus_rx_data[1] << 16) | +- (dbbus_rx_data[2] << 8) | +- (dbbus_rx_data[3]); +- +- dbbus_tx_data[0] = 0x72; +- dbbus_tx_data[1] = 0x83; +- dbbus_tx_data[2] = 0x00; +- dbbus_tx_data[3] = 0x00; +- dbbus_tx_data[4] = 0x04; +- write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5); +- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4); +- if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39) +- && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39) +- && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) { +- info_sw_id = (dbbus_rx_data[0] - 0x30) * 100 + +- (dbbus_rx_data[1] - 0x30) * 10 + +- (dbbus_rx_data[2] - 0x30); +- } +- +- dev_dbg(&ts_data->client->dev, +- "[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32 = 0x%x\n", +- main_sw_id, info_sw_id, bin_conf_crc32); +-} +- +-static ssize_t firmware_update_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- return snprintf(buf, 3, "%d\n", ts_data->pdata->updating_fw); +-} +- +-static ssize_t firmware_update_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, +- size_t size) +-{ +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- ts_data->pdata->updating_fw = true; +- disable_irq(ts_data->client->irq); +- +- size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false); +- +- enable_irq(ts_data->client->irq); +- ts_data->pdata->updating_fw = false; +- +- return size; +-} +- +-static DEVICE_ATTR(update, (S_IRUGO | S_IWUSR), +- firmware_update_show, +- firmware_update_store); +- +-static int prepare_fw_data(struct device *dev) +-{ +- int count; +- int i; +- int ret; +- const struct firmware *fw = NULL; +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- ret = request_firmware(&fw, ts_data->pdata->fw_name, dev); +- if (ret < 0) { +- dev_err(dev, "Request firmware failed - %s (%d)\n", +- ts_data->pdata->fw_name, ret); +- return ret; +- } +- +- count = fw->size / 1024; +- +- for (i = 0; i < count; i++) +- memcpy(fw_bin_data[i], fw->data + (i * 1024), 1024); +- +- fw_file_major = MSG_FW_FILE_MAJOR_VERSION(fw); +- fw_file_minor = MSG_FW_FILE_MINOR_VERSION(fw); +- dev_dbg(dev, "New firmware: %d.%d", +- fw_file_major, fw_file_minor); +- +- return fw->size; +-} +- +-static ssize_t firmware_update_smart_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, +- size_t size) +-{ +- int ret; +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- ret = prepare_fw_data(dev); +- if (ret < 0) { +- dev_err(dev, "Request firmware failed -(%d)\n", ret); +- return ret; +- } +- ts_data->pdata->updating_fw = true; +- disable_irq(ts_data->client->irq); +- +- ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false); +- if (ret == 0) +- dev_err(dev, "firmware_update_c33 ret = %d\n", ret); +- +- enable_irq(ts_data->client->irq); +- ts_data->pdata->updating_fw = false; +- +- return ret; +-} +- +-static ssize_t firmware_force_update_smart_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, +- size_t size) +-{ +- int ret; +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- ret = prepare_fw_data(dev); +- if (ret < 0) { +- dev_err(dev, "Request firmware failed -(%d)\n", ret); +- return ret; +- } +- ts_data->pdata->updating_fw = true; +- disable_irq(ts_data->client->irq); +- +- ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, true); +- if (ret == 0) +- dev_err(dev, "firmware_update_c33 et = %d\n", ret); +- +- enable_irq(ts_data->client->irq); +- ts_data->pdata->updating_fw = false; +- +- return ret; +-} +- +-static DEVICE_ATTR(update_fw, (S_IRUGO | S_IWUSR), +- firmware_update_show, +- firmware_update_smart_store); +- +-static DEVICE_ATTR(force_update_fw, (S_IRUGO | S_IWUSR), +- firmware_update_show, +- firmware_force_update_smart_store); +- +-static ssize_t firmware_version_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- msg21xx_read_firmware_id(ts_data); +- return snprintf(buf, sizeof(char) * 8, "%03d%03d\n", +- ts_data->pdata->fw_version_major, +- ts_data->pdata->fw_version_minor); +-} +- +-static DEVICE_ATTR(version, S_IRUGO, +- firmware_version_show, +- NULL); +- +- +-static ssize_t msg21xx_fw_name_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1, +- "%s\n", ts_data->pdata->fw_name); +-} +- +-static ssize_t msg21xx_fw_name_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t size) +-{ +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- if (size > MSTAR_FW_NAME_MAX_LEN - 1) +- return -EINVAL; +- +- strlcpy(ts_data->pdata->fw_name, buf, size); +- if (ts_data->pdata->fw_name[size - 1] == '\n') +- ts_data->pdata->fw_name[size - 1] = 0; +- +- return size; +-} +- +-static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR), +- msg21xx_fw_name_show, msg21xx_fw_name_store); +- +-static ssize_t firmware_data_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, +- size_t size) +-{ +- int count = size / 1024; +- int i; +- +- for (i = 0; i < count; i++) +- memcpy(fw_bin_data[i], buf + (i * 1024), 1024); +- +- if (buf != NULL) +- dev_dbg(dev, "buf[0] = %c\n", buf[0]); +- +- return size; +-} +- +-static DEVICE_ATTR(data, S_IWUSR, NULL, firmware_data_store); +- +-static ssize_t tp_print_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- tp_print_proc_read(ts_data); +- +- return snprintf(buf, 3, "%d\n", ts_data->suspended); +-} +- +-static ssize_t tp_print_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, +- size_t size) +-{ +- return size; +-} +- +-static DEVICE_ATTR(tpp, (S_IRUGO | S_IWUSR), +- tp_print_show, tp_print_store); +- +-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR +-static void _msg_enable_proximity(void) +-{ +- unsigned char tx_data[4] = {0}; +- +- tx_data[0] = 0x52; +- tx_data[1] = 0x00; +- tx_data[2] = 0x47; +- tx_data[3] = 0xa0; +- mutex_lock(&msg21xx_mutex); +- write_i2c_seq(ts_data->client->addr, &tx_data[0], 4); +- mutex_unlock(&msg21xx_mutex); +- +- bEnableTpProximity = 1; +-} +- +-static void _msg_disable_proximity(void) +-{ +- unsigned char tx_data[4] = {0}; +- +- tx_data[0] = 0x52; +- tx_data[1] = 0x00; +- tx_data[2] = 0x47; +- tx_data[3] = 0xa1; +- mutex_lock(&msg21xx_mutex); +- write_i2c_seq(ts_data->client->addr, &tx_data[0], 4); +- mutex_unlock(&msg21xx_mutex); +- +- bEnableTpProximity = 0; +- bFaceClosingTp = 0; +-} +- +-static void tsps_msg21xx_enable(int en) +-{ +- if (en) +- _msg_enable_proximity(); +- else +- _msg_disable_proximity(); +-} +- +-static int tsps_msg21xx_data(void) +-{ +- return bFaceClosingTp; +-} +-#endif +- +-static int msg21xx_pinctrl_init(struct msg21xx_ts_data *ts_data) +-{ +- int retval; +- +- /* Get pinctrl if target uses pinctrl */ +- ts_data->ts_pinctrl = devm_pinctrl_get(&(ts_data->client->dev)); +- if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) { +- retval = PTR_ERR(ts_data->ts_pinctrl); +- dev_dbg(&ts_data->client->dev, +- "Target does not use pinctrl %d\n", retval); +- goto err_pinctrl_get; +- } +- +- ts_data->pinctrl_state_active = pinctrl_lookup_state( +- ts_data->ts_pinctrl, PINCTRL_STATE_ACTIVE); +- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_active)) { +- retval = PTR_ERR(ts_data->pinctrl_state_active); +- dev_dbg(&ts_data->client->dev, +- "Can't lookup %s pinstate %d\n", +- PINCTRL_STATE_ACTIVE, retval); +- goto err_pinctrl_lookup; +- } +- +- ts_data->pinctrl_state_suspend = pinctrl_lookup_state( +- ts_data->ts_pinctrl, PINCTRL_STATE_SUSPEND); +- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_suspend)) { +- retval = PTR_ERR(ts_data->pinctrl_state_suspend); +- dev_dbg(&ts_data->client->dev, +- "Can't lookup %s pinstate %d\n", +- PINCTRL_STATE_SUSPEND, retval); +- goto err_pinctrl_lookup; +- } +- +- ts_data->pinctrl_state_release = pinctrl_lookup_state( +- ts_data->ts_pinctrl, PINCTRL_STATE_RELEASE); +- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { +- retval = PTR_ERR(ts_data->pinctrl_state_release); +- dev_dbg(&ts_data->client->dev, +- "Can't lookup %s pinstate %d\n", +- PINCTRL_STATE_RELEASE, retval); +- } +- +- return 0; +- +-err_pinctrl_lookup: +- devm_pinctrl_put(ts_data->ts_pinctrl); +-err_pinctrl_get: +- ts_data->ts_pinctrl = NULL; +- return retval; +-} +- +-static unsigned char calculate_checksum(unsigned char *msg, int length) +-{ +- int checksum = 0, i; +- +- for (i = 0; i < length; i++) +- checksum += msg[i]; +- +- return (unsigned char)((-checksum) & 0xFF); +-} +- +-static int parse_info(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char data[DEMO_MODE_PACKET_LENGTH] = {0}; +- unsigned char checksum = 0; +- unsigned int x = 0, y = 0; +- unsigned int x2 = 0, y2 = 0; +- unsigned int delta_x = 0, delta_y = 0; +- +- mutex_lock(&msg21xx_mutex); +- read_i2c_seq(ts_data, ts_data->client->addr, &data[0], +- DEMO_MODE_PACKET_LENGTH); +- mutex_unlock(&msg21xx_mutex); +- checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1)); +- dev_dbg(&ts_data->client->dev, "check sum: [%x] == [%x]?\n", +- data[DEMO_MODE_PACKET_LENGTH-1], checksum); +- +- if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) { +- dev_err(&ts_data->client->dev, "WRONG CHECKSUM\n"); +- return -EINVAL; +- } +- +- if (data[0] != 0x52) { +- dev_err(&ts_data->client->dev, "WRONG HEADER\n"); +- return -EINVAL; +- } +- +- ts_data->info.keycode = 0xFF; +- if ((data[1] == 0xFF) && (data[2] == 0xFF) && +- (data[3] == 0xFF) && (data[4] == 0xFF) && +- (data[6] == 0xFF)) { +- if ((data[5] == 0xFF) || (data[5] == 0)) { +- ts_data->info.keycode = 0xFF; +- } else if ((data[5] == 1) || (data[5] == 2) || +- (data[5] == 4) || (data[5] == 8)) { +- ts_data->info.keycode = data[5] >> 1; +- +- dev_dbg(&ts_data->client->dev, +- "ts_data->info.keycode index %d\n", +- ts_data->info.keycode); +- } +- #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR +- else if (bEnableTpProximity && ((data[5] == 0x80) || +- (data[5] == 0x40))) { +- if (data[5] == 0x80) +- bFaceClosingTp = 1; +- else if (data[5] == 0x40) +- bFaceClosingTp = 0; +- +- return -EINVAL; +- } +- #endif +- else { +- dev_err(&ts_data->client->dev, "WRONG KEY\n"); +- return -EINVAL; +- } +- } else { +- x = (((data[1] & 0xF0) << 4) | data[2]); +- y = (((data[1] & 0x0F) << 8) | data[3]); +- delta_x = (((data[4] & 0xF0) << 4) | data[5]); +- delta_y = (((data[4] & 0x0F) << 8) | data[6]); +- +- if ((delta_x == 0) && (delta_y == 0)) { +- ts_data->info.point[0].x = +- x * ts_data->pdata->x_max / TPD_WIDTH; +- ts_data->info.point[0].y = +- y * ts_data->pdata->y_max / TPD_HEIGHT; +- ts_data->info.count = 1; +- } else { +- if (delta_x > 2048) +- delta_x -= 4096; +- +- if (delta_y > 2048) +- delta_y -= 4096; +- +- x2 = (unsigned int)((signed short)x + +- (signed short)delta_x); +- y2 = (unsigned int)((signed short)y + +- (signed short)delta_y); +- ts_data->info.point[0].x = +- x * ts_data->pdata->x_max / TPD_WIDTH; +- ts_data->info.point[0].y = +- y * ts_data->pdata->y_max / TPD_HEIGHT; +- ts_data->info.point[1].x = +- x2 * ts_data->pdata->x_max / TPD_WIDTH; +- ts_data->info.point[1].y = +- y2 * ts_data->pdata->y_max / TPD_HEIGHT; +- ts_data->info.count = ts_data->pdata->num_max_touches; +- } +- } +- +- return 0; +-} +- +-static void touch_driver_touch_released(struct msg21xx_ts_data *ts_data) +-{ +- int i; +- +- for (i = 0; i < ts_data->pdata->num_max_touches; i++) { +- input_mt_slot(ts_data->input_dev, i); +- input_mt_report_slot_state(ts_data->input_dev, +- MT_TOOL_FINGER, 0); +- } +- +- input_report_key(ts_data->input_dev, BTN_TOUCH, 0); +- input_report_key(ts_data->input_dev, BTN_TOOL_FINGER, 0); +- input_sync(ts_data->input_dev); +-} +- +-/* read data through I2C then report data to input +- *sub-system when interrupt occurred +- */ +-static irqreturn_t msg21xx_ts_interrupt(int irq, void *dev_id) +-{ +- int i = 0; +- static int last_keycode = 0xFF; +- static int last_count; +- struct msg21xx_ts_data *ts_data = dev_id; +- +- ts_data->info.count = 0; +- if (parse_info(ts_data) == 0) { +- if (ts_data->info.keycode != 0xFF) { /* key touch pressed */ +- if (ts_data->info.keycode < +- ts_data->pdata->num_buttons) { +- if (ts_data->info.keycode != last_keycode) { +- dev_dbg(&ts_data->client->dev, +- "key touch pressed"); +- +- input_report_key(ts_data->input_dev, +- BTN_TOUCH, 1); +- input_report_key(ts_data->input_dev, +- ts_data->pdata->button_map[ +- ts_data->info.keycode], 1); +- +- last_keycode = ts_data->info.keycode; +- } else { +- /* pass duplicate key-pressing */ +- dev_dbg(&ts_data->client->dev, +- "REPEATED KEY\n"); +- } +- } else { +- dev_dbg(&ts_data->client->dev, "WRONG KEY\n"); +- } +- } else { /* key touch released */ +- if (last_keycode != 0xFF) { +- dev_dbg(&ts_data->client->dev, "key touch released"); +- +- input_report_key(ts_data->input_dev, +- BTN_TOUCH, 0); +- input_report_key(ts_data->input_dev, +- ts_data->pdata->button_map[last_keycode], +- 0); +- +- last_keycode = 0xFF; +- } +- } +- +- if (ts_data->info.count > 0) { /* point touch pressed */ +- for (i = 0; i < ts_data->info.count; i++) { +- input_mt_slot(ts_data->input_dev, i); +- input_mt_report_slot_state(ts_data->input_dev, +- MT_TOOL_FINGER, 1); +- input_report_abs(ts_data->input_dev, +- ABS_MT_TOUCH_MAJOR, 1); +- input_report_abs(ts_data->input_dev, +- ABS_MT_POSITION_X, +- ts_data->info.point[i].x); +- input_report_abs(ts_data->input_dev, +- ABS_MT_POSITION_Y, +- ts_data->info.point[i].y); +- } +- } +- +- if (last_count > info.count) { +- for (i = info.count; i < MAX_TOUCH_NUM; i++) { +- input_mt_slot(input_dev, i); +- input_mt_report_slot_state(input_dev, +- } +- +- if (last_count > ts_data->info.count) { +- for (i = ts_data->info.count; +- i < ts_data->pdata->num_max_touches; +- i++) { +- input_mt_slot(ts_data->input_dev, i); +- input_mt_report_slot_state(ts_data->input_dev, +- MT_TOOL_FINGER, 0); +- } +- } +- last_count = ts_data->info.count; +- +- input_report_key(ts_data->input_dev, BTN_TOUCH, +- ts_data->info.count > 0); +- input_report_key(ts_data->input_dev, BTN_TOOL_FINGER, +- ts_data->info.count > 0); +- +- input_sync(ts_data->input_dev); +- } +- +- return IRQ_HANDLED; +-} +- +-static int msg21xx_ts_power_init(struct msg21xx_ts_data *ts_data, bool init) +-{ +- int rc; +- +- if (init) { +- ts_data->vdd = regulator_get(&ts_data->client->dev, +- "vdd"); +- if (IS_ERR(ts_data->vdd)) { +- rc = PTR_ERR(ts_data->vdd); +- dev_err(&ts_data->client->dev, +- "Regulator get failed vdd rc=%d\n", rc); +- return rc; +- } +- +- if (regulator_count_voltages(ts_data->vdd) > 0) { +- rc = regulator_set_voltage(ts_data->vdd, +- MSTAR_VTG_MIN_UV, +- MSTAR_VTG_MAX_UV); +- if (rc) { +- dev_err(&ts_data->client->dev, +- "Regulator set_vtg failed vdd rc=%d\n", +- rc); +- goto reg_vdd_put; +- } +- } +- +- ts_data->vcc_i2c = regulator_get(&ts_data->client->dev, +- "vcc_i2c"); +- if (IS_ERR(ts_data->vcc_i2c)) { +- rc = PTR_ERR(ts_data->vcc_i2c); +- dev_err(&ts_data->client->dev, +- "Regulator get failed vcc_i2c rc=%d\n", rc); +- goto reg_vdd_set_vtg; +- } +- +- if (regulator_count_voltages(ts_data->vcc_i2c) > 0) { +- rc = regulator_set_voltage(ts_data->vcc_i2c, +- MSTAR_I2C_VTG_MIN_UV, +- MSTAR_I2C_VTG_MAX_UV); +- if (rc) { +- dev_err(&ts_data->client->dev, +- "Regulator set_vtg failed vcc_i2c rc=%d\n", rc); +- goto reg_vcc_i2c_put; +- } +- } +- } else { +- if (regulator_count_voltages(ts_data->vdd) > 0) +- regulator_set_voltage(ts_data->vdd, 0, +- MSTAR_VTG_MAX_UV); +- +- regulator_put(ts_data->vdd); +- +- if (regulator_count_voltages(ts_data->vcc_i2c) > 0) +- regulator_set_voltage(ts_data->vcc_i2c, 0, +- MSTAR_I2C_VTG_MAX_UV); +- +- regulator_put(ts_data->vcc_i2c); +- } +- +- return 0; +- +-reg_vcc_i2c_put: +- regulator_put(ts_data->vcc_i2c); +-reg_vdd_set_vtg: +- if (regulator_count_voltages(ts_data->vdd) > 0) +- regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV); +-reg_vdd_put: +- regulator_put(ts_data->vdd); +- return rc; +-} +- +-static int msg21xx_ts_power_on(struct msg21xx_ts_data *ts_data, bool on) +-{ +- int rc; +- +- if (!on) +- goto power_off; +- +- rc = regulator_enable(ts_data->vdd); +- if (rc) { +- dev_err(&ts_data->client->dev, +- "Regulator vdd enable failed rc=%d\n", rc); +- return rc; +- } +- +- rc = regulator_enable(ts_data->vcc_i2c); +- if (rc) { +- dev_err(&ts_data->client->dev, +- "Regulator vcc_i2c enable failed rc=%d\n", rc); +- regulator_disable(ts_data->vdd); +- } +- +- return rc; +- +- DBG("*** %s ***\n", __func__); +- rc = regulator_disable(vdd); +-power_off: +- rc = regulator_disable(ts_data->vdd); +- if (rc) { +- dev_err(&ts_data->client->dev, +- "Regulator vdd disable failed rc=%d\n", rc); +- return rc; +- } +- +- rc = regulator_disable(ts_data->vcc_i2c); +- if (rc) { +- dev_err(&ts_data->client->dev, +- "Regulator vcc_i2c disable failed rc=%d\n", rc); +- rc = regulator_enable(ts_data->vdd); +- } +- +- return rc; +-} +- +-static int msg21xx_ts_gpio_configure(struct msg21xx_ts_data *ts_data, bool on) +-{ +- int ret = 0; +- +- if (!on) +- goto pwr_deinit; +- +- if (gpio_is_valid(ts_data->pdata->irq_gpio)) { +- ret = gpio_request(ts_data->pdata->irq_gpio, +- "msg21xx_irq_gpio"); +- if (ret) { +- dev_err(&ts_data->client->dev, +- "Failed to request GPIO[%d], %d\n", +- ts_data->pdata->irq_gpio, ret); +- goto err_irq_gpio_req; +- } +- ret = gpio_direction_input(ts_data->pdata->irq_gpio); +- if (ret) { +- dev_err(&ts_data->client->dev, +- "Failed to set direction for gpio[%d], %d\n", +- ts_data->pdata->irq_gpio, ret); +- goto err_irq_gpio_dir; +- } +- gpio_set_value_cansleep(ts_data->pdata->irq_gpio, 1); +- } else { +- dev_err(&ts_data->client->dev, "irq gpio not provided\n"); +- goto err_irq_gpio_req; +- } +- +- if (gpio_is_valid(ts_data->pdata->reset_gpio)) { +- ret = gpio_request(ts_data->pdata->reset_gpio, +- "msg21xx_reset_gpio"); +- if (ret) { +- dev_err(&ts_data->client->dev, +- "Failed to request GPIO[%d], %d\n", +- ts_data->pdata->reset_gpio, ret); +- goto err_reset_gpio_req; +- } +- +- } else { +- if (gpio_is_valid(pdata->irq_gpio)) +- gpio_free(pdata->irq_gpio); +- if (gpio_is_valid(pdata->reset_gpio)) { +- gpio_set_value_cansleep(pdata->reset_gpio, 0); +- ret = gpio_direction_input(pdata->reset_gpio); +- if (ret) +- dev_err(&i2c_client->dev, +- "Unable to set direction for gpio [%d]\n", +- pdata->reset_gpio); +- gpio_free(pdata->reset_gpio); +- } +- } +- return 0; +- /* power on TP */ +- ret = gpio_direction_output( +- ts_data->pdata->reset_gpio, 1); +- if (ret) { +- dev_err(&ts_data->client->dev, +- "Failed to set direction for GPIO[%d], %d\n", +- ts_data->pdata->reset_gpio, ret); +- goto err_reset_gpio_dir; +- } +- msleep(100); +- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0); +- msleep(20); +- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 1); +- msleep(200); +- } else { +- dev_err(&ts_data->client->dev, "reset gpio not provided\n"); +- goto err_reset_gpio_req; +- } +- +- return 0; +- +-err_reset_gpio_dir: +- if (gpio_is_valid(ts_data->pdata->reset_gpio)) +- gpio_free(ts_data->pdata->irq_gpio); +-err_reset_gpio_req: +-err_irq_gpio_dir: +- if (gpio_is_valid(ts_data->pdata->irq_gpio)) +- gpio_free(ts_data->pdata->irq_gpio); +-err_irq_gpio_req: +- return ret; +- +-pwr_deinit: +- if (gpio_is_valid(ts_data->pdata->irq_gpio)) +- gpio_free(ts_data->pdata->irq_gpio); +- if (gpio_is_valid(ts_data->pdata->reset_gpio)) { +- gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0); +- ret = gpio_direction_input(ts_data->pdata->reset_gpio); +- if (ret) +- dev_err(&ts_data->client->dev, +- "Unable to set direction for gpio [%d]\n", +- ts_data->pdata->reset_gpio); +- gpio_free(ts_data->pdata->reset_gpio); +- } +- return 0; +-} +- +-#ifdef CONFIG_PM +-static int msg21xx_ts_resume(struct device *dev) +-{ +- int retval; +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- if (!ts_data->suspended) { +- dev_info(dev, "msg21xx_ts already in resume\n"); +- return 0; +- } +- +- mutex_lock(&ts_data->ts_mutex); +- +- retval = msg21xx_ts_power_on(ts_data, true); +- if (retval) { +- dev_err(dev, "msg21xx_ts power on failed"); +- mutex_unlock(&ts_data->ts_mutex); +- return retval; +- } +- +- if (ts_data->ts_pinctrl) { +- retval = pinctrl_select_state(ts_data->ts_pinctrl, +- ts_data->pinctrl_state_active); +- if (retval < 0) { +- dev_err(dev, "Cannot get active pinctrl state\n"); +- mutex_unlock(&ts_data->ts_mutex); +- return retval; +- } +- } +- +- retval = msg21xx_ts_gpio_configure(ts_data, true); +- if (retval) { +- dev_err(dev, "Failed to put gpios in active state %d", +- retval); +- mutex_unlock(&ts_data->ts_mutex); +- return retval; +- } +- +- enable_irq(ts_data->client->irq); +- ts_data->suspended = false; +- +- mutex_unlock(&ts_data->ts_mutex); +- +- return 0; +-} +- +-static int msg21xx_ts_suspend(struct device *dev) +-{ +- int retval; +- struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev); +- +- if (ts_data->pdata->updating_fw) { +- dev_info(dev, "Firmware loading in progress\n"); +- return 0; +- } +- +- if (ts_data->suspended) { +- dev_info(dev, "msg21xx_ts already in suspend\n"); +- return 0; +- } +- +-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR +- if (bEnableTpProximity) { +- dev_dbg(dev, "suspend bEnableTpProximity=%d\n", +- bEnableTpProximity); +- return 0; +- } +-#endif +- +- mutex_lock(&ts_data->ts_mutex); +- +- disable_irq(ts_data->client->irq); +- +- touch_driver_touch_released(ts_data); +- +- if (ts_data->ts_pinctrl) { +- retval = pinctrl_select_state(ts_data->ts_pinctrl, +- ts_data->pinctrl_state_suspend); +- if (retval < 0) { +- dev_err(dev, "Cannot get idle pinctrl state %d\n", +- retval); +- mutex_unlock(&ts_data->ts_mutex); +- return retval; +- } +- } +- +- retval = msg21xx_ts_gpio_configure(ts_data, false); +- if (retval) { +- dev_err(dev, "Failed to put gpios in idle state %d", +- retval); +- mutex_unlock(&ts_data->ts_mutex); +- return retval; +- } +- +- retval = msg21xx_ts_power_on(ts_data, false); +- if (retval) { +- dev_err(dev, "msg21xx_ts power off failed"); +- mutex_unlock(&ts_data->ts_mutex); +- return retval; +- } +- +- ts_data->suspended = true; +- +- mutex_unlock(&ts_data->ts_mutex); +- +- return 0; +-} +-#else +-static int msg21xx_ts_resume(struct device *dev) +-{ +- return 0; +-} +-static int msg21xx_ts_suspend(struct device *dev) +-{ +- return 0; +-} +-#endif +- +-static int msg21xx_debug_suspend_set(void *_data, u64 val) +-{ +- struct msg21xx_ts_data *data = _data; +- +- mutex_lock(&data->input_dev->mutex); +- +- if (val) +- msg21xx_ts_suspend(&data->client->dev); +- else +- msg21xx_ts_resume(&data->client->dev); +- +- mutex_unlock(&data->input_dev->mutex); +- +- return 0; +-} +- +-static int msg21xx_debug_suspend_get(void *_data, u64 *val) +-{ +- struct msg21xx_ts_data *data = _data; +- +- mutex_lock(&data->input_dev->mutex); +- *val = data->suspended; +- mutex_unlock(&data->input_dev->mutex); +- +- return 0; +-} +- +-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, msg21xx_debug_suspend_get, +- msg21xx_debug_suspend_set, "%lld\n"); +- +- +-#if defined(CONFIG_FB) +-static int fb_notifier_callback(struct notifier_block *self, +- unsigned long event, void *data) +-{ +- struct fb_event *evdata = data; +- int *blank; +- struct msg21xx_ts_data *ts_data = +- container_of(self, struct msg21xx_ts_data, fb_notif); +- +- if (evdata && evdata->data && event == FB_EVENT_BLANK) { +- blank = evdata->data; +- if (*blank == FB_BLANK_UNBLANK) +- msg21xx_ts_resume(&ts_data->client->dev); +- else if (*blank == FB_BLANK_POWERDOWN) +- msg21xx_ts_suspend(&ts_data->client->dev); +- } +- +- return 0; +-} +-#endif +- +-static int msg21xx_get_dt_coords(struct device *dev, char *name, +- struct msg21xx_ts_platform_data *pdata) +-{ +- u32 coords[FT_COORDS_ARR_SIZE]; +- struct property *prop; +- struct device_node *np = dev->of_node; +- int coords_size, rc; +- +- prop = of_find_property(np, name, NULL); +- if (!prop) +- return -EINVAL; +- if (!prop->value) +- return -ENODATA; +- +- coords_size = prop->length / sizeof(u32); +- if (coords_size != FT_COORDS_ARR_SIZE) { +- dev_err(dev, "invalid %s\n", name); +- return -EINVAL; +- } +- +- rc = of_property_read_u32_array(np, name, coords, coords_size); +- if (rc && (rc != -EINVAL)) { +- dev_err(dev, "Unable to read %s\n", name); +- return rc; +- } +- +- if (!strcmp(name, "mstar,panel-coords")) { +- pdata->panel_minx = coords[0]; +- pdata->panel_miny = coords[1]; +- pdata->panel_maxx = coords[2]; +- pdata->panel_maxy = coords[3]; +- } else if (!strcmp(name, "mstar,display-coords")) { +- pdata->x_min = coords[0]; +- pdata->y_min = coords[1]; +- pdata->x_max = coords[2]; +- pdata->y_max = coords[3]; +- } else { +- dev_err(dev, "unsupported property %s\n", name); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int msg21xx_parse_dt(struct device *dev, +- struct msg21xx_ts_platform_data *pdata) +-{ +- int rc; +- struct device_node *np = dev->of_node; +- struct property *prop; +- u32 temp_val; +- +- rc = msg21xx_get_dt_coords(dev, "mstar,panel-coords", pdata); +- if (rc && (rc != -EINVAL)) +- return rc; +- +- rc = msg21xx_get_dt_coords(dev, "mstar,display-coords", pdata); +- if (rc) +- return rc; +- +- rc = of_property_read_u32(np, "mstar,hard-reset-delay-ms", +- &temp_val); +- if (!rc) +- pdata->hard_reset_delay_ms = temp_val; +- else +- return rc; +- +- rc = of_property_read_u32(np, "mstar,post-hard-reset-delay-ms", +- &temp_val); +- if (!rc) +- pdata->post_hard_reset_delay_ms = temp_val; +- else +- return rc; +- +- /* reset, irq gpio info */ +- pdata->reset_gpio = of_get_named_gpio_flags(np, "mstar,reset-gpio", +- 0, &pdata->reset_gpio_flags); +- if (pdata->reset_gpio < 0) +- return pdata->reset_gpio; +- +- pdata->irq_gpio = of_get_named_gpio_flags(np, "mstar,irq-gpio", +- 0, &pdata->irq_gpio_flags); +- if (pdata->irq_gpio < 0) +- return pdata->irq_gpio; +- +- rc = of_property_read_u32(np, "mstar,ic-type", &temp_val); +- if (rc && (rc != -EINVAL)) +- return rc; +- +- pdata->ic_type = temp_val; +- +- rc = of_property_read_u32(np, "mstar,num-max-touches", &temp_val); +- if (!rc) +- pdata->num_max_touches = temp_val; +- else +- return rc; +- +- prop = of_find_property(np, "mstar,button-map", NULL); +- if (prop) { +- pdata->num_buttons = prop->length / sizeof(temp_val); +- if (pdata->num_buttons > MAX_BUTTONS) +- return -EINVAL; +- +- rc = of_property_read_u32_array(np, +- "mstar,button-map", pdata->button_map, +- pdata->num_buttons); +- if (rc) { +- dev_err(dev, "Unable to read key codes\n"); +- return rc; +- } +- } +- +- return 0; +-} +- +-/* probe function is used for matching and initializing input device */ +-static int msg21xx_ts_probe(struct i2c_client *client, +- const struct i2c_device_id *id) { +- +- int ret = 0, i; +- struct dentry *temp, *dir; +- struct input_dev *input_dev; +- struct msg21xx_ts_data *ts_data; +- struct msg21xx_ts_platform_data *pdata; +- +- if (client->dev.of_node) { +- pdata = devm_kzalloc(&client->dev, +- sizeof(struct msg21xx_ts_platform_data), GFP_KERNEL); +- if (!pdata) +- return -ENOMEM; +- +- ret = msg21xx_parse_dt(&client->dev, pdata); +- if (ret) { +- dev_err(&client->dev, "DT parsing failed\n"); +- return ret; +- } +- } else +- pdata = client->dev.platform_data; +- +- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { +- dev_err(&client->dev, "I2C not supported\n"); +- return -ENODEV; +- } +- +- ts_data = devm_kzalloc(&client->dev, +- sizeof(struct msg21xx_ts_data), GFP_KERNEL); +- if (!ts_data) +- return -ENOMEM; +- +- ts_data->client = client; +- ts_data->info.point = devm_kzalloc(&client->dev, +- sizeof(struct touchPoint_t) * pdata->num_max_touches, +- GFP_KERNEL); +- if (!ts_data->info.point) { +- dev_err(&client->dev, "Not enough memory\n"); +- return -ENOMEM; +- } +- +- /* allocate an input device */ +- input_dev = input_allocate_device(); +- if (!input_dev) { +- ret = -ENOMEM; +- dev_err(&client->dev, "input device allocation failed\n"); +- goto err_input_allocate_dev; +- } +- +- input_dev->name = client->name; +- input_dev->phys = "I2C"; +- input_dev->dev.parent = &client->dev; +- input_dev->id.bustype = BUS_I2C; +- +- ts_data->input_dev = input_dev; +- ts_data->client = client; +- ts_data->pdata = pdata; +- +- input_set_drvdata(input_dev, ts_data); +- i2c_set_clientdata(client, ts_data); +- +- ret = msg21xx_ts_power_init(ts_data, true); +- if (ret) { +- dev_err(&client->dev, "Mstar power init failed\n"); +- return ret; +- } +- +- ret = msg21xx_ts_power_on(ts_data, true); +- if (ret) { +- dev_err(&client->dev, "Mstar power on failed\n"); +- goto exit_deinit_power; +- } +- +- ret = msg21xx_pinctrl_init(ts_data); +- if (!ret && ts_data->ts_pinctrl) { +- /* +- * Pinctrl handle is optional. If pinctrl handle is found +- * let pins to be configured in active state. If not +- * found continue further without error. +- */ +- ret = pinctrl_select_state(ts_data->ts_pinctrl, +- ts_data->pinctrl_state_active); +- if (ret < 0) +- dev_err(&client->dev, +- "Failed to select %s pinatate %d\n", +- PINCTRL_STATE_ACTIVE, ret); +- } +- +- ret = msg21xx_ts_gpio_configure(ts_data, true); +- if (ret) { +- dev_err(&client->dev, "Failed to configure gpio %d\n", ret); +- goto exit_gpio_config; +- } +- +- if (msg21xx_get_ic_type(ts_data) == 0) { +- dev_err(&client->dev, "The current IC is not Mstar\n"); +- ret = -1; +- goto err_wrong_ic_type; +- } +- +- mutex_init(&msg21xx_mutex); +- mutex_init(&ts_data->ts_mutex); +- +- /* set the supported event type for input device */ +- set_bit(EV_ABS, input_dev->evbit); +- set_bit(EV_SYN, input_dev->evbit); +- set_bit(EV_KEY, input_dev->evbit); +- set_bit(BTN_TOUCH, input_dev->keybit); +- set_bit(BTN_TOOL_FINGER, input_dev->keybit); +- set_bit(INPUT_PROP_DIRECT, input_dev->propbit); +- +- for (i = 0; i < pdata->num_buttons; i++) +- input_set_capability(input_dev, EV_KEY, pdata->button_map[i]); +- +- input_set_drvdata(input_dev, ts_data); +- i2c_set_clientdata(client, ts_data); +- +-#ifdef CONFIG_TP_HAVE_KEY +- { +- int i; +- +- for (i = 0; i < num_buttons; i++) +- input_set_capability(input_dev, EV_KEY, button_map[i]); +- } +-#endif +- +- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, +- 0, 2, 0, 0); +- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0); +- input_set_abs_params(input_dev, ABS_MT_POSITION_X, +- 0, pdata->x_max, 0, 0); +- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, +- 0, pdata->y_max, 0, 0); +- ret = input_mt_init_slots(input_dev, pdata->num_max_touches, 0); +- if (ret) { +- dev_err(&client->dev, +- "Error %d initialising slots\n", ret); +- goto err_free_mem; +- } +- +- /* register the input device to input sub-system */ +- ret = input_register_device(input_dev); +- if (ret < 0) { +- dev_err(&client->dev, +- "Unable to register ms-touchscreen input device\n"); +- goto err_input_reg_dev; +- } +- +- /* version */ +- if (device_create_file(&client->dev, &dev_attr_version) < 0) { +- dev_err(&client->dev, +- "Failed to create device file(%s)!\n", +- dev_attr_version.attr.name); +- goto err_create_fw_ver_file; +- } +- /* update */ +- if (device_create_file(&client->dev, &dev_attr_update) < 0) { +- dev_err(&client->dev, +- "Failed to create device file(%s)!\n", +- dev_attr_update.attr.name); +- goto err_create_fw_update_file; +- } +- /* data */ +- if (device_create_file(&client->dev, &dev_attr_data) < 0) { +- dev_err(&client->dev, +- "Failed to create device file(%s)!\n", +- dev_attr_data.attr.name); +- goto err_create_fw_data_file; +- } +- /* fw name */ +- if (device_create_file(&client->dev, &dev_attr_fw_name) < 0) { +- dev_err(&client->dev, +- "Failed to create device file(%s)!\n", +- dev_attr_fw_name.attr.name); +- goto err_create_fw_name_file; +- } +- /* smart fw update */ +- if (device_create_file(&client->dev, &dev_attr_update_fw) < 0) { +- dev_err(&client->dev, +- "Failed to create device file(%s)!\n", +- dev_attr_update_fw.attr.name); +- goto err_create_update_fw_file; +- } +- /* smart fw force update */ +- if (device_create_file(&client->dev, +- &dev_attr_force_update_fw) < 0) { +- dev_err(&client->dev, +- "Failed to create device file(%s)!\n", +- dev_attr_force_update_fw.attr.name); +- goto err_create_force_update_fw_file; +- } +- dir = debugfs_create_dir(MSTAR_DEBUG_DIR_NAME, NULL); +- temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, dir, +- ts_data, &debug_suspend_fops); +- if (temp == NULL || IS_ERR(temp)) { +- dev_err(&client->dev, +- "debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); +- goto free_debug_dir; +- } +- +-#ifdef TP_PRINT +- tp_print_create_entry(ts_data); +-#endif +- +- ret = request_threaded_irq(client->irq, NULL, +- msg21xx_ts_interrupt, +- pdata->irq_gpio_flags | IRQF_ONESHOT, +- "msg21xx", ts_data); +- if (ret) +- goto err_req_irq; +- +- disable_irq(client->irq); +- +-#if defined(CONFIG_FB) +- ts_data->fb_notif.notifier_call = fb_notifier_callback; +- ret = fb_register_client(&ts_data->fb_notif); +-#endif +- +-#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR +- tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable, +- &tsps_msg21xx_data); +-#endif +- +- dev_dbg(&client->dev, "mstar touch screen registered\n"); +- enable_irq(client->irq); +- return 0; +- +-err_req_irq: +- free_irq(client->irq, ts_data); +- device_remove_file(&client->dev, &dev_attr_data); +-free_debug_dir: +- debugfs_remove_recursive(dir); +-err_create_fw_data_file: +- device_remove_file(&client->dev, &dev_attr_update); +-err_create_fw_update_file: +- device_remove_file(&client->dev, &dev_attr_version); +-err_create_fw_name_file: +- device_remove_file(&client->dev, &dev_attr_fw_name); +-err_create_update_fw_file: +- device_remove_file(&client->dev, &dev_attr_update_fw); +-err_create_force_update_fw_file: +- device_remove_file(&client->dev, &dev_attr_force_update_fw); +-err_create_fw_ver_file: +- input_unregister_device(input_dev); +- +-err_input_reg_dev: +- input_free_device(input_dev); +- input_dev = NULL; +-err_input_allocate_dev: +- mutex_destroy(&msg21xx_mutex); +- mutex_destroy(&ts_data->ts_mutex); +- +-err_wrong_ic_type: +- msg21xx_ts_gpio_configure(ts_data, false); +-exit_gpio_config: +- if (ts_data->ts_pinctrl) { +- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { +- devm_pinctrl_put(ts_data->ts_pinctrl); +- ts_data->ts_pinctrl = NULL; +- } else { +- ret = pinctrl_select_state(ts_data->ts_pinctrl, +- ts_data->pinctrl_state_release); +- if (ret < 0) +- dev_err(&ts_data->client->dev, +- "Cannot get release pinctrl state\n"); +- } +- } +- msg21xx_ts_power_on(ts_data, false); +-exit_deinit_power: +- msg21xx_ts_power_init(ts_data, false); +-err_free_mem: +- input_free_device(input_dev); +- +- return ret; +-} +- +-/* remove function is triggered when the input device is removed +- *from input sub-system +- */ +-static int touch_driver_remove(struct i2c_client *client) +-{ +- int retval = 0; +- struct msg21xx_ts_data *ts_data = i2c_get_clientdata(client); +- +- free_irq(ts_data->client->irq, ts_data); +- gpio_free(ts_data->pdata->irq_gpio); +- gpio_free(ts_data->pdata->reset_gpio); +- +- if (ts_data->ts_pinctrl) { +- if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { +- devm_pinctrl_put(ts_data->ts_pinctrl); +- ts_data->ts_pinctrl = NULL; +- } else { +- retval = pinctrl_select_state(ts_data->ts_pinctrl, +- ts_data->pinctrl_state_release); +- if (retval < 0) +- dev_err(&ts_data->client->dev, +- "Cannot get release pinctrl state\n"); +- } +- } +- +- input_unregister_device(ts_data->input_dev); +- mutex_destroy(&msg21xx_mutex); +- mutex_destroy(&ts_data->ts_mutex); +- +- return retval; +-} +- +-/* The I2C device list is used for matching I2C device +- *and I2C device driver. +- */ +-static const struct i2c_device_id touch_device_id[] = { +- {"msg21xx", 0}, +- {}, /* should not omitted */ +-}; +- +-static const struct of_device_id msg21xx_match_table[] = { +- { .compatible = "mstar,msg21xx", }, +- { }, +-}; +- +-MODULE_DEVICE_TABLE(i2c, touch_device_id); +- +-static struct i2c_driver touch_device_driver = { +- .driver = { +- .name = "ms-msg21xx", +- .owner = THIS_MODULE, +- .of_match_table = msg21xx_match_table, +- }, +- .probe = msg21xx_ts_probe, +- .remove = touch_driver_remove, +- .id_table = touch_device_id, +-}; +- +-module_i2c_driver(touch_device_driver); +- +-#ifdef TP_PRINT +-#include +- +-static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256; +-static unsigned char row, units, cnt; +- +-static int tp_print_proc_read(struct msg21xx_ts_data *ts_data) +-{ +- unsigned short i, j; +- unsigned short left, offset = 0; +- unsigned char dbbus_tx_data[3] = {0}; +- unsigned char u8Data; +- signed short s16Data; +- int s32Data; +- char *buf = NULL; +- +- left = cnt*row*units; +- if ((ts_data->suspended == 0) && +- (InfoAddr != 0x0F) && +- (PoolAddr != 0x10) && +- (left > 0)) { +- buf = kmalloc(left, GFP_KERNEL); +- if (buf != NULL) { +- +- while (left > 0) { +- dbbus_tx_data[0] = 0x53; +- dbbus_tx_data[1] = ((PoolAddr + offset) >> 8) +- & 0xFF; +- dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF; +- mutex_lock(&msg21xx_mutex); +- write_i2c_seq(ts_data, ts_data->client->addr, +- &dbbus_tx_data[0], 3); +- read_i2c_seq(ts_data, ts_data->client->addr, +- &buf[offset], +- left > TransLen ? TransLen : left); +- mutex_unlock(&msg21xx_mutex); +- +- if (left > TransLen) { +- left -= TransLen; +- offset += TransLen; +- } else { +- left = 0; +- } +- } +- +- for (i = 0; i < cnt; i++) { +- for (j = 0; j < row; j++) { +- if (units == 1) { +- u8Data = buf[i * row * units + +- j * units]; +- } else if (units == 2) { +- s16Data = buf[i * row * units + +- j * units] + +- (buf[i * row * units + +- j * units + 1] << 8); +- } else if (units == 4) { +- s32Data = buf[i * row * units + +- j * units] + +- (buf[i * row * units + +- j * units + 1] << 8) + +- (buf[i * row * units + +- j * units + 2] << 16) + +- (buf[i * row * units + +- j * units + 3] << 24); +- } +- } +- } +- +- kfree(buf); +- } +- } +- +- return 0; +-} +- +-static void tp_print_create_entry(struct msg21xx_ts_data *ts_data) +-{ +- unsigned char dbbus_tx_data[3] = {0}; +- unsigned char dbbus_rx_data[8] = {0}; +- +- dbbus_tx_data[0] = 0x53; +- dbbus_tx_data[1] = 0x00; +- dbbus_tx_data[2] = 0x58; +- mutex_lock(&msg21xx_mutex); +- write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 3); +- read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4); +- mutex_unlock(&msg21xx_mutex); +- InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0]; +- PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2]; +- +- if ((InfoAddr != 0x0F) && (PoolAddr != 0x10)) { +- msleep(20); +- dbbus_tx_data[0] = 0x53; +- dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF; +- dbbus_tx_data[2] = InfoAddr & 0xFF; +- mutex_lock(&msg21xx_mutex); +- write_i2c_seq(ts_data, ts_data->client->addr, +- &dbbus_tx_data[0], 3); +- read_i2c_seq(ts_data, ts_data->client->addr, +- &dbbus_rx_data[0], 8); +- mutex_unlock(&msg21xx_mutex); +- +- units = dbbus_rx_data[0]; +- row = dbbus_rx_data[1]; +- cnt = dbbus_rx_data[2]; +- TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6]; +- +- if (device_create_file(&ts_data->client->dev, +- &dev_attr_tpp) < 0) +- dev_err(&ts_data->client->dev, "Failed to create device file(%s)!\n", +- dev_attr_tpp.attr.name); +- } +-} +-#endif +- +-MODULE_AUTHOR("MStar Semiconductor, Inc."); +-MODULE_LICENSE("GPL v2"); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6423/0.patch b/Patches/Linux_CVEs/CVE-2017-6423/0.patch new file mode 100644 index 00000000..d561f1ca --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6423/0.patch @@ -0,0 +1,67 @@ +From 0f264f812b61884390b432fdad081a3e995ba768 Mon Sep 17 00:00:00 2001 +From: Kaushal Kumar +Date: Fri, 20 Jan 2017 15:23:40 +0530 +Subject: soc: qcom: make debugfs support configurable for kryo l2 accessors + driver + +Add config option to enable/disable l2 indirect access debug capability. +The driver exposes l2 indirect access debugfs interface to get/set data, +address, and target cpus so keep it disabled by default. + +Change-Id: I22f84d16a3bf12a78295f2d052bb50e90d6f2a8b +Signed-off-by: Kaushal Kumar +--- + drivers/soc/qcom/Kconfig | 10 ++++++++++ + drivers/soc/qcom/kryo-l2-accessors.c | 6 +++--- + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig +index ae2f304..b039090 100644 +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -292,6 +292,16 @@ config MSM_CACHE_M4M_ERP64_PANIC_ON_UE + Say 'Y' here to cause kernel panic when uncorrectable cache/M4M errors + are detected. + ++config MSM_L2_IA_DEBUG ++ bool "Enable MSM L2 Indirect Access Debug" ++ depends on DEBUG_FS ++ default n ++ help ++ This option enables L2 indirect access debug ++ capability. It exposes L2 indirect access ++ debugfs interface to get/set data, address, ++ and target cpus. ++ + config MSM_RPM_SMD + bool "RPM driver using SMD protocol" + help +diff --git a/drivers/soc/qcom/kryo-l2-accessors.c b/drivers/soc/qcom/kryo-l2-accessors.c +index a945f9e..1d81074 100644 +--- a/drivers/soc/qcom/kryo-l2-accessors.c ++++ b/drivers/soc/qcom/kryo-l2-accessors.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2015, 2017, The 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 +@@ -80,7 +80,7 @@ u64 get_l2_indirect_reg(u64 reg) + } + EXPORT_SYMBOL(get_l2_indirect_reg); + +-#if defined(CONFIG_DEBUG_FS) ++#if defined(CONFIG_MSM_L2_IA_DEBUG) + + static u32 debug_addr; + static int debug_target_cpu; +@@ -180,4 +180,4 @@ static int l2_ia_debug_init(void) + } + late_initcall(l2_ia_debug_init); + +-#endif /* CONFIG_DEBUG_FS */ ++#endif /* CONFIG_MSM_L2_IA_DEBUG */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6424/0.patch b/Patches/Linux_CVEs/CVE-2017-6424/0.patch new file mode 100644 index 00000000..cfc79dea --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6424/0.patch @@ -0,0 +1,40 @@ +From 5cc2ac840e36a3342c5194c20b314f0bb95ef7e1 Mon Sep 17 00:00:00 2001 +From: Nishank Aggarwal +Date: Thu, 12 Jan 2017 14:32:02 +0530 +Subject: qcacld-2.0: Fix buffer overflow in WLANSAP_Set_WPARSNIes() + +Currently In WLANSAP_Set_WPARSNIes() the parameter WPARSNIEsLen +is user-controllable and never validates which uses as the length +for a memory copy. This enables user-space applications to corrupt +heap memory and potentially crash the kernel. + +Fix is to validate the WPARSNIes length to its max before use as the +length for a memory copy. + +Change-Id: I7aff731aeae22bfd84beb955439a799abef37f68 +CRs-Fixed: 1102648 +--- + CORE/HDD/src/wlan_hdd_hostapd.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index 693c0c9..59b32f2 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -6099,6 +6099,13 @@ static int __iw_set_ap_genie(struct net_device *dev, + return 0; + } + ++ if (wrqu->data.length > DOT11F_IE_RSN_MAX_LEN) { ++ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ++ "%s: WPARSN Ie input length is more than max[%d]", __func__, ++ wrqu->data.length); ++ return -EINVAL; ++ } ++ + switch (genie[0]) + { + case DOT11F_EID_WPA: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6424/1.patch b/Patches/Linux_CVEs/CVE-2017-6424/1.patch new file mode 100644 index 00000000..a91f45c3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6424/1.patch @@ -0,0 +1,50 @@ +From 8cac3c4aac106b917e60e7aa7d4c4189e376913c Mon Sep 17 00:00:00 2001 +From: Nishank Aggarwal +Date: Fri, 10 Feb 2017 15:48:13 +0530 +Subject: wlan: Fix buffer overflow in WLANSAP_Set_WPARSNIes() + +qcacld-2.0 to prima propagation + +Currently In WLANSAP_Set_WPARSNIes() the parameter WPARSNIEsLen +is user-controllable and never validates which uses as the length +for a memory copy. This enables user-space applications to corrupt +heap memory and potentially crash the kernel. + +Fix is to validate the WPARSNIes length to its max before use as the +length for a memory copy. + +Change-Id: I7aff731aeae22bfd84beb955439a799abef37f68 +CRs-Fixed: 1102648 +--- + CORE/HDD/src/wlan_hdd_hostapd.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index 33f7d50..c0c5c14 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * +@@ -4180,6 +4180,14 @@ static int __iw_set_ap_genie(struct net_device *dev, + return 0; + } + ++ if (wrqu->data.length > DOT11F_IE_RSN_MAX_LEN) ++ { ++ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ++ "%s: WPARSN Ie input length is more than max[%d]", __func__, ++ wrqu->data.length); ++ return -EINVAL; ++ } ++ + switch (genie[0]) + { + case DOT11F_EID_WPA: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6425/0.patch b/Patches/Linux_CVEs/CVE-2017-6425/0.patch new file mode 100644 index 00000000..3c156278 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6425/0.patch @@ -0,0 +1,46 @@ +From ef86560a21fe1f256f6ba772a195201ff202c657 Mon Sep 17 00:00:00 2001 +From: "Sravan Kumar D.V.N" +Date: Fri, 6 Jan 2017 13:50:04 +0530 +Subject: msm: mdss: Clear compat structures before copying to user + +In the compat layer, the temporary structures used to convert +data from 32bit to 64bit structures need to be set to 0 before +being assigned values. + +CRs-Fixed: 1103689 +Change-Id: I405500f427f3f4dc4d38a9fb188fece9a31614ca +Signed-off-by: Sravan Kumar D.V.N +--- + drivers/video/msm/mdss/mdss_compat_utils.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c +index ce786f2..35b1b49 100644 +--- a/drivers/video/msm/mdss/mdss_compat_utils.c ++++ b/drivers/video/msm/mdss/mdss_compat_utils.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 1994 Martin Schaller + * + * 2001 - Documented with DocBook +@@ -965,6 +965,7 @@ static int __to_user_pcc_coeff_v1_7( + struct mdp_pcc_data_v1_7_32 pcc_cfg_payload32; + struct mdp_pcc_data_v1_7 pcc_cfg_payload; + ++ memset(&pcc_cfg_payload32, 0, sizeof(pcc_cfg_payload32)); + if (copy_from_user(&pcc_cfg_payload, + pcc_cfg->cfg_payload, + sizeof(struct mdp_pcc_data_v1_7))) { +@@ -2160,6 +2161,7 @@ static int __to_user_pa_data_v1_7( + struct mdp_pa_data_v1_7_32 pa_cfg_payload32; + struct mdp_pa_data_v1_7 pa_cfg_payload; + ++ memset(&pa_cfg_payload32, 0, sizeof(pa_cfg_payload32)); + if (copy_from_user(&pa_cfg_payload, + pa_v2_cfg->cfg_payload, + sizeof(pa_cfg_payload))) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6426/0.patch b/Patches/Linux_CVEs/CVE-2017-6426/0.patch new file mode 100644 index 00000000..1243066b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6426/0.patch @@ -0,0 +1,124 @@ +From 80decd6365deec08c35ecb902a58f9210599b39a Mon Sep 17 00:00:00 2001 +From: ansharma +Date: Fri, 20 Jan 2017 14:43:57 +0530 +Subject: platform: msm: spmi: Fix possible race condition in debugfs + +There is a possible race condition when debugfs files are concurrently +accessed by multiple threads. Fix this. + +CRs-Fixed: 1106842 +Change-Id: Ifd092143f428db3cf73c45ec4f0aaa96318ae165 +Signed-off-by: ansharma +--- + drivers/platform/msm/spmi/spmi-dbgfs.c | 37 +++++++++++++++++++++++++--------- + 1 file changed, 28 insertions(+), 9 deletions(-) + +diff --git a/drivers/platform/msm/spmi/spmi-dbgfs.c b/drivers/platform/msm/spmi/spmi-dbgfs.c +index b0a354b..86f1b0d 100644 +--- a/drivers/platform/msm/spmi/spmi-dbgfs.c ++++ b/drivers/platform/msm/spmi/spmi-dbgfs.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014, 2017, The 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 +@@ -69,6 +69,7 @@ struct spmi_trans { + u32 addr; /* 20-bit address: SID + PID + Register offset */ + u32 offset; /* Offset of last read data */ + bool raw_data; /* Set to true for raw data dump */ ++ struct mutex spmi_dfs_lock; /* Prevent thread concurrency */ + struct spmi_controller *ctrl; + struct spmi_log_buffer *log; /* log buffer */ + }; +@@ -168,6 +169,7 @@ static int spmi_dfs_open(struct spmi_ctrl_data *ctrl_data, struct file *file) + trans->addr = ctrl_data->addr; + trans->ctrl = ctrl_data->ctrl; + trans->offset = trans->addr; ++ mutex_init(&trans->spmi_dfs_lock); + + file->private_data = trans; + return 0; +@@ -197,6 +199,7 @@ static int spmi_dfs_close(struct inode *inode, struct file *file) + + if (trans && trans->log) { + file->private_data = NULL; ++ mutex_destroy(&trans->spmi_dfs_lock); + kfree(trans->log); + kfree(trans); + } +@@ -473,14 +476,21 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf, + int cnt = 0; + u8 *values; + size_t ret = 0; +- ++ u32 offset; ++ char *kbuf; + struct spmi_trans *trans = file->private_data; +- u32 offset = trans->offset; ++ ++ mutex_lock(&trans->spmi_dfs_lock); ++ ++ trans = file->private_data; ++ offset = trans->offset; + + /* Make a copy of the user data */ +- char *kbuf = kmalloc(count + 1, GFP_KERNEL); +- if (!kbuf) +- return -ENOMEM; ++ kbuf = kmalloc(count + 1, GFP_KERNEL); ++ if (!kbuf) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } + + ret = copy_from_user(kbuf, buf, count); + if (ret == count) { +@@ -517,6 +527,8 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf, + + free_buf: + kfree(kbuf); ++unlock_mutex: ++ mutex_unlock(&trans->spmi_dfs_lock); + return ret; + } + +@@ -537,10 +549,13 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, + size_t ret; + size_t len; + ++ mutex_lock(&trans->spmi_dfs_lock); + /* Is the the log buffer empty */ + if (log->rpos >= log->wpos) { +- if (get_log_data(trans) <= 0) +- return 0; ++ if (get_log_data(trans) <= 0) { ++ len = 0; ++ goto unlock_mutex; ++ } + } + + len = min(count, log->wpos - log->rpos); +@@ -548,7 +563,8 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, + ret = copy_to_user(buf, &log->data[log->rpos], len); + if (ret == len) { + pr_err("error copy SPMI register values to user\n"); +- return -EFAULT; ++ len = -EFAULT; ++ goto unlock_mutex; + } + + /* 'ret' is the number of bytes not copied */ +@@ -556,6 +572,9 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf, + + *ppos += len; + log->rpos += len; ++ ++unlock_mutex: ++ mutex_unlock(&trans->spmi_dfs_lock); + return len; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6874/0.patch b/Patches/Linux_CVEs/CVE-2017-6874/0.patch new file mode 100644 index 00000000..ed0eb437 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6874/0.patch @@ -0,0 +1,89 @@ +From 040757f738e13caaa9c5078bca79aa97e11dde88 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Sun, 5 Mar 2017 15:03:22 -0600 +Subject: ucount: Remove the atomicity from ucount->count + +Always increment/decrement ucount->count under the ucounts_lock. The +increments are there already and moving the decrements there means the +locking logic of the code is simpler. This simplification in the +locking logic fixes a race between put_ucounts and get_ucounts that +could result in a use-after-free because the count could go zero then +be found by get_ucounts and then be freed by put_ucounts. + +A bug presumably this one was found by a combination of syzkaller and +KASAN. JongWhan Kim reported the syzkaller failure and Dmitry Vyukov +spotted the race in the code. + +Cc: stable@vger.kernel.org +Fixes: f6b2db1a3e8d ("userns: Make the count of user namespaces per user") +Reported-by: JongHwan Kim +Reported-by: Dmitry Vyukov +Reviewed-by: Andrei Vagin +Signed-off-by: "Eric W. Biederman" +--- + include/linux/user_namespace.h | 2 +- + kernel/ucount.c | 18 +++++++++++------- + 2 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h +index be76523..32354b4 100644 +--- a/include/linux/user_namespace.h ++++ b/include/linux/user_namespace.h +@@ -72,7 +72,7 @@ struct ucounts { + struct hlist_node node; + struct user_namespace *ns; + kuid_t uid; +- atomic_t count; ++ int count; + atomic_t ucount[UCOUNT_COUNTS]; + }; + +diff --git a/kernel/ucount.c b/kernel/ucount.c +index 62630a4..b4eeee0 100644 +--- a/kernel/ucount.c ++++ b/kernel/ucount.c +@@ -144,7 +144,7 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid) + + new->ns = ns; + new->uid = uid; +- atomic_set(&new->count, 0); ++ new->count = 0; + + spin_lock_irq(&ucounts_lock); + ucounts = find_ucounts(ns, uid, hashent); +@@ -155,8 +155,10 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid) + ucounts = new; + } + } +- if (!atomic_add_unless(&ucounts->count, 1, INT_MAX)) ++ if (ucounts->count == INT_MAX) + ucounts = NULL; ++ else ++ ucounts->count += 1; + spin_unlock_irq(&ucounts_lock); + return ucounts; + } +@@ -165,13 +167,15 @@ static void put_ucounts(struct ucounts *ucounts) + { + unsigned long flags; + +- if (atomic_dec_and_test(&ucounts->count)) { +- spin_lock_irqsave(&ucounts_lock, flags); ++ spin_lock_irqsave(&ucounts_lock, flags); ++ ucounts->count -= 1; ++ if (!ucounts->count) + hlist_del_init(&ucounts->node); +- spin_unlock_irqrestore(&ucounts_lock, flags); ++ else ++ ucounts = NULL; ++ spin_unlock_irqrestore(&ucounts_lock, flags); + +- kfree(ucounts); +- } ++ kfree(ucounts); + } + + static inline bool atomic_inc_below(atomic_t *v, int u) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-6951/0.patch b/Patches/Linux_CVEs/CVE-2017-6951/0.patch new file mode 100644 index 00000000..a38cafa9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-6951/0.patch @@ -0,0 +1,49 @@ +From 44d6e10f77095133e3882529a16b686b2305e6b0 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 18 Apr 2017 15:31:08 +0100 +Subject: KEYS: Change the name of the dead type to ".dead" to prevent user + access + +commit c1644fe041ebaf6519f6809146a77c3ead9193af upstream. + +This fixes CVE-2017-6951. + +Userspace should not be able to do things with the "dead" key type as it +doesn't have some of the helper functions set upon it that the kernel +needs. Attempting to use it may cause the kernel to crash. + +Fix this by changing the name of the type to ".dead" so that it's rejected +up front on userspace syscalls by key_get_type_from_user(). + +Though this doesn't seem to affect recent kernels, it does affect older +ones, certainly those prior to: + + commit c06cfb08b88dfbe13be44a69ae2fdc3a7c902d81 + Author: David Howells + Date: Tue Sep 16 17:36:06 2014 +0100 + KEYS: Remove key_type::match in favour of overriding default by match_preparse + +which went in before 3.18-rc1. + +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/gc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/keys/gc.c b/security/keys/gc.c +index addf060..9cb4fe4 100644 +--- a/security/keys/gc.c ++++ b/security/keys/gc.c +@@ -46,7 +46,7 @@ static unsigned long key_gc_flags; + * immediately unlinked. + */ + struct key_type key_type_dead = { +- .name = "dead", ++ .name = ".dead", + }; + + /* +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7184/0.patch b/Patches/Linux_CVEs/CVE-2017-7184/0.patch new file mode 100644 index 00000000..f07a8bf6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7184/0.patch @@ -0,0 +1,48 @@ +From 677e806da4d916052585301785d847c3b3e6186a Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Wed, 22 Mar 2017 07:29:31 +0000 +Subject: xfrm_user: validate XFRM_MSG_NEWAE XFRMA_REPLAY_ESN_VAL replay_window + +When a new xfrm state is created during an XFRM_MSG_NEWSA call we +validate the user supplied replay_esn to ensure that the size is valid +and to ensure that the replay_window size is within the allocated +buffer. However later it is possible to update this replay_esn via a +XFRM_MSG_NEWAE call. There we again validate the size of the supplied +buffer matches the existing state and if so inject the contents. We do +not at this point check that the replay_window is within the allocated +memory. This leads to out-of-bounds reads and writes triggered by +netlink packets. This leads to memory corruption and the potential for +priviledge escalation. + +We already attempt to validate the incoming replay information in +xfrm_new_ae() via xfrm_replay_verify_len(). This confirms that the user +is not trying to change the size of the replay state buffer which +includes the replay_esn. It however does not check the replay_window +remains within that buffer. Add validation of the contained +replay_window. + +CVE-2017-7184 +Signed-off-by: Andy Whitcroft +Acked-by: Steffen Klassert +Signed-off-by: Linus Torvalds +--- + net/xfrm/xfrm_user.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 9705c27..cdf887f 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -415,6 +415,9 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es + if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) + return -EINVAL; + ++ if (up->replay_window > up->bmp_len * sizeof(__u32) * 8) ++ return -EINVAL; ++ + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7184/1.patch b/Patches/Linux_CVEs/CVE-2017-7184/1.patch new file mode 100644 index 00000000..d484354e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7184/1.patch @@ -0,0 +1,38 @@ +From f843ee6dd019bcece3e74e76ad9df0155655d0df Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 23 Mar 2017 07:45:44 +0000 +Subject: xfrm_user: validate XFRM_MSG_NEWAE incoming ESN size harder + +Kees Cook has pointed out that xfrm_replay_state_esn_len() is subject to +wrapping issues. To ensure we are correctly ensuring that the two ESN +structures are the same size compare both the overall size as reported +by xfrm_replay_state_esn_len() and the internal length are the same. + +CVE-2017-7184 +Signed-off-by: Andy Whitcroft +Acked-by: Steffen Klassert +Signed-off-by: Linus Torvalds +--- + net/xfrm/xfrm_user.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index cdf887f..40a8aa3 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -412,7 +412,11 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es + up = nla_data(rp); + ulen = xfrm_replay_state_esn_len(up); + +- if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) ++ /* Check the overall length and the internal bitmap length to avoid ++ * potential overflow. */ ++ if (nla_len(rp) < ulen || ++ xfrm_replay_state_esn_len(replay_esn) != ulen || ++ replay_esn->bmp_len != up->bmp_len) + return -EINVAL; + + if (up->replay_window > up->bmp_len * sizeof(__u32) * 8) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7187/0.patch b/Patches/Linux_CVEs/CVE-2017-7187/0.patch new file mode 100644 index 00000000..447ba969 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7187/0.patch @@ -0,0 +1,54 @@ + + + +kernel/git/torvalds/linux.git - Linux kernel source tree + + + + + + + + + + +
      + + + + +
      +aboutsummaryrefslogtreecommitdiffstats
      + + + +
      +
      +
      diff options
      context:
      space:
      mode:
      + + + + +
      authorpeter chang <dpf@google.com>2017-02-15 14:11:54 -0800
      committerMartin K. Petersen <martin.petersen@oracle.com>2017-03-16 19:46:33 -0400
      commitbf33f87dd04c371ea33feb821b60d63d754e3124 (patch)
      tree4207379ccff4dd625ff04a3cbc44fddfe819fac9
      parent645b8ef5943f95b74240568105ce2be21c6640b4 (diff)
      downloadlinux-bf33f87dd04c371ea33feb821b60d63d754e3124.tar.gz
      +
      scsi: sg: check length passed to SG_NEXT_CMD_LEN
      The user can control the size of the next command passed along, but the +value passed to the ioctl isn't checked against the usable max command +size. + +Cc: <stable@vger.kernel.org> +Signed-off-by: Peter Chang <dpf@google.com> +Acked-by: Douglas Gilbert <dgilbert@interlog.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +
      +
      -rw-r--r--drivers/scsi/sg.c2
      1 files changed, 2 insertions, 0 deletions
      diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
      index e831e01..849ff810 100644
      --- a/drivers/scsi/sg.c
      +++ b/drivers/scsi/sg.c
      @@ -996,6 +996,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
      result = get_user(val, ip);
      if (result)
      return result;
      + if (val > SG_MAX_CDB_SIZE)
      + return -ENOMEM;
      sfp->next_cmd_len = (val > 0) ? val : 0;
      return 0;
      case SG_GET_VERSION_NUM:
      + +
      + + diff --git a/Patches/Linux_CVEs/CVE-2017-7277/0.patch b/Patches/Linux_CVEs/CVE-2017-7277/0.patch new file mode 100644 index 00000000..9d45f459 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7277/0.patch @@ -0,0 +1,121 @@ +From 4ef1b2869447411ad3ef91ad7d4891a83c1a509a Mon Sep 17 00:00:00 2001 +From: Soheil Hassas Yeganeh +Date: Sat, 18 Mar 2017 17:03:00 -0400 +Subject: tcp: mark skbs with SCM_TIMESTAMPING_OPT_STATS + +SOF_TIMESTAMPING_OPT_STATS can be enabled and disabled +while packets are collected on the error queue. +So, checking SOF_TIMESTAMPING_OPT_STATS in sk->sk_tsflags +is not enough to safely assume that the skb contains +OPT_STATS data. + +Add a bit in sock_exterr_skb to indicate whether the +skb contains opt_stats data. + +Fixes: 1c885808e456 ("tcp: SOF_TIMESTAMPING_OPT_STATS option for SO_TIMESTAMPING") +Reported-by: JongHwan Kim +Signed-off-by: Soheil Hassas Yeganeh +Signed-off-by: Eric Dumazet +Signed-off-by: Willem de Bruijn +Signed-off-by: David S. Miller +--- + include/linux/errqueue.h | 2 ++ + net/core/skbuff.c | 17 +++++++++++------ + net/socket.c | 2 +- + 3 files changed, 14 insertions(+), 7 deletions(-) + +diff --git a/include/linux/errqueue.h b/include/linux/errqueue.h +index 9ca23fc..6fdfc88 100644 +--- a/include/linux/errqueue.h ++++ b/include/linux/errqueue.h +@@ -20,6 +20,8 @@ struct sock_exterr_skb { + struct sock_extended_err ee; + u16 addr_offset; + __be16 port; ++ u8 opt_stats:1, ++ unused:7; + }; + + #endif +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index b1fbd19..9f78109 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -3793,16 +3793,20 @@ EXPORT_SYMBOL(skb_clone_sk); + + static void __skb_complete_tx_timestamp(struct sk_buff *skb, + struct sock *sk, +- int tstype) ++ int tstype, ++ bool opt_stats) + { + struct sock_exterr_skb *serr; + int err; + ++ BUILD_BUG_ON(sizeof(struct sock_exterr_skb) > sizeof(skb->cb)); ++ + serr = SKB_EXT_ERR(skb); + memset(serr, 0, sizeof(*serr)); + serr->ee.ee_errno = ENOMSG; + serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; + serr->ee.ee_info = tstype; ++ serr->opt_stats = opt_stats; + if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { + serr->ee.ee_data = skb_shinfo(skb)->tskey; + if (sk->sk_protocol == IPPROTO_TCP && +@@ -3843,7 +3847,7 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, + */ + if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { + *skb_hwtstamps(skb) = *hwtstamps; +- __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); ++ __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND, false); + sock_put(sk); + } + } +@@ -3854,7 +3858,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, + struct sock *sk, int tstype) + { + struct sk_buff *skb; +- bool tsonly; ++ bool tsonly, opt_stats = false; + + if (!sk) + return; +@@ -3867,9 +3871,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, + #ifdef CONFIG_INET + if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) && + sk->sk_protocol == IPPROTO_TCP && +- sk->sk_type == SOCK_STREAM) ++ sk->sk_type == SOCK_STREAM) { + skb = tcp_get_timestamping_opt_stats(sk); +- else ++ opt_stats = true; ++ } else + #endif + skb = alloc_skb(0, GFP_ATOMIC); + } else { +@@ -3888,7 +3893,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, + else + skb->tstamp = ktime_get_real(); + +- __skb_complete_tx_timestamp(skb, sk, tstype); ++ __skb_complete_tx_timestamp(skb, sk, tstype, opt_stats); + } + EXPORT_SYMBOL_GPL(__skb_tstamp_tx); + +diff --git a/net/socket.c b/net/socket.c +index 692d698..985ef06 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -706,7 +706,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, + SCM_TIMESTAMPING, sizeof(tss), &tss); + + if (skb_is_err_queue(skb) && skb->len && +- (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS)) ++ SKB_EXT_ERR(skb)->opt_stats) + put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, + skb->len, skb->data); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7277/1.patch b/Patches/Linux_CVEs/CVE-2017-7277/1.patch new file mode 100644 index 00000000..85f41260 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7277/1.patch @@ -0,0 +1,95 @@ +From 8605330aac5a5785630aec8f64378a54891937cc Mon Sep 17 00:00:00 2001 +From: Soheil Hassas Yeganeh +Date: Sat, 18 Mar 2017 17:02:59 -0400 +Subject: tcp: fix SCM_TIMESTAMPING_OPT_STATS for normal skbs + +__sock_recv_timestamp can be called for both normal skbs (for +receive timestamps) and for skbs on the error queue (for transmit +timestamps). + +Commit 1c885808e456 +(tcp: SOF_TIMESTAMPING_OPT_STATS option for SO_TIMESTAMPING) +assumes any skb passed to __sock_recv_timestamp are from +the error queue, containing OPT_STATS in the content of the skb. +This results in accessing invalid memory or generating junk +data. + +To fix this, set skb->pkt_type to PACKET_OUTGOING for packets +on the error queue. This is safe because on the receive path +on local sockets skb->pkt_type is never set to PACKET_OUTGOING. +With that, copy OPT_STATS from a packet, only if its pkt_type +is PACKET_OUTGOING. + +Fixes: 1c885808e456 ("tcp: SOF_TIMESTAMPING_OPT_STATS option for SO_TIMESTAMPING") +Reported-by: JongHwan Kim +Signed-off-by: Soheil Hassas Yeganeh +Signed-off-by: Eric Dumazet +Signed-off-by: Willem de Bruijn +Signed-off-by: David S. Miller +--- + net/core/skbuff.c | 10 ++++++++++ + net/socket.c | 13 ++++++++++++- + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index cd4ba8c..b1fbd19 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -3694,6 +3694,15 @@ static void sock_rmem_free(struct sk_buff *skb) + atomic_sub(skb->truesize, &sk->sk_rmem_alloc); + } + ++static void skb_set_err_queue(struct sk_buff *skb) ++{ ++ /* pkt_type of skbs received on local sockets is never PACKET_OUTGOING. ++ * So, it is safe to (mis)use it to mark skbs on the error queue. ++ */ ++ skb->pkt_type = PACKET_OUTGOING; ++ BUILD_BUG_ON(PACKET_OUTGOING == 0); ++} ++ + /* + * Note: We dont mem charge error packets (no sk_forward_alloc changes) + */ +@@ -3707,6 +3716,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) + skb->sk = sk; + skb->destructor = sock_rmem_free; + atomic_add(skb->truesize, &sk->sk_rmem_alloc); ++ skb_set_err_queue(skb); + + /* before exiting rcu section, make sure dst is refcounted */ + skb_dst_force(skb); +diff --git a/net/socket.c b/net/socket.c +index e034fe4..692d698 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -652,6 +652,16 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, + } + EXPORT_SYMBOL(kernel_sendmsg); + ++static bool skb_is_err_queue(const struct sk_buff *skb) ++{ ++ /* pkt_type of skbs enqueued on the error queue are set to ++ * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do ++ * in recvmsg, since skbs received on a local socket will never ++ * have a pkt_type of PACKET_OUTGOING. ++ */ ++ return skb->pkt_type == PACKET_OUTGOING; ++} ++ + /* + * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) + */ +@@ -695,7 +705,8 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, + put_cmsg(msg, SOL_SOCKET, + SCM_TIMESTAMPING, sizeof(tss), &tss); + +- if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS)) ++ if (skb_is_err_queue(skb) && skb->len && ++ (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS)) + put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, + skb->len, skb->data); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7364/0.patch b/Patches/Linux_CVEs/CVE-2017-7364/0.patch new file mode 100644 index 00000000..be2c9551 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7364/0.patch @@ -0,0 +1,49 @@ +From 3ce6c47d2142fcd2c4c1181afe08630aaae5a267 Mon Sep 17 00:00:00 2001 +From: Harsh Sahu +Date: Thu, 16 Feb 2017 19:52:02 -0800 +Subject: msm : mdss: Avoid arbitrary free of scale_data in error condition + +In mdss_fb_copy_destscaler_data function when the code enters error +section it may free up some arbitrary kernel address. This may +generate security vulnerability. Hence fixed the loop condition in +err: to real count of allocated buffer to avoid this arbitrary free. + +Change-Id: I4014a3bf9cb0f5da994fa5c0233b7940009be0cd +Signed-off-by: Harsh Sahu +--- + drivers/video/fbdev/msm/mdss_fb.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c +index a183fd7..5eab4a5 100644 +--- a/drivers/video/fbdev/msm/mdss_fb.c ++++ b/drivers/video/fbdev/msm/mdss_fb.c +@@ -4471,7 +4471,7 @@ err: + static int __mdss_fb_copy_destscaler_data(struct fb_info *info, + struct mdp_layer_commit *commit) + { +- int i; ++ int i = 0; + int ret = 0; + u32 data_size; + struct mdp_destination_scaler_data __user *ds_data_user; +@@ -4544,6 +4544,7 @@ static int __mdss_fb_copy_destscaler_data(struct fb_info *info, + data_size); + if (ret) { + pr_err("scale data copy from user failed\n"); ++ kfree(scale_data); + goto err; + } + } +@@ -4553,7 +4554,7 @@ static int __mdss_fb_copy_destscaler_data(struct fb_info *info, + + err: + if (ds_data) { +- for (i = 0; i < commit->commit_v1.dest_scaler_cnt; i++) { ++ for (i--; i >= 0; i--) { + scale_data = to_user_ptr(ds_data[i].scale); + kfree(scale_data); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7366/0.patch b/Patches/Linux_CVEs/CVE-2017-7366/0.patch new file mode 100644 index 00000000..2bf4e77c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7366/0.patch @@ -0,0 +1,457 @@ +From f4c9ffd6cd7960265f38e285ac43cbecf2459e45 Mon Sep 17 00:00:00 2001 +From: Jordan Crouse +Date: Tue, 31 May 2016 11:24:23 -0600 +Subject: msm: kgsl: Fix pagetable member of struct kgsl_memdesc + +memdesc->pagetable is supposed to help ensure that memory gets +unmapped before it is freed, but the pagetable member is being +populated at create time not when the buffer gets mapped. This +forces the developer to ensure that the same pagetable is +used for both the create and map step. Instead, assign the +pagetable member when it is first used (to get a GPU address) +and put it away when the GPU address is released. + +Change-Id: Ic0dedbad372fd9029b932dd99633a650049751ed +Signed-off-by: Jordan Crouse +Signed-off-by: Sudeep Yedalapure +--- + drivers/gpu/msm/adreno_a5xx.c | 4 ++-- + drivers/gpu/msm/kgsl.c | 33 +++++++-------------------------- + drivers/gpu/msm/kgsl_iommu.c | 35 +++++++++++++++++++---------------- + drivers/gpu/msm/kgsl_mmu.c | 29 +++++++++++++++++++++++------ + drivers/gpu/msm/kgsl_mmu.h | 7 +++---- + drivers/gpu/msm/kgsl_sharedmem.c | 27 ++++++++------------------- + drivers/gpu/msm/kgsl_sharedmem.h | 11 ++++------- + 7 files changed, 66 insertions(+), 80 deletions(-) + +diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c +index f770972..bcef03e 100644 +--- a/drivers/gpu/msm/adreno_a5xx.c ++++ b/drivers/gpu/msm/adreno_a5xx.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The 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 +@@ -250,7 +250,7 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev) + return ret; + + ret = kgsl_allocate_user(&adreno_dev->dev, &crit_pkts_refbuf0, +- NULL, PAGE_SIZE, KGSL_MEMFLAGS_SECURE); ++ PAGE_SIZE, KGSL_MEMFLAGS_SECURE); + if (ret) + return ret; + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index d06eebb..bd022f1 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2008-2017, The 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 +@@ -370,24 +370,6 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, + return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc); + } + +-/** +- * kgsl_mem_entry_untrack_gpuaddr() - Untrack memory that is previously tracked +- * process - Pointer to process private to which memory belongs +- * entry - Memory entry to untrack +- * +- * Function just does the opposite of kgsl_mem_entry_track_gpuaddr. Needs to be +- * called with processes spin lock held +- */ +-static void +-kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, +- struct kgsl_mem_entry *entry) +-{ +- struct kgsl_pagetable *pagetable = entry->memdesc.pagetable; +- +- if (entry->memdesc.gpuaddr) +- kgsl_mmu_put_gpuaddr(pagetable, &entry->memdesc); +-} +- + /* Commit the entry to the process so it can be accessed by other operations */ + static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry) + { +@@ -436,7 +418,7 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, + + if (id < 0) { + ret = id; +- kgsl_mem_entry_untrack_gpuaddr(process, entry); ++ kgsl_mmu_put_gpuaddr(&entry->memdesc); + goto err_put_proc_priv; + } + +@@ -472,6 +454,7 @@ err_put_proc_priv: + static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) + { + unsigned int type; ++ + if (entry == NULL) + return; + +@@ -488,9 +471,7 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) + entry->priv->stats[type].cur -= entry->memdesc.size; + spin_unlock(&entry->priv->mem_lock); + +- kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc); +- +- kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry); ++ kgsl_mmu_put_gpuaddr(&entry->memdesc); + + kgsl_process_private_put(entry->priv); + +@@ -3021,7 +3002,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( + entry->memdesc.priv |= KGSL_MEMDESC_SECURE; + + ret = kgsl_allocate_user(dev_priv->device, &entry->memdesc, +- private->pagetable, size, flags); ++ size, flags); + if (ret != 0) + goto err; + +@@ -3442,11 +3423,11 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private, + return ret; + + entry->memdesc.gpuaddr = (uint64_t) addr; ++ entry->memdesc.pagetable = private->pagetable; + + ret = kgsl_mmu_map(private->pagetable, &entry->memdesc); + if (ret) { +- kgsl_mmu_put_gpuaddr(private->pagetable, +- &entry->memdesc); ++ kgsl_mmu_put_gpuaddr(&entry->memdesc); + return ret; + } + +diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c +index 0d207494c..724d129 100644 +--- a/drivers/gpu/msm/kgsl_iommu.c ++++ b/drivers/gpu/msm/kgsl_iommu.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2017, The 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 +@@ -1402,17 +1402,16 @@ static int _setstate_alloc(struct kgsl_device *device, + { + int ret; + +- ret = kgsl_sharedmem_alloc_contig(device, &iommu->setstate, NULL, +- PAGE_SIZE); +- if (ret) +- return ret; ++ ret = kgsl_sharedmem_alloc_contig(device, &iommu->setstate, PAGE_SIZE); + +- /* Mark the setstate memory as read only */ +- iommu->setstate.flags |= KGSL_MEMFLAGS_GPUREADONLY; ++ if (!ret) { ++ /* Mark the setstate memory as read only */ ++ iommu->setstate.flags |= KGSL_MEMFLAGS_GPUREADONLY; + +- kgsl_sharedmem_set(device, &iommu->setstate, 0, 0, PAGE_SIZE); ++ kgsl_sharedmem_set(device, &iommu->setstate, 0, 0, PAGE_SIZE); ++ } + +- return 0; ++ return ret; + } + + static int kgsl_iommu_init(struct kgsl_mmu *mmu) +@@ -1663,7 +1662,7 @@ static int _iommu_map_guard_page(struct kgsl_pagetable *pt, + + if (!kgsl_secure_guard_page_memdesc.sgt) { + if (kgsl_allocate_user(KGSL_MMU_DEVICE(pt->mmu), +- &kgsl_secure_guard_page_memdesc, pt, ++ &kgsl_secure_guard_page_memdesc, + sgp_size, KGSL_MEMFLAGS_SECURE)) { + KGSL_CORE_ERR( + "Secure guard page alloc failed\n"); +@@ -2264,23 +2263,27 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable, + } + + ret = _insert_gpuaddr(pagetable, addr, size); +- if (ret == 0) ++ if (ret == 0) { + memdesc->gpuaddr = addr; ++ memdesc->pagetable = pagetable; ++ } + + out: + spin_unlock(&pagetable->lock); + return ret; + } + +-static void kgsl_iommu_put_gpuaddr(struct kgsl_pagetable *pagetable, +- struct kgsl_memdesc *memdesc) ++static void kgsl_iommu_put_gpuaddr(struct kgsl_memdesc *memdesc) + { +- spin_lock(&pagetable->lock); ++ if (memdesc->pagetable == NULL) ++ return; ++ ++ spin_lock(&memdesc->pagetable->lock); + +- if (_remove_gpuaddr(pagetable, memdesc->gpuaddr)) ++ if (_remove_gpuaddr(memdesc->pagetable, memdesc->gpuaddr)) + BUG(); + +- spin_unlock(&pagetable->lock); ++ spin_unlock(&memdesc->pagetable->lock); + } + + static int kgsl_iommu_svm_range(struct kgsl_pagetable *pagetable, +diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c +index d0c5dc7..99dff79 100644 +--- a/drivers/gpu/msm/kgsl_mmu.c ++++ b/drivers/gpu/msm/kgsl_mmu.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2002,2007-2017, The 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 +@@ -419,17 +419,29 @@ EXPORT_SYMBOL(kgsl_mmu_map); + * @pagetable: Pagetable to release the memory from + * @memdesc: Memory descriptor containing the GPU address to free + */ +-void kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable, +- struct kgsl_memdesc *memdesc) ++void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc) + { ++ struct kgsl_pagetable *pagetable = memdesc->pagetable; ++ int unmap_fail = 0; ++ + if (memdesc->size == 0 || memdesc->gpuaddr == 0) + return; + +- if (PT_OP_VALID(pagetable, put_gpuaddr)) +- pagetable->pt_ops->put_gpuaddr(pagetable, memdesc); ++ if (!kgsl_memdesc_is_global(memdesc)) ++ unmap_fail = kgsl_mmu_unmap(pagetable, memdesc); ++ ++ /* ++ * Do not free the gpuaddr/size if unmap fails. Because if we ++ * try to map this range in future, the iommu driver will throw ++ * a BUG_ON() because it feels we are overwriting a mapping. ++ */ ++ if (PT_OP_VALID(pagetable, put_gpuaddr) && (unmap_fail == 0)) ++ pagetable->pt_ops->put_gpuaddr(memdesc); + + if (!kgsl_memdesc_is_global(memdesc)) + memdesc->gpuaddr = 0; ++ ++ memdesc->pagetable = NULL; + } + EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr); + +@@ -580,7 +592,12 @@ static int nommu_get_gpuaddr(struct kgsl_pagetable *pagetable, + + memdesc->gpuaddr = (uint64_t) sg_phys(memdesc->sgt->sgl); + +- return memdesc->gpuaddr != 0 ? 0 : -ENOMEM; ++ if (memdesc->gpuaddr) { ++ memdesc->pagetable = pagetable; ++ return 0; ++ } ++ ++ return -ENOMEM; + } + + static struct kgsl_mmu_pt_ops nommu_pt_ops = { +diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h +index 93b1f9d..d191b1c 100644 +--- a/drivers/gpu/msm/kgsl_mmu.h ++++ b/drivers/gpu/msm/kgsl_mmu.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2002,2007-2017, The 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 +@@ -92,7 +92,7 @@ struct kgsl_mmu_pt_ops { + u64 (*get_ttbr0)(struct kgsl_pagetable *); + u32 (*get_contextidr)(struct kgsl_pagetable *); + int (*get_gpuaddr)(struct kgsl_pagetable *, struct kgsl_memdesc *); +- void (*put_gpuaddr)(struct kgsl_pagetable *, struct kgsl_memdesc *); ++ void (*put_gpuaddr)(struct kgsl_memdesc *); + uint64_t (*find_svm_region)(struct kgsl_pagetable *, uint64_t, uint64_t, + uint64_t, uint64_t); + int (*set_svm_region)(struct kgsl_pagetable *, uint64_t, uint64_t); +@@ -180,8 +180,7 @@ int kgsl_mmu_map(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc); + int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc); +-void kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable, +- struct kgsl_memdesc *memdesc); ++void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc); + unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr); + unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, + u64 ttbr0, uint64_t addr); +diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c +index 941e4c4..7d7fec7 100644 +--- a/drivers/gpu/msm/kgsl_sharedmem.c ++++ b/drivers/gpu/msm/kgsl_sharedmem.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2002,2007-2017, The 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 +@@ -318,12 +318,11 @@ static int kgsl_cma_alloc_secure(struct kgsl_device *device, + + static int kgsl_allocate_secure(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, +- struct kgsl_pagetable *pagetable, + uint64_t size) { + int ret; + + if (MMU_FEATURE(&device->mmu, KGSL_MMU_HYP_SECURE_ALLOC)) +- ret = kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size); ++ ret = kgsl_sharedmem_page_alloc_user(memdesc, size); + else + ret = kgsl_cma_alloc_secure(device, memdesc, size); + +@@ -332,7 +331,6 @@ static int kgsl_allocate_secure(struct kgsl_device *device, + + int kgsl_allocate_user(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, +- struct kgsl_pagetable *pagetable, + uint64_t size, uint64_t flags) + { + int ret; +@@ -340,12 +338,11 @@ int kgsl_allocate_user(struct kgsl_device *device, + memdesc->flags = flags; + + if (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_NONE) +- ret = kgsl_sharedmem_alloc_contig(device, memdesc, +- pagetable, size); ++ ret = kgsl_sharedmem_alloc_contig(device, memdesc, size); + else if (flags & KGSL_MEMFLAGS_SECURE) +- ret = kgsl_allocate_secure(device, memdesc, pagetable, size); ++ ret = kgsl_allocate_secure(device, memdesc, size); + else +- ret = kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size); ++ ret = kgsl_sharedmem_page_alloc_user(memdesc, size); + + return ret; + } +@@ -637,7 +634,6 @@ static inline int get_page_size(size_t size, unsigned int align) + + int + kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, +- struct kgsl_pagetable *pagetable, + uint64_t size) + { + int ret = 0; +@@ -671,7 +667,6 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, + + len_alloc = PAGE_ALIGN(size) >> PAGE_SHIFT; + +- memdesc->pagetable = pagetable; + memdesc->ops = &kgsl_page_alloc_ops; + + /* +@@ -805,10 +800,8 @@ void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc) + if (memdesc == NULL || memdesc->size == 0) + return; + +- if (memdesc->gpuaddr) { +- kgsl_mmu_unmap(memdesc->pagetable, memdesc); +- kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc); +- } ++ /* Make sure the memory object has been unmapped */ ++ kgsl_mmu_put_gpuaddr(memdesc); + + if (memdesc->ops && memdesc->ops->free) + memdesc->ops->free(memdesc); +@@ -988,8 +981,7 @@ void kgsl_get_memory_usage(char *name, size_t name_size, uint64_t memflags) + EXPORT_SYMBOL(kgsl_get_memory_usage); + + int kgsl_sharedmem_alloc_contig(struct kgsl_device *device, +- struct kgsl_memdesc *memdesc, +- struct kgsl_pagetable *pagetable, uint64_t size) ++ struct kgsl_memdesc *memdesc, uint64_t size) + { + int result = 0; + +@@ -998,7 +990,6 @@ int kgsl_sharedmem_alloc_contig(struct kgsl_device *device, + return -EINVAL; + + memdesc->size = size; +- memdesc->pagetable = pagetable; + memdesc->ops = &kgsl_cma_ops; + memdesc->dev = device->dev->parent; + +@@ -1089,7 +1080,6 @@ static int kgsl_cma_alloc_secure(struct kgsl_device *device, + { + struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device); + int result = 0; +- struct kgsl_pagetable *pagetable = device->mmu.securepagetable; + size_t aligned; + + /* Align size to 1M boundaries */ +@@ -1109,7 +1099,6 @@ static int kgsl_cma_alloc_secure(struct kgsl_device *device, + memdesc->priv &= ~KGSL_MEMDESC_GUARD_PAGE; + + memdesc->size = aligned; +- memdesc->pagetable = pagetable; + memdesc->ops = &kgsl_cma_ops; + memdesc->dev = iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE].dev; + +diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h +index aae79ad..19477f5 100644 +--- a/drivers/gpu/msm/kgsl_sharedmem.h ++++ b/drivers/gpu/msm/kgsl_sharedmem.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2002,2007-2017, The 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 +@@ -26,7 +26,7 @@ struct kgsl_process_private; + + int kgsl_sharedmem_alloc_contig(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, +- struct kgsl_pagetable *pagetable, uint64_t size); ++ uint64_t size); + + void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc); + +@@ -66,13 +66,11 @@ void kgsl_sharedmem_uninit_sysfs(void); + + int kgsl_allocate_user(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, +- struct kgsl_pagetable *pagetable, + uint64_t size, uint64_t flags); + + void kgsl_get_memory_usage(char *str, size_t len, uint64_t memflags); + + int kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, +- struct kgsl_pagetable *pagetable, + uint64_t size); + + #define MEMFLAGS(_flags, _mask, _shift) \ +@@ -271,11 +269,10 @@ static inline int kgsl_allocate_global(struct kgsl_device *device, + memdesc->priv = priv; + + if ((memdesc->priv & KGSL_MEMDESC_CONTIG) != 0) +- ret = kgsl_sharedmem_alloc_contig(device, memdesc, NULL, ++ ret = kgsl_sharedmem_alloc_contig(device, memdesc, + (size_t) size); + else { +- ret = kgsl_sharedmem_page_alloc_user(memdesc, NULL, +- (size_t) size); ++ ret = kgsl_sharedmem_page_alloc_user(memdesc, (size_t) size); + if (ret == 0) + kgsl_memdesc_map(memdesc); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7366/1.patch b/Patches/Linux_CVEs/CVE-2017-7366/1.patch new file mode 100644 index 00000000..4b2c8a54 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7366/1.patch @@ -0,0 +1,254 @@ +From 7c4d5736d32f91f0cafe6cd86d00e26389970b00 Mon Sep 17 00:00:00 2001 +From: Jordan Crouse +Date: Tue, 31 May 2016 11:24:24 -0600 +Subject: msm: kgsl: Make sure USE_CPU_MAP + MAP_USER_MEM work together + +If one is mapping anonyomous user memory in the GPU with SVM enabled +we want to try to accommodate that request if possible. The memory +address was being set up correctly in the memory descriptor but +the GPU address was getting tripped up when getting mapped in the +process. This is because the memory should be treated like SVM +memory so it needs to be registered in the memory tree and the +rest of the path needs to accept the address. + +Change-Id: Ic0dedbad661143977a226d50263c26b5af579ce3 +Signed-off-by: Jordan Crouse +Signed-off-by: Sudeep Yedalapure +--- + drivers/gpu/msm/kgsl.c | 134 +++++++++++++++++++++---------------------------- + 1 file changed, 57 insertions(+), 77 deletions(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index bd022f1..db3ba02 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -166,9 +166,10 @@ int kgsl_memfree_find_entry(pid_t ptname, uint64_t *gpuaddr, + return 0; + } + +-static void kgsl_memfree_purge(pid_t ptname, uint64_t gpuaddr, +- uint64_t size) ++static void kgsl_memfree_purge(struct kgsl_pagetable *pagetable, ++ uint64_t gpuaddr, uint64_t size) + { ++ pid_t ptname = pagetable ? pagetable->name : 0; + int i; + + if (memfree.list == NULL) +@@ -332,40 +333,22 @@ kgsl_mem_entry_destroy(struct kref *kref) + } + EXPORT_SYMBOL(kgsl_mem_entry_destroy); + +-/** +- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and +- * assign it with a gpu address space before insertion +- * @process: the process that owns the memory +- * @entry: the memory entry +- * +- * @returns - 0 on succcess else error code +- * +- * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address. +- * The assignment of gpu address and insertion into list needs to +- * happen with the memory lock held to avoid race conditions between +- * gpu address being selected and some other thread looking through the +- * rb list in search of memory based on gpuaddr +- * This function should be called with processes memory spinlock held +- */ +-static int +-kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, +- struct kgsl_mem_entry *entry) ++/* Allocate a IOVA for memory objects that don't use SVM */ ++static int kgsl_mem_entry_track_gpuaddr(struct kgsl_device *device, ++ struct kgsl_process_private *process, ++ struct kgsl_mem_entry *entry) + { +- struct kgsl_pagetable *pagetable = process->pagetable; ++ struct kgsl_pagetable *pagetable; + + /* +- * If cpu=gpu map is used then caller needs to set the +- * gpu address ++ * If SVM is enabled for this object then the address needs to be ++ * assigned elsewhere + */ +- if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { +- if (!entry->memdesc.gpuaddr) +- return 0; +- } else if (entry->memdesc.gpuaddr) { +- WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n"); +- return -EINVAL; +- } +- if (kgsl_memdesc_is_secured(&entry->memdesc)) +- pagetable = pagetable->mmu->securepagetable; ++ if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) ++ return 0; ++ ++ pagetable = kgsl_memdesc_is_secured(&entry->memdesc) ? ++ device->mmu.securepagetable : process->pagetable; + + return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc); + } +@@ -381,33 +364,25 @@ static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry) + spin_unlock(&entry->priv->mem_lock); + } + +-/** +- * kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process +- * @entry: the memory entry +- * @process: the owner process +- * +- * Attach a newly created mem_entry to its owner process so that +- * it can be found later. The mem_entry will be added to mem_idr and have +- * its 'id' field assigned. +- * +- * @returns - 0 on success or error code on failure. ++/* ++ * Attach the memory object to a process by (possibly) getting a GPU address and ++ * (possibly) mapping it + */ +-int +-kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, +- struct kgsl_device_private *dev_priv) ++static int kgsl_mem_entry_attach_process(struct kgsl_device *device, ++ struct kgsl_process_private *process, ++ struct kgsl_mem_entry *entry) + { +- int id; +- int ret; +- struct kgsl_process_private *process = dev_priv->process_priv; +- struct kgsl_pagetable *pagetable = NULL; ++ int id, ret; + + ret = kgsl_process_private_get(process); + if (!ret) + return -EBADF; + +- ret = kgsl_mem_entry_track_gpuaddr(process, entry); +- if (ret) +- goto err_put_proc_priv; ++ ret = kgsl_mem_entry_track_gpuaddr(device, process, entry); ++ if (ret) { ++ kgsl_process_private_put(process); ++ return ret; ++ } + + idr_preload(GFP_KERNEL); + spin_lock(&process->mem_lock); +@@ -417,40 +392,33 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, + idr_preload_end(); + + if (id < 0) { +- ret = id; +- kgsl_mmu_put_gpuaddr(&entry->memdesc); +- goto err_put_proc_priv; ++ if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) ++ kgsl_mmu_put_gpuaddr(&entry->memdesc); ++ kgsl_process_private_put(process); ++ return id; + } + + entry->id = id; + entry->priv = process; + +- /* map the memory after unlocking if gpuaddr has been assigned */ ++ /* ++ * Map the memory if a GPU address is already assigned, either through ++ * kgsl_mem_entry_track_gpuaddr() or via some other SVM process ++ */ + if (entry->memdesc.gpuaddr) { +- /* if a secured buffer map it to secure global pagetable */ +- if (kgsl_memdesc_is_secured(&entry->memdesc)) +- pagetable = process->pagetable->mmu->securepagetable; +- else +- pagetable = process->pagetable; ++ ret = kgsl_mmu_map(entry->memdesc.pagetable, &entry->memdesc); + +- entry->memdesc.pagetable = pagetable; +- ret = kgsl_mmu_map(pagetable, &entry->memdesc); + if (ret) + kgsl_mem_entry_detach_process(entry); + } + +- kgsl_memfree_purge(pagetable ? pagetable->name : 0, +- entry->memdesc.gpuaddr, entry->memdesc.size); +- +- return ret; ++ kgsl_memfree_purge(entry->memdesc.pagetable, entry->memdesc.gpuaddr, ++ entry->memdesc.size); + +-err_put_proc_priv: +- kgsl_process_private_put(process); + return ret; + } + + /* Detach a memory entry from a process and unmap it from the MMU */ +- + static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) + { + unsigned int type; +@@ -2052,10 +2020,21 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, + entry->memdesc.pagetable = pagetable; + entry->memdesc.size = (uint64_t) size; + entry->memdesc.useraddr = hostptr; +- if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) +- entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr; + entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ADDR; + ++ if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { ++ int ret; ++ ++ /* Register the address in the database */ ++ ret = kgsl_mmu_set_svm_region(pagetable, ++ (uint64_t) entry->memdesc.useraddr, (uint64_t) size); ++ ++ if (ret) ++ return ret; ++ ++ entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr; ++ } ++ + return memdesc_sg_virt(&entry->memdesc, NULL); + } + +@@ -2305,7 +2284,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, + + param->flags = entry->memdesc.flags; + +- ret = kgsl_mem_entry_attach_process(entry, dev_priv); ++ ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); + if (ret) + goto unmap; + +@@ -2609,7 +2588,8 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, + /* echo back flags */ + param->flags = (unsigned int) entry->memdesc.flags; + +- result = kgsl_mem_entry_attach_process(entry, dev_priv); ++ result = kgsl_mem_entry_attach_process(dev_priv->device, private, ++ entry); + if (result) + goto error_attach; + +@@ -3006,7 +2986,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( + if (ret != 0) + goto err; + +- ret = kgsl_mem_entry_attach_process(entry, dev_priv); ++ ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); + if (ret != 0) { + kgsl_sharedmem_free(&entry->memdesc); + goto err; +@@ -3431,8 +3411,8 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private, + return ret; + } + +- kgsl_memfree_purge(private->pagetable ? private->pagetable->name : 0, +- entry->memdesc.gpuaddr, entry->memdesc.size); ++ kgsl_memfree_purge(private->pagetable, entry->memdesc.gpuaddr, ++ entry->memdesc.size); + + return addr; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7368/0.patch b/Patches/Linux_CVEs/CVE-2017-7368/0.patch new file mode 100644 index 00000000..8bcd196c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7368/0.patch @@ -0,0 +1,368 @@ +From 143ef972be1621458930ea3fc1def5ebce7b0c5d Mon Sep 17 00:00:00 2001 +From: Yeleswarapu Nagaradhesh +Date: Tue, 14 Feb 2017 14:27:56 +0530 +Subject: ASoC: msm: acquire lock in ioctl + +If two ioctls are triggered with different commands, +there is a possibility to access freed confidence level +memory. To resolve this acquire lock in ioctl. +Also release mutex lock properly in error cases. + +CRs-Fixed: 1103085 +Change-Id: I7d6b2eff21c8297e5f0755a0c141254be32f777d +Signed-off-by: Yeleswarapu Nagaradhesh +--- + sound/soc/msm/msm-cpe-lsm.c | 1 + + sound/soc/msm/qdsp6v2/msm-lsm-client.c | 93 ++++++++++++++++++++++++---------- + 2 files changed, 68 insertions(+), 26 deletions(-) + +diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c +index 7989a1e..3762e02 100644 +--- a/sound/soc/msm/msm-cpe-lsm.c ++++ b/sound/soc/msm/msm-cpe-lsm.c +@@ -1621,6 +1621,7 @@ static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream, + switch (cmd) { + case SNDRV_LSM_REG_SND_MODEL_V2: { + struct snd_lsm_sound_model_v2 snd_model; ++ + if (copy_from_user(&snd_model, (void *)arg, + sizeof(struct snd_lsm_sound_model_v2))) { + dev_err(rtd->dev, +diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +index d5358e3..62a4e82 100644 +--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c ++++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2017, 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 +@@ -84,6 +84,7 @@ struct lsm_priv { + atomic_t buf_count; + atomic_t read_abort; + wait_queue_head_t period_wait; ++ struct mutex lsm_api_lock; + int appl_cnt; + int dma_write; + }; +@@ -900,10 +901,18 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + case SNDRV_LSM_EVENT_STATUS: + dev_dbg(rtd->dev, "%s: Get event status\n", __func__); + atomic_set(&prtd->event_wait_stop, 0); ++ ++ /* ++ * Release the api lock before wait to allow ++ * other IOCTLs to be invoked while waiting ++ * for event ++ */ ++ mutex_unlock(&prtd->lsm_api_lock); + rc = wait_event_freezable(prtd->event_wait, + (cmpxchg(&prtd->event_avail, 1, 0) || + (xchg = atomic_cmpxchg(&prtd->event_wait_stop, + 1, 0)))); ++ mutex_lock(&prtd->lsm_api_lock); + dev_dbg(rtd->dev, "%s: wait_event_freezable %d event_wait_stop %d\n", + __func__, rc, xchg); + if (!rc && !xchg) { +@@ -1147,6 +1156,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + rtd = substream->private_data; + prtd = runtime->private_data; + ++ mutex_lock(&prtd->lsm_api_lock); ++ + switch (cmd) { + case SNDRV_LSM_EVENT_STATUS: { + struct snd_lsm_event_status *user = NULL, userarg32; +@@ -1154,7 +1165,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + if (copy_from_user(&userarg32, arg, sizeof(userarg32))) { + dev_err(rtd->dev, "%s: err copyuser ioctl %s\n", + __func__, "SNDRV_LSM_EVENT_STATUS"); +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } + + if (userarg32.payload_size > +@@ -1162,7 +1174,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + pr_err("%s: payload_size %d is invalid, max allowed = %d\n", + __func__, userarg32.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + size = sizeof(*user) + userarg32.payload_size; +@@ -1171,7 +1184,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: Allocation failed event status size %d\n", + __func__, size); +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } else { + cmd = SNDRV_LSM_EVENT_STATUS; + user->payload_size = userarg32.payload_size; +@@ -1220,7 +1234,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: %s: not supported if using topology\n", + __func__, "REG_SND_MODEL_V2"); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + if (copy_from_user(&snd_modelv232, arg, +@@ -1261,7 +1276,7 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: %s: not supported if using topology\n", + __func__, "SET_PARAMS_32"); +- return -EINVAL; ++ err = -EINVAL; + } + + if (copy_from_user(&det_params32, arg, +@@ -1304,7 +1319,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: %s: not supported if not using topology\n", + __func__, "SET_MODULE_PARAMS_32"); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + if (copy_from_user(&p_data_32, arg, +@@ -1313,7 +1329,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + "%s: %s: copy_from_user failed, size = %zd\n", + __func__, "SET_MODULE_PARAMS_32", + sizeof(p_data_32)); +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } + + p_data.params = compat_ptr(p_data_32.params); +@@ -1325,7 +1342,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + "%s: %s: Invalid num_params %d\n", + __func__, "SET_MODULE_PARAMS_32", + p_data.num_params); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + if (p_data.data_size != +@@ -1334,7 +1352,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + "%s: %s: Invalid size %d\n", + __func__, "SET_MODULE_PARAMS_32", + p_data.data_size); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + p_size = sizeof(struct lsm_params_info_32) * +@@ -1345,7 +1364,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: no memory for params32, size = %zd\n", + __func__, p_size); +- return -ENOMEM; ++ err = -ENOMEM; ++ goto done; + } + + p_size = sizeof(struct lsm_params_info) * p_data.num_params; +@@ -1355,7 +1375,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + "%s: no memory for params, size = %zd\n", + __func__, p_size); + kfree(params32); +- return -ENOMEM; ++ err = -ENOMEM; ++ goto done; + } + + if (copy_from_user(params32, p_data.params, +@@ -1365,7 +1386,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + __func__, "params32", p_data.data_size); + kfree(params32); + kfree(params); +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } + + p_info_32 = (struct lsm_params_info_32 *) params32; +@@ -1408,6 +1430,8 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + err = msm_lsm_ioctl_shared(substream, cmd, arg); + break; + } ++done: ++ mutex_unlock(&prtd->lsm_api_lock); + return err; + } + #else +@@ -1432,6 +1456,7 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + prtd = runtime->private_data; + rtd = substream->private_data; + ++ mutex_lock(&prtd->lsm_api_lock); + switch (cmd) { + case SNDRV_LSM_REG_SND_MODEL_V2: { + struct snd_lsm_sound_model_v2 snd_model_v2; +@@ -1440,7 +1465,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: %s: not supported if using topology\n", + __func__, "REG_SND_MODEL_V2"); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + if (copy_from_user(&snd_model_v2, arg, sizeof(snd_model_v2))) { +@@ -1467,7 +1493,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: %s: not supported if using topology\n", + __func__, "SET_PARAMS"); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + pr_debug("%s: SNDRV_LSM_SET_PARAMS\n", __func__); +@@ -1488,7 +1515,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: LSM_SET_PARAMS failed, err %d\n", + __func__, err); +- return err; ++ ++ goto done; + } + + case SNDRV_LSM_SET_MODULE_PARAMS: { +@@ -1500,7 +1528,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: %s: not supported if not using topology\n", + __func__, "SET_MODULE_PARAMS"); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + if (copy_from_user(&p_data, arg, +@@ -1508,7 +1537,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: %s: copy_from_user failed, size = %zd\n", + __func__, "p_data", sizeof(p_data)); +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } + + if (p_data.num_params > LSM_PARAMS_MAX) { +@@ -1516,7 +1546,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + "%s: %s: Invalid num_params %d\n", + __func__, "SET_MODULE_PARAMS", + p_data.num_params); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + p_size = p_data.num_params * +@@ -1527,7 +1558,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + "%s: %s: Invalid size %zd\n", + __func__, "SET_MODULE_PARAMS", p_size); + +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } + + params = kzalloc(p_size, GFP_KERNEL); +@@ -1535,7 +1567,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: no memory for params\n", + __func__); +- return -ENOMEM; ++ err = -ENOMEM; ++ goto done; + } + + if (copy_from_user(params, p_data.params, +@@ -1544,7 +1577,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + "%s: %s: copy_from_user failed, size = %d\n", + __func__, "params", p_data.data_size); + kfree(params); +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } + + err = msm_lsm_process_params(substream, &p_data, params); +@@ -1564,7 +1598,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: err copyuser event_status\n", + __func__); +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } + + if (userarg.payload_size > +@@ -1572,7 +1607,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + pr_err("%s: payload_size %d is invalid, max allowed = %d\n", + __func__, userarg.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); +- return -EINVAL; ++ err = -EINVAL; ++ goto done; + } + + size = sizeof(struct snd_lsm_event_status) + +@@ -1582,7 +1618,8 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + dev_err(rtd->dev, + "%s: Allocation failed event status size %d\n", + __func__, size); +- return -EFAULT; ++ err = -EFAULT; ++ goto done; + } else { + user->payload_size = userarg.payload_size; + err = msm_lsm_ioctl_shared(substream, cmd, user); +@@ -1605,12 +1642,14 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + if (err) + dev_err(rtd->dev, + "%s: lsmevent failed %d", __func__, err); +- return err; ++ goto done; + } + default: + err = msm_lsm_ioctl_shared(substream, cmd, arg); + break; + } ++done: ++ mutex_unlock(&prtd->lsm_api_lock); + return err; + } + +@@ -1627,6 +1666,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) + __func__); + return -ENOMEM; + } ++ mutex_init(&prtd->lsm_api_lock); + spin_lock_init(&prtd->event_lock); + init_waitqueue_head(&prtd->event_wait); + init_waitqueue_head(&prtd->period_wait); +@@ -1776,6 +1816,7 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) + kfree(prtd->event_status); + prtd->event_status = NULL; + spin_unlock_irqrestore(&prtd->event_lock, flags); ++ mutex_destroy(&prtd->lsm_api_lock); + kfree(prtd); + runtime->private_data = NULL; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7369/0.patch b/Patches/Linux_CVEs/CVE-2017-7369/0.patch new file mode 100644 index 00000000..46098299 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7369/0.patch @@ -0,0 +1,50 @@ +From 75ed08a822cf378ffed0d2f177d06555bd77a006 Mon Sep 17 00:00:00 2001 +From: Walter Yang +Date: Thu, 2 Mar 2017 12:13:34 +0800 +Subject: ASoC: Add backend user count checking + +Add backend user count checking to protect the index +boundary. + +Change-Id: Ic1b61d1f7130252cc54da0b16553858714988dbd +CRs-Fixed: 2009216 +Signed-off-by: Walter Yang +--- + sound/soc/soc-compress.c | 5 +++++ + sound/soc/soc-pcm.c | 4 ++++ + 2 files changed, 9 insertions(+) + +diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c +index 8902662..3b30818 100644 +--- a/sound/soc/soc-compress.c ++++ b/sound/soc/soc-compress.c +@@ -569,6 +569,11 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, + cstream, &async_domain); + } else { + be_list[j++] = be; ++ if (j == DPCM_MAX_BE_USERS) { ++ dev_dbg(fe->dev, ++ "ASoC: MAX backend users!\n"); ++ break; ++ } + } + } + for (i = 0; i < j; i++) { +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 7e2b2f3..21e503c 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -1851,6 +1851,10 @@ void dpcm_be_dai_prepare_async(struct snd_soc_pcm_runtime *fe, int stream, + dpcm, domain); + } else { + dpcm_async[i++] = dpcm; ++ if (i == DPCM_MAX_BE_USERS) { ++ dev_dbg(fe->dev, "ASoC: MAX backend users!\n"); ++ break; ++ } + } + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7369/1.patch b/Patches/Linux_CVEs/CVE-2017-7369/1.patch new file mode 100644 index 00000000..2af50f01 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7369/1.patch @@ -0,0 +1,50 @@ +From ae8f1d5f60644983aba7fbab469d0e542a187c6e Mon Sep 17 00:00:00 2001 +From: Walter Yang +Date: Thu, 2 Mar 2017 12:13:34 +0800 +Subject: ASoC: Add backend user count checking + +Add backend user count checking to protect the index +boundary. + +Change-Id: Ic1b61d1f7130252cc54da0b16553858714988dbd +CRs-Fixed: 2009216 +Signed-off-by: Walter Yang +--- + sound/soc/soc-compress.c | 5 +++++ + sound/soc/soc-pcm.c | 4 ++++ + 2 files changed, 9 insertions(+) + +diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c +index 832f221f..a56e2e5 100644 +--- a/sound/soc/soc-compress.c ++++ b/sound/soc/soc-compress.c +@@ -533,6 +533,11 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, + cstream, &async_domain); + } else { + be_list[j++] = be; ++ if (j == DPCM_MAX_BE_USERS) { ++ dev_dbg(fe->dev, ++ "ASoC: MAX backend users!\n"); ++ break; ++ } + } + } + for (i = 0; i < j; i++) { +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 6c44757..e6de6ad 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -2320,6 +2320,10 @@ void dpcm_be_dai_prepare_async(struct snd_soc_pcm_runtime *fe, int stream, + dpcm, domain); + } else { + dpcm_async[i++] = dpcm; ++ if (i == DPCM_MAX_BE_USERS) { ++ dev_dbg(fe->dev, "ASoC: MAX backend users!\n"); ++ break; ++ } + } + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7370/0.patch b/Patches/Linux_CVEs/CVE-2017-7370/0.patch new file mode 100644 index 00000000..ca2c40fc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7370/0.patch @@ -0,0 +1,50 @@ +From 970edf007fbe64b094437541a42477d653802d85 Mon Sep 17 00:00:00 2001 +From: Benjamin Chan +Date: Mon, 6 Mar 2017 11:48:27 -0500 +Subject: msm: mdss: Add lock to avoid release of active session in rotator + +Add mutex lock to protect an active rotator session from being closed. +Without the lock, this can happen if a rotator closing IOCTL is +called from a separate thread. + +CRs-Fixed: 2006159 +Change-Id: I927a0c626bdae5ef149e12979ec4befdbac1b7f7 +Signed-off-by: Benjamin Chan +--- + drivers/video/msm/mdss/mdss_rotator.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_rotator.c b/drivers/video/msm/mdss/mdss_rotator.c +index f23a05c..f3c40cf 100644 +--- a/drivers/video/msm/mdss/mdss_rotator.c ++++ b/drivers/video/msm/mdss/mdss_rotator.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The 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 +@@ -2059,10 +2059,12 @@ static int mdss_rotator_config_session(struct mdss_rot_mgr *mgr, + return ret; + } + ++ mutex_lock(&mgr->lock); + perf = mdss_rotator_find_session(private, config.session_id); + if (!perf) { + pr_err("No session with id=%u could be found\n", + config.session_id); ++ mutex_unlock(&mgr->lock); + return -EINVAL; + } + +@@ -2085,6 +2087,7 @@ static int mdss_rotator_config_session(struct mdss_rot_mgr *mgr, + config.output.format); + done: + ATRACE_END(__func__); ++ mutex_unlock(&mgr->lock); + return ret; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7371/0.patch b/Patches/Linux_CVEs/CVE-2017-7371/0.patch new file mode 100644 index 00000000..ddf667fc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7371/0.patch @@ -0,0 +1,45 @@ +From e02e63b8014f7a0a5ea17a5196fb4ef1283fd1fd Mon Sep 17 00:00:00 2001 +From: Sungjun Park +Date: Mon, 23 Jan 2017 13:28:44 -0800 +Subject: bluetooth: Fix free data pointer routine + +Data pointer has been reused after freed it. So, +it has been moved to after using the data pointer +to clean up resource and freed it. + +Change-Id: Ibc94e092134ff1f36e896c679ade7f639254a24d +Signed-off-by: Sungjun Park +--- + drivers/bluetooth/btfm_slim.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c +index a88ae0f..37cc628 100644 +--- a/drivers/bluetooth/btfm_slim.c ++++ b/drivers/bluetooth/btfm_slim.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2017, The 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 +@@ -512,7 +512,6 @@ static int btfm_slim_remove(struct slim_device *slim) + BTFMSLIM_DBG(""); + mutex_destroy(&btfm_slim->io_lock); + mutex_destroy(&btfm_slim->xfer_lock); +- kfree(btfm_slim); + snd_soc_unregister_codec(&slim->dev); + + BTFMSLIM_DBG("slim_remove_device() - btfm_slim->slim_ifd"); +@@ -520,6 +519,8 @@ static int btfm_slim_remove(struct slim_device *slim) + + BTFMSLIM_DBG("slim_remove_device() - btfm_slim->slim_pgd"); + slim_remove_device(slim); ++ ++ kfree(btfm_slim); + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7371/1.patch b/Patches/Linux_CVEs/CVE-2017-7371/1.patch new file mode 100644 index 00000000..19b01e18 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7371/1.patch @@ -0,0 +1,45 @@ +From 9d5a0bc7f6318821fddf9fc0ac9a05e58bb00a6b Mon Sep 17 00:00:00 2001 +From: Sungjun Park +Date: Mon, 23 Jan 2017 13:28:44 -0800 +Subject: bluetooth: Fix free data pointer routine + +Data pointer has been reused after freed it. So, +it has been moved to after using the data pointer +to clean up resource and freed it. + +Change-Id: Ibc94e092134ff1f36e896c679ade7f639254a24d +Signed-off-by: Sungjun Park +--- + drivers/bluetooth/btfm_slim.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c +index 5fb00b9..1c6e256 100644 +--- a/drivers/bluetooth/btfm_slim.c ++++ b/drivers/bluetooth/btfm_slim.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2017, The 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 +@@ -509,7 +509,6 @@ static int btfm_slim_remove(struct slim_device *slim) + BTFMSLIM_DBG(""); + mutex_destroy(&btfm_slim->io_lock); + mutex_destroy(&btfm_slim->xfer_lock); +- kfree(btfm_slim); + snd_soc_unregister_codec(&slim->dev); + + BTFMSLIM_DBG("slim_remove_device() - btfm_slim->slim_ifd"); +@@ -517,6 +516,8 @@ static int btfm_slim_remove(struct slim_device *slim) + + BTFMSLIM_DBG("slim_remove_device() - btfm_slim->slim_pgd"); + slim_remove_device(slim); ++ ++ kfree(btfm_slim); + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7372/0.patch b/Patches/Linux_CVEs/CVE-2017-7372/0.patch new file mode 100644 index 00000000..e13a06c0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7372/0.patch @@ -0,0 +1,127 @@ +From 1806be003731d6d4be55e5b940d14ab772839e13 Mon Sep 17 00:00:00 2001 +From: Rahul Sharma +Date: Thu, 19 Jan 2017 17:01:57 +0530 +Subject: msm: ba: Fix race conditions in debug writes + +Use dynamic allocation for debug buffer instead of static. +This is to avoid race condition which can cause buffer overflows. + +Change-Id: I1b4eecb4280843064712ee3b7b52e23f55ab53c3 +Signed-off-by: Rahul Sharma +--- + drivers/video/msm/ba/msm_ba_debug.c | 58 +++++++++++++++++++++++++------------ + 1 file changed, 39 insertions(+), 19 deletions(-) + +diff --git a/drivers/video/msm/ba/msm_ba_debug.c b/drivers/video/msm/ba/msm_ba_debug.c +index a39a0d3..d41d1ab 100644 +--- a/drivers/video/msm/ba/msm_ba_debug.c ++++ b/drivers/video/msm/ba/msm_ba_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2015,2017 The 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 +@@ -13,7 +13,7 @@ + + #include "msm_ba_debug.h" + +-#define MAX_DBG_BUF_SIZE 4096 ++#define MAX_DBG_BUF_SIZE 1008 + + int msm_ba_debug = BA_ERR | BA_WARN; + int msm_ba_debug_out = BA_OUT_PRINTK; +@@ -24,11 +24,9 @@ struct debug_buffer { + u32 filled_size; + }; + +-static struct debug_buffer dbg_buf; +- + #define INIT_DBG_BUF(__buf) ({ \ +- __buf.curr = __buf.ptr;\ +- __buf.filled_size = 0; \ ++ __buf->curr = __buf->ptr;\ ++ __buf->filled_size = 0; \ + }) + + static int dev_info_open(struct inode *inode, struct file *file) +@@ -58,19 +56,30 @@ static ssize_t dev_info_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) + { + struct msm_ba_dev *dev_ctxt = file->private_data; ++ struct debug_buffer *dbg_buf = NULL; ++ ssize_t size = 0; + + if (!dev_ctxt) { + dprintk(BA_ERR, "Invalid params, dev: 0x%p", dev_ctxt); + return 0; + } ++ ++ dbg_buf = kmalloc(sizeof(struct debug_buffer), GFP_KERNEL); ++ if (NULL == dbg_buf) ++ return 0; ++ + INIT_DBG_BUF(dbg_buf); +- write_str(&dbg_buf, "==============================="); +- write_str(&dbg_buf, "DEV: 0x%p", dev_ctxt); +- write_str(&dbg_buf, "==============================="); +- write_str(&dbg_buf, "state: %d", dev_ctxt->state); ++ write_str(dbg_buf, "==============================="); ++ write_str(dbg_buf, "DEV: 0x%p", dev_ctxt); ++ write_str(dbg_buf, "==============================="); ++ write_str(dbg_buf, "state: %d", dev_ctxt->state); + +- return simple_read_from_buffer(buf, count, ppos, +- dbg_buf.ptr, dbg_buf.filled_size); ++ size = simple_read_from_buffer(buf, count, ppos, ++ dbg_buf->ptr, dbg_buf->filled_size); ++ ++ kfree(dbg_buf); ++ ++ return size; + } + + static const struct file_operations dev_info_fops = { +@@ -155,21 +164,32 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) + { + struct msm_ba_inst *inst = file->private_data; ++ struct debug_buffer *dbg_buf = NULL; ++ ssize_t size = 0; + + if (!inst) { + dprintk(BA_ERR, "Invalid params, dev: %p", inst); + return 0; + } ++ ++ dbg_buf = kmalloc(sizeof(struct debug_buffer), GFP_KERNEL); ++ if (NULL == dbg_buf) ++ return 0; ++ + INIT_DBG_BUF(dbg_buf); +- write_str(&dbg_buf, "==============================="); +- write_str(&dbg_buf, "INSTANCE: %p (%s)", inst, ++ write_str(dbg_buf, "==============================="); ++ write_str(dbg_buf, "INSTANCE: %p (%s)", inst, + "BA device"); +- write_str(&dbg_buf, "==============================="); +- write_str(&dbg_buf, "dev: %p", inst->dev_ctxt); +- write_str(&dbg_buf, "state: %d", inst->state); ++ write_str(dbg_buf, "==============================="); ++ write_str(dbg_buf, "dev: %p", inst->dev_ctxt); ++ write_str(dbg_buf, "state: %d", inst->state); + +- return simple_read_from_buffer(buf, count, ppos, +- dbg_buf.ptr, dbg_buf.filled_size); ++ size = simple_read_from_buffer(buf, count, ppos, ++ dbg_buf->ptr, dbg_buf->filled_size); ++ ++ kfree(dbg_buf); ++ ++ return size; + } + + static const struct file_operations inst_info_fops = { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7373/0.patch b/Patches/Linux_CVEs/CVE-2017-7373/0.patch new file mode 100644 index 00000000..134f7075 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7373/0.patch @@ -0,0 +1,34 @@ +From e5eb0d3aa6fe62ee437a2269a1802b1a72f61b75 Mon Sep 17 00:00:00 2001 +From: Benjamin Chan +Date: Thu, 15 Dec 2016 13:46:42 -0500 +Subject: msm: mdss: Fix invalid dma attachment during fb shutdown + +If DMA attachment fail during fb_mmap, all ION memory will get free. It +is necessary to reset the fbmem and fb_attachemnt pointer to NULL, +otherwise during shutdown will perform another free and causing issue. + +CRs-Fixed: 1090244 +Change-Id: I92affcf2ce039eecfc72b7c191e058f37815c726 +Signed-off-by: Benjamin Chan +--- + drivers/video/fbdev/msm/mdss_fb.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c +index 98ca6c3..152879a 100644 +--- a/drivers/video/fbdev/msm/mdss_fb.c ++++ b/drivers/video/fbdev/msm/mdss_fb.c +@@ -2082,6 +2082,10 @@ err_put: + dma_buf_put(mfd->fbmem_buf); + fb_mmap_failed: + ion_free(mfd->fb_ion_client, mfd->fb_ion_handle); ++ mfd->fb_attachment = NULL; ++ mfd->fb_table = NULL; ++ mfd->fb_ion_handle = NULL; ++ mfd->fbmem_buf = NULL; + return rc; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7373/1.patch b/Patches/Linux_CVEs/CVE-2017-7373/1.patch new file mode 100644 index 00000000..d7b5ea41 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7373/1.patch @@ -0,0 +1,33 @@ +From eac4a77bb71750b02e91508b15c9aaf4fe2b94ae Mon Sep 17 00:00:00 2001 +From: Sachin Bhayare +Date: Fri, 23 Dec 2016 11:22:44 +0530 +Subject: msm: mdss: Fix invalid dma attachment during fb shutdown + +If DMA attachment fail during fb_mmap, all ION memory will get free. It +is necessary to reset the fbmem and fb_attachemnt pointer to NULL, +otherwise during shutdown will perform another free and causing issue. + +CRs-Fixed: 1090244 +Change-Id: I92affcf2ce039eecfc72b7c191e058f37815c726 +Signed-off-by: Benjamin Chan +Signed-off-by: Sachin Bhayare +--- + drivers/video/msm/mdss/mdss_fb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c +index 2e8092d..c2d1441 100644 +--- a/drivers/video/msm/mdss/mdss_fb.c ++++ b/drivers/video/msm/mdss/mdss_fb.c +@@ -1660,6 +1660,8 @@ int mdss_fb_alloc_fb_ion_memory(struct msm_fb_data_type *mfd, size_t fb_size) + + fb_mmap_failed: + ion_free(mfd->fb_ion_client, mfd->fb_ion_handle); ++ mfd->fb_ion_handle = NULL; ++ mfd->fbmem_buf = NULL; + return rc; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7374/0.patch b/Patches/Linux_CVEs/CVE-2017-7374/0.patch new file mode 100644 index 00000000..55e33c63 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7374/0.patch @@ -0,0 +1,251 @@ +From 1b53cf9815bb4744958d41f3795d5d5a1d365e2d Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Tue, 21 Feb 2017 15:07:11 -0800 +Subject: fscrypt: remove broken support for detecting keyring key revocation + +Filesystem encryption ostensibly supported revoking a keyring key that +had been used to "unlock" encrypted files, causing those files to become +"locked" again. This was, however, buggy for several reasons, the most +severe of which was that when key revocation happened to be detected for +an inode, its fscrypt_info was immediately freed, even while other +threads could be using it for encryption or decryption concurrently. +This could be exploited to crash the kernel or worse. + +This patch fixes the use-after-free by removing the code which detects +the keyring key having been revoked, invalidated, or expired. Instead, +an encrypted inode that is "unlocked" now simply remains unlocked until +it is evicted from memory. Note that this is no worse than the case for +block device-level encryption, e.g. dm-crypt, and it still remains +possible for a privileged user to evict unused pages, inodes, and +dentries by running 'sync; echo 3 > /proc/sys/vm/drop_caches', or by +simply unmounting the filesystem. In fact, one of those actions was +already needed anyway for key revocation to work even somewhat sanely. +This change is not expected to break any applications. + +In the future I'd like to implement a real API for fscrypt key +revocation that interacts sanely with ongoing filesystem operations --- +waiting for existing operations to complete and blocking new operations, +and invalidating and sanitizing key material and plaintext from the VFS +caches. But this is a hard problem, and for now this bug must be fixed. + +This bug affected almost all versions of ext4, f2fs, and ubifs +encryption, and it was potentially reachable in any kernel configured +with encryption support (CONFIG_EXT4_ENCRYPTION=y, +CONFIG_EXT4_FS_ENCRYPTION=y, CONFIG_F2FS_FS_ENCRYPTION=y, or +CONFIG_UBIFS_FS_ENCRYPTION=y). Note that older kernels did not use the +shared fs/crypto/ code, but due to the potential security implications +of this bug, it may still be worthwhile to backport this fix to them. + +Fixes: b7236e21d55f ("ext4 crypto: reorganize how we store keys in the inode") +Cc: stable@vger.kernel.org # v4.2+ +Signed-off-by: Eric Biggers +Signed-off-by: Theodore Ts'o +Acked-by: Michael Halcrow +--- + fs/crypto/crypto.c | 10 +-------- + fs/crypto/fname.c | 2 +- + fs/crypto/fscrypt_private.h | 4 ---- + fs/crypto/keyinfo.c | 52 ++++++++------------------------------------- + 4 files changed, 11 insertions(+), 57 deletions(-) + +diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c +index 02a7a92..6d6eca3 100644 +--- a/fs/crypto/crypto.c ++++ b/fs/crypto/crypto.c +@@ -327,7 +327,6 @@ EXPORT_SYMBOL(fscrypt_decrypt_page); + static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) + { + struct dentry *dir; +- struct fscrypt_info *ci; + int dir_has_key, cached_with_key; + + if (flags & LOOKUP_RCU) +@@ -339,18 +338,11 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) + return 0; + } + +- ci = d_inode(dir)->i_crypt_info; +- if (ci && ci->ci_keyring_key && +- (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | +- (1 << KEY_FLAG_REVOKED) | +- (1 << KEY_FLAG_DEAD)))) +- ci = NULL; +- + /* this should eventually be an flag in d_flags */ + spin_lock(&dentry->d_lock); + cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY; + spin_unlock(&dentry->d_lock); +- dir_has_key = (ci != NULL); ++ dir_has_key = (d_inode(dir)->i_crypt_info != NULL); + dput(dir); + + /* +diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c +index 13052b8..37b4989 100644 +--- a/fs/crypto/fname.c ++++ b/fs/crypto/fname.c +@@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, + fname->disk_name.len = iname->len; + return 0; + } +- ret = fscrypt_get_crypt_info(dir); ++ ret = fscrypt_get_encryption_info(dir); + if (ret && ret != -EOPNOTSUPP) + return ret; + +diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h +index fdbb8af..e39696e 100644 +--- a/fs/crypto/fscrypt_private.h ++++ b/fs/crypto/fscrypt_private.h +@@ -67,7 +67,6 @@ struct fscrypt_info { + u8 ci_filename_mode; + u8 ci_flags; + struct crypto_skcipher *ci_ctfm; +- struct key *ci_keyring_key; + u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; + }; + +@@ -101,7 +100,4 @@ extern int fscrypt_do_page_crypto(const struct inode *inode, + extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx, + gfp_t gfp_flags); + +-/* keyinfo.c */ +-extern int fscrypt_get_crypt_info(struct inode *); +- + #endif /* _FSCRYPT_PRIVATE_H */ +diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c +index 02eb6b9..cb3e82a 100644 +--- a/fs/crypto/keyinfo.c ++++ b/fs/crypto/keyinfo.c +@@ -95,6 +95,7 @@ static int validate_user_key(struct fscrypt_info *crypt_info, + kfree(description); + if (IS_ERR(keyring_key)) + return PTR_ERR(keyring_key); ++ down_read(&keyring_key->sem); + + if (keyring_key->type != &key_type_logon) { + printk_once(KERN_WARNING +@@ -102,11 +103,9 @@ static int validate_user_key(struct fscrypt_info *crypt_info, + res = -ENOKEY; + goto out; + } +- down_read(&keyring_key->sem); + ukp = user_key_payload(keyring_key); + if (ukp->datalen != sizeof(struct fscrypt_key)) { + res = -EINVAL; +- up_read(&keyring_key->sem); + goto out; + } + master_key = (struct fscrypt_key *)ukp->data; +@@ -117,17 +116,11 @@ static int validate_user_key(struct fscrypt_info *crypt_info, + "%s: key size incorrect: %d\n", + __func__, master_key->size); + res = -ENOKEY; +- up_read(&keyring_key->sem); + goto out; + } + res = derive_key_aes(ctx->nonce, master_key->raw, raw_key); +- up_read(&keyring_key->sem); +- if (res) +- goto out; +- +- crypt_info->ci_keyring_key = keyring_key; +- return 0; + out: ++ up_read(&keyring_key->sem); + key_put(keyring_key); + return res; + } +@@ -169,12 +162,11 @@ static void put_crypt_info(struct fscrypt_info *ci) + if (!ci) + return; + +- key_put(ci->ci_keyring_key); + crypto_free_skcipher(ci->ci_ctfm); + kmem_cache_free(fscrypt_info_cachep, ci); + } + +-int fscrypt_get_crypt_info(struct inode *inode) ++int fscrypt_get_encryption_info(struct inode *inode) + { + struct fscrypt_info *crypt_info; + struct fscrypt_context ctx; +@@ -184,21 +176,15 @@ int fscrypt_get_crypt_info(struct inode *inode) + u8 *raw_key = NULL; + int res; + ++ if (inode->i_crypt_info) ++ return 0; ++ + res = fscrypt_initialize(inode->i_sb->s_cop->flags); + if (res) + return res; + + if (!inode->i_sb->s_cop->get_context) + return -EOPNOTSUPP; +-retry: +- crypt_info = ACCESS_ONCE(inode->i_crypt_info); +- if (crypt_info) { +- if (!crypt_info->ci_keyring_key || +- key_validate(crypt_info->ci_keyring_key) == 0) +- return 0; +- fscrypt_put_encryption_info(inode, crypt_info); +- goto retry; +- } + + res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); + if (res < 0) { +@@ -229,7 +215,6 @@ retry: + crypt_info->ci_data_mode = ctx.contents_encryption_mode; + crypt_info->ci_filename_mode = ctx.filenames_encryption_mode; + crypt_info->ci_ctfm = NULL; +- crypt_info->ci_keyring_key = NULL; + memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor, + sizeof(crypt_info->ci_master_key)); + +@@ -273,14 +258,8 @@ retry: + if (res) + goto out; + +- kzfree(raw_key); +- raw_key = NULL; +- if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) { +- put_crypt_info(crypt_info); +- goto retry; +- } +- return 0; +- ++ if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL) ++ crypt_info = NULL; + out: + if (res == -ENOKEY) + res = 0; +@@ -288,6 +267,7 @@ out: + kzfree(raw_key); + return res; + } ++EXPORT_SYMBOL(fscrypt_get_encryption_info); + + void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci) + { +@@ -305,17 +285,3 @@ void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci) + put_crypt_info(ci); + } + EXPORT_SYMBOL(fscrypt_put_encryption_info); +- +-int fscrypt_get_encryption_info(struct inode *inode) +-{ +- struct fscrypt_info *ci = inode->i_crypt_info; +- +- if (!ci || +- (ci->ci_keyring_key && +- (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | +- (1 << KEY_FLAG_REVOKED) | +- (1 << KEY_FLAG_DEAD))))) +- return fscrypt_get_crypt_info(inode); +- return 0; +-} +-EXPORT_SYMBOL(fscrypt_get_encryption_info); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7472/0.patch b/Patches/Linux_CVEs/CVE-2017-7472/0.patch new file mode 100644 index 00000000..dc8e7e3d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7472/0.patch @@ -0,0 +1,182 @@ +From 6efda2501976288f10895834ba2782d0df093441 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Tue, 18 Apr 2017 15:31:09 +0100 +Subject: KEYS: fix keyctl_set_reqkey_keyring() to not leak thread keyrings + +commit c9f838d104fed6f2f61d68164712e3204bf5271b upstream. + +This fixes CVE-2017-7472. + +Running the following program as an unprivileged user exhausts kernel +memory by leaking thread keyrings: + + #include + + int main() + { + for (;;) + keyctl_set_reqkey_keyring(KEY_REQKEY_DEFL_THREAD_KEYRING); + } + +Fix it by only creating a new thread keyring if there wasn't one before. +To make things more consistent, make install_thread_keyring_to_cred() +and install_process_keyring_to_cred() both return 0 if the corresponding +keyring is already present. + +Fixes: d84f4f992cbd ("CRED: Inaugurate COW credentials") +Signed-off-by: Eric Biggers +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/keyctl.c | 11 ++++------- + security/keys/process_keys.c | 44 +++++++++++++++++++++++++++----------------- + 2 files changed, 31 insertions(+), 24 deletions(-) + +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index af86b35..1187d2f 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -1258,8 +1258,8 @@ error: + * Read or set the default keyring in which request_key() will cache keys and + * return the old setting. + * +- * If a process keyring is specified then this will be created if it doesn't +- * yet exist. The old setting will be returned if successful. ++ * If a thread or process keyring is specified then it will be created if it ++ * doesn't yet exist. The old setting will be returned if successful. + */ + long keyctl_set_reqkey_keyring(int reqkey_defl) + { +@@ -1284,11 +1284,8 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) + + case KEY_REQKEY_DEFL_PROCESS_KEYRING: + ret = install_process_keyring_to_cred(new); +- if (ret < 0) { +- if (ret != -EEXIST) +- goto error; +- ret = 0; +- } ++ if (ret < 0) ++ goto error; + goto set; + + case KEY_REQKEY_DEFL_DEFAULT: +diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c +index db91639..162077d 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -125,13 +125,18 @@ error: + } + + /* +- * Install a fresh thread keyring directly to new credentials. This keyring is +- * allowed to overrun the quota. ++ * Install a thread keyring to the given credentials struct if it didn't have ++ * one already. This is allowed to overrun the quota. ++ * ++ * Return: 0 if a thread keyring is now present; -errno on failure. + */ + int install_thread_keyring_to_cred(struct cred *new) + { + struct key *keyring; + ++ if (new->thread_keyring) ++ return 0; ++ + keyring = keyring_alloc("_tid", new->uid, new->gid, new, + KEY_POS_ALL | KEY_USR_VIEW, + KEY_ALLOC_QUOTA_OVERRUN, NULL); +@@ -143,7 +148,9 @@ int install_thread_keyring_to_cred(struct cred *new) + } + + /* +- * Install a fresh thread keyring, discarding the old one. ++ * Install a thread keyring to the current task if it didn't have one already. ++ * ++ * Return: 0 if a thread keyring is now present; -errno on failure. + */ + static int install_thread_keyring(void) + { +@@ -154,8 +161,6 @@ static int install_thread_keyring(void) + if (!new) + return -ENOMEM; + +- BUG_ON(new->thread_keyring); +- + ret = install_thread_keyring_to_cred(new); + if (ret < 0) { + abort_creds(new); +@@ -166,17 +171,17 @@ static int install_thread_keyring(void) + } + + /* +- * Install a process keyring directly to a credentials struct. ++ * Install a process keyring to the given credentials struct if it didn't have ++ * one already. This is allowed to overrun the quota. + * +- * Returns -EEXIST if there was already a process keyring, 0 if one installed, +- * and other value on any other error ++ * Return: 0 if a process keyring is now present; -errno on failure. + */ + int install_process_keyring_to_cred(struct cred *new) + { + struct key *keyring; + + if (new->process_keyring) +- return -EEXIST; ++ return 0; + + keyring = keyring_alloc("_pid", new->uid, new->gid, new, + KEY_POS_ALL | KEY_USR_VIEW, +@@ -189,11 +194,9 @@ int install_process_keyring_to_cred(struct cred *new) + } + + /* +- * Make sure a process keyring is installed for the current process. The +- * existing process keyring is not replaced. ++ * Install a process keyring to the current task if it didn't have one already. + * +- * Returns 0 if there is a process keyring by the end of this function, some +- * error otherwise. ++ * Return: 0 if a process keyring is now present; -errno on failure. + */ + static int install_process_keyring(void) + { +@@ -207,14 +210,18 @@ static int install_process_keyring(void) + ret = install_process_keyring_to_cred(new); + if (ret < 0) { + abort_creds(new); +- return ret != -EEXIST ? ret : 0; ++ return ret; + } + + return commit_creds(new); + } + + /* +- * Install a session keyring directly to a credentials struct. ++ * Install the given keyring as the session keyring of the given credentials ++ * struct, replacing the existing one if any. If the given keyring is NULL, ++ * then install a new anonymous session keyring. ++ * ++ * Return: 0 on success; -errno on failure. + */ + int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) + { +@@ -249,8 +256,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) + } + + /* +- * Install a session keyring, discarding the old one. If a keyring is not +- * supplied, an empty one is invented. ++ * Install the given keyring as the session keyring of the current task, ++ * replacing the existing one if any. If the given keyring is NULL, then ++ * install a new anonymous session keyring. ++ * ++ * Return: 0 on success; -errno on failure. + */ + static int install_session_keyring(struct key *keyring) + { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7487/0.patch b/Patches/Linux_CVEs/CVE-2017-7487/0.patch new file mode 100644 index 00000000..f91b0b84 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7487/0.patch @@ -0,0 +1,38 @@ +From ee0d8d8482345ff97a75a7d747efc309f13b0d80 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 2 May 2017 13:58:53 +0300 +Subject: ipx: call ipxitf_put() in ioctl error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We should call ipxitf_put() if the copy_to_user() fails. + +Reported-by: 李强 +Signed-off-by: Dan Carpenter +Signed-off-by: David S. Miller +--- + net/ipx/af_ipx.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c +index 8a9219f..fa31ef2 100644 +--- a/net/ipx/af_ipx.c ++++ b/net/ipx/af_ipx.c +@@ -1168,11 +1168,10 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg) + sipx->sipx_network = ipxif->if_netnum; + memcpy(sipx->sipx_node, ipxif->if_node, + sizeof(sipx->sipx_node)); +- rc = -EFAULT; ++ rc = 0; + if (copy_to_user(arg, &ifr, sizeof(ifr))) +- break; ++ rc = -EFAULT; + ipxitf_put(ipxif); +- rc = 0; + break; + } + case SIOCAIPXITFCRT: +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7495/0.patch b/Patches/Linux_CVEs/CVE-2017-7495/0.patch new file mode 100644 index 00000000..d501826e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7495/0.patch @@ -0,0 +1,87 @@ +From 06bd3c36a733ac27962fea7d6f47168841376824 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Sun, 24 Apr 2016 00:56:03 -0400 +Subject: ext4: fix data exposure after a crash + +Huang has reported that in his powerfail testing he is seeing stale +block contents in some of recently allocated blocks although he mounts +ext4 in data=ordered mode. After some investigation I have found out +that indeed when delayed allocation is used, we don't add inode to +transaction's list of inodes needing flushing before commit. Originally +we were doing that but commit f3b59291a69d removed the logic with a +flawed argument that it is not needed. + +The problem is that although for delayed allocated blocks we write their +contents immediately after allocating them, there is no guarantee that +the IO scheduler or device doesn't reorder things and thus transaction +allocating blocks and attaching them to inode can reach stable storage +before actual block contents. Actually whenever we attach freshly +allocated blocks to inode using a written extent, we should add inode to +transaction's ordered inode list to make sure we properly wait for block +contents to be written before committing the transaction. So that is +what we do in this patch. This also handles other cases where stale data +exposure was possible - like filling hole via mmap in +data=ordered,nodelalloc mode. + +The only exception to the above rule are extending direct IO writes where +blkdev_direct_IO() waits for IO to complete before increasing i_size and +thus stale data exposure is not possible. For now we don't complicate +the code with optimizing this special case since the overhead is pretty +low. In case this is observed to be a performance problem we can always +handle it using a special flag to ext4_map_blocks(). + +CC: stable@vger.kernel.org +Fixes: f3b59291a69d0b734be1fc8be489fef2dd846d3d +Reported-by: "HUANG Weller (CM/ESW12-CN)" +Tested-by: "HUANG Weller (CM/ESW12-CN)" +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +--- + fs/ext4/inode.c | 24 +++++++++++++++--------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 981a1fc..250c2df 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -684,6 +684,21 @@ out_sem: + ret = check_block_validity(inode, map); + if (ret != 0) + return ret; ++ ++ /* ++ * Inodes with freshly allocated blocks where contents will be ++ * visible after transaction commit must be on transaction's ++ * ordered data list. ++ */ ++ if (map->m_flags & EXT4_MAP_NEW && ++ !(map->m_flags & EXT4_MAP_UNWRITTEN) && ++ !(flags & EXT4_GET_BLOCKS_ZERO) && ++ !IS_NOQUOTA(inode) && ++ ext4_should_order_data(inode)) { ++ ret = ext4_jbd2_file_inode(handle, inode); ++ if (ret) ++ return ret; ++ } + } + return retval; + } +@@ -1289,15 +1304,6 @@ static int ext4_write_end(struct file *file, + int i_size_changed = 0; + + trace_ext4_write_end(inode, pos, len, copied); +- if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) { +- ret = ext4_jbd2_file_inode(handle, inode); +- if (ret) { +- unlock_page(page); +- put_page(page); +- goto errout; +- } +- } +- + if (ext4_has_inline_data(inode)) { + ret = ext4_write_inline_data_end(inode, pos, len, + copied, page); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7616/0.patch b/Patches/Linux_CVEs/CVE-2017-7616/0.patch new file mode 100644 index 00000000..97b6ec6f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7616/0.patch @@ -0,0 +1,76 @@ +From cf01fb9985e8deb25ccf0ea54d916b8871ae0e62 Mon Sep 17 00:00:00 2001 +From: Chris Salls +Date: Fri, 7 Apr 2017 23:48:11 -0700 +Subject: mm/mempolicy.c: fix error handling in set_mempolicy and mbind. + +In the case that compat_get_bitmap fails we do not want to copy the +bitmap to the user as it will contain uninitialized stack data and leak +sensitive data. + +Signed-off-by: Chris Salls +Signed-off-by: Linus Torvalds +--- + mm/mempolicy.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 75b2745..37d0b33 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -1529,7 +1529,6 @@ COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, policy, + COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, nmask, + compat_ulong_t, maxnode) + { +- long err = 0; + unsigned long __user *nm = NULL; + unsigned long nr_bits, alloc_size; + DECLARE_BITMAP(bm, MAX_NUMNODES); +@@ -1538,14 +1537,13 @@ COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, nmask, + alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8; + + if (nmask) { +- err = compat_get_bitmap(bm, nmask, nr_bits); ++ if (compat_get_bitmap(bm, nmask, nr_bits)) ++ return -EFAULT; + nm = compat_alloc_user_space(alloc_size); +- err |= copy_to_user(nm, bm, alloc_size); ++ if (copy_to_user(nm, bm, alloc_size)) ++ return -EFAULT; + } + +- if (err) +- return -EFAULT; +- + return sys_set_mempolicy(mode, nm, nr_bits+1); + } + +@@ -1553,7 +1551,6 @@ COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len, + compat_ulong_t, mode, compat_ulong_t __user *, nmask, + compat_ulong_t, maxnode, compat_ulong_t, flags) + { +- long err = 0; + unsigned long __user *nm = NULL; + unsigned long nr_bits, alloc_size; + nodemask_t bm; +@@ -1562,14 +1559,13 @@ COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len, + alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8; + + if (nmask) { +- err = compat_get_bitmap(nodes_addr(bm), nmask, nr_bits); ++ if (compat_get_bitmap(nodes_addr(bm), nmask, nr_bits)) ++ return -EFAULT; + nm = compat_alloc_user_space(alloc_size); +- err |= copy_to_user(nm, nodes_addr(bm), alloc_size); ++ if (copy_to_user(nm, nodes_addr(bm), alloc_size)) ++ return -EFAULT; + } + +- if (err) +- return -EFAULT; +- + return sys_mbind(start, len, mode, nm, nr_bits+1, flags); + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7618/0.patch b/Patches/Linux_CVEs/CVE-2017-7618/0.patch new file mode 100644 index 00000000..a384a909 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7618/0.patch @@ -0,0 +1,234 @@ +From c2798145e731005fa1e6ee2a489940c1dd8f03e4 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Mon, 10 Apr 2017 17:27:57 +0800 +Subject: crypto: ahash - Fix EINPROGRESS notification callback + +commit ef0579b64e93188710d48667cb5e014926af9f1b upstream. + +The ahash API modifies the request's callback function in order +to clean up after itself in some corner cases (unaligned final +and missing finup). + +When the request is complete ahash will restore the original +callback and everything is fine. However, when the request gets +an EBUSY on a full queue, an EINPROGRESS callback is made while +the request is still ongoing. + +In this case the ahash API will incorrectly call its own callback. + +This patch fixes the problem by creating a temporary request +object on the stack which is used to relay EINPROGRESS back to +the original completion function. + +This patch also adds code to preserve the original flags value. + +Fixes: ab6bf4e5e5e4 ("crypto: hash - Fix the pointer voodoo in...") +Reported-by: Sabrina Dubroca +Tested-by: Sabrina Dubroca +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/ahash.c | 79 ++++++++++++++++++++++++++---------------- + include/crypto/internal/hash.h | 10 ++++++ + 2 files changed, 60 insertions(+), 29 deletions(-) + +diff --git a/crypto/ahash.c b/crypto/ahash.c +index 46ab909..a11220e 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -31,6 +31,7 @@ struct ahash_request_priv { + crypto_completion_t complete; + void *data; + u8 *result; ++ u32 flags; + void *ubuf[] CRYPTO_MINALIGN_ATTR; + }; + +@@ -269,6 +270,8 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt) + priv->result = req->result; + priv->complete = req->base.complete; + priv->data = req->base.data; ++ priv->flags = req->base.flags; ++ + /* + * WARNING: We do not backup req->priv here! The req->priv + * is for internal use of the Crypto API and the +@@ -283,38 +286,44 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt) + return 0; + } + +-static void ahash_restore_req(struct ahash_request *req) ++static void ahash_restore_req(struct ahash_request *req, int err) + { + struct ahash_request_priv *priv = req->priv; + ++ if (!err) ++ memcpy(priv->result, req->result, ++ crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); ++ + /* Restore the original crypto request. */ + req->result = priv->result; +- req->base.complete = priv->complete; +- req->base.data = priv->data; ++ ++ ahash_request_set_callback(req, priv->flags, ++ priv->complete, priv->data); + req->priv = NULL; + + /* Free the req->priv.priv from the ADJUSTED request. */ + kzfree(priv); + } + +-static void ahash_op_unaligned_finish(struct ahash_request *req, int err) ++static void ahash_notify_einprogress(struct ahash_request *req) + { + struct ahash_request_priv *priv = req->priv; ++ struct crypto_async_request oreq; + +- if (err == -EINPROGRESS) +- return; +- +- if (!err) +- memcpy(priv->result, req->result, +- crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); ++ oreq.data = priv->data; + +- ahash_restore_req(req); ++ priv->complete(&oreq, -EINPROGRESS); + } + + static void ahash_op_unaligned_done(struct crypto_async_request *req, int err) + { + struct ahash_request *areq = req->data; + ++ if (err == -EINPROGRESS) { ++ ahash_notify_einprogress(areq); ++ return; ++ } ++ + /* + * Restore the original request, see ahash_op_unaligned() for what + * goes where. +@@ -325,7 +334,7 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err) + */ + + /* First copy req->result into req->priv.result */ +- ahash_op_unaligned_finish(areq, err); ++ ahash_restore_req(areq, err); + + /* Complete the ORIGINAL request. */ + areq->base.complete(&areq->base, err); +@@ -341,7 +350,12 @@ static int ahash_op_unaligned(struct ahash_request *req, + return err; + + err = op(req); +- ahash_op_unaligned_finish(req, err); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; ++ ++ ahash_restore_req(req, err); + + return err; + } +@@ -376,25 +390,14 @@ int crypto_ahash_digest(struct ahash_request *req) + } + EXPORT_SYMBOL_GPL(crypto_ahash_digest); + +-static void ahash_def_finup_finish2(struct ahash_request *req, int err) ++static void ahash_def_finup_done2(struct crypto_async_request *req, int err) + { +- struct ahash_request_priv *priv = req->priv; ++ struct ahash_request *areq = req->data; + + if (err == -EINPROGRESS) + return; + +- if (!err) +- memcpy(priv->result, req->result, +- crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); +- +- ahash_restore_req(req); +-} +- +-static void ahash_def_finup_done2(struct crypto_async_request *req, int err) +-{ +- struct ahash_request *areq = req->data; +- +- ahash_def_finup_finish2(areq, err); ++ ahash_restore_req(areq, err); + + areq->base.complete(&areq->base, err); + } +@@ -405,11 +408,15 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err) + goto out; + + req->base.complete = ahash_def_finup_done2; +- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; ++ + err = crypto_ahash_reqtfm(req)->final(req); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; + + out: +- ahash_def_finup_finish2(req, err); ++ ahash_restore_req(req, err); + return err; + } + +@@ -417,7 +424,16 @@ static void ahash_def_finup_done1(struct crypto_async_request *req, int err) + { + struct ahash_request *areq = req->data; + ++ if (err == -EINPROGRESS) { ++ ahash_notify_einprogress(areq); ++ return; ++ } ++ ++ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; ++ + err = ahash_def_finup_finish1(areq, err); ++ if (areq->priv) ++ return; + + areq->base.complete(&areq->base, err); + } +@@ -432,6 +448,11 @@ static int ahash_def_finup(struct ahash_request *req) + return err; + + err = tfm->update(req); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; ++ + return ahash_def_finup_finish1(req, err); + } + +diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h +index 3b4af1d..a25414c 100644 +--- a/include/crypto/internal/hash.h ++++ b/include/crypto/internal/hash.h +@@ -173,6 +173,16 @@ static inline struct ahash_instance *ahash_alloc_instance( + return crypto_alloc_instance2(name, alg, ahash_instance_headroom()); + } + ++static inline void ahash_request_complete(struct ahash_request *req, int err) ++{ ++ req->base.complete(&req->base, err); ++} ++ ++static inline u32 ahash_request_flags(struct ahash_request *req) ++{ ++ return req->base.flags; ++} ++ + static inline struct crypto_ahash *crypto_spawn_ahash( + struct crypto_ahash_spawn *spawn) + { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7618/1.patch b/Patches/Linux_CVEs/CVE-2017-7618/1.patch new file mode 100644 index 00000000..85373076 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7618/1.patch @@ -0,0 +1 @@ +Not Found \ No newline at end of file diff --git a/Patches/Linux_CVEs/CVE-2017-7889/0.patch b/Patches/Linux_CVEs/CVE-2017-7889/0.patch new file mode 100644 index 00000000..d247d1fc --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7889/0.patch @@ -0,0 +1,210 @@ +From a4866aa812518ed1a37d8ea0c881dc946409de94 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 5 Apr 2017 09:39:08 -0700 +Subject: mm: Tighten x86 /dev/mem with zeroing reads + +Under CONFIG_STRICT_DEVMEM, reading System RAM through /dev/mem is +disallowed. However, on x86, the first 1MB was always allowed for BIOS +and similar things, regardless of it actually being System RAM. It was +possible for heap to end up getting allocated in low 1MB RAM, and then +read by things like x86info or dd, which would trip hardened usercopy: + +usercopy: kernel memory exposure attempt detected from ffff880000090000 (dma-kmalloc-256) (4096 bytes) + +This changes the x86 exception for the low 1MB by reading back zeros for +System RAM areas instead of blindly allowing them. More work is needed to +extend this to mmap, but currently mmap doesn't go through usercopy, so +hardened usercopy won't Oops the kernel. + +Reported-by: Tommi Rantala +Tested-by: Tommi Rantala +Signed-off-by: Kees Cook +--- + arch/x86/mm/init.c | 41 +++++++++++++++++++-------- + drivers/char/mem.c | 82 ++++++++++++++++++++++++++++++++++-------------------- + 2 files changed, 82 insertions(+), 41 deletions(-) + +diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c +index 22af912..889e761 100644 +--- a/arch/x86/mm/init.c ++++ b/arch/x86/mm/init.c +@@ -643,21 +643,40 @@ void __init init_mem_mapping(void) + * devmem_is_allowed() checks to see if /dev/mem access to a certain address + * is valid. The argument is a physical page number. + * +- * +- * On x86, access has to be given to the first megabyte of ram because that area +- * contains BIOS code and data regions used by X and dosemu and similar apps. +- * Access has to be given to non-kernel-ram areas as well, these contain the PCI +- * mmio resources as well as potential bios/acpi data regions. ++ * On x86, access has to be given to the first megabyte of RAM because that ++ * area traditionally contains BIOS code and data regions used by X, dosemu, ++ * and similar apps. Since they map the entire memory range, the whole range ++ * must be allowed (for mapping), but any areas that would otherwise be ++ * disallowed are flagged as being "zero filled" instead of rejected. ++ * Access has to be given to non-kernel-ram areas as well, these contain the ++ * PCI mmio resources as well as potential bios/acpi data regions. + */ + int devmem_is_allowed(unsigned long pagenr) + { +- if (pagenr < 256) +- return 1; +- if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) ++ if (page_is_ram(pagenr)) { ++ /* ++ * For disallowed memory regions in the low 1MB range, ++ * request that the page be shown as all zeros. ++ */ ++ if (pagenr < 256) ++ return 2; ++ ++ return 0; ++ } ++ ++ /* ++ * This must follow RAM test, since System RAM is considered a ++ * restricted resource under CONFIG_STRICT_IOMEM. ++ */ ++ if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) { ++ /* Low 1MB bypasses iomem restrictions. */ ++ if (pagenr < 256) ++ return 1; ++ + return 0; +- if (!page_is_ram(pagenr)) +- return 1; +- return 0; ++ } ++ ++ return 1; + } + + void free_init_pages(char *what, unsigned long begin, unsigned long end) +diff --git a/drivers/char/mem.c b/drivers/char/mem.c +index 6d9cc2d..7e4a9d1 100644 +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -60,6 +60,10 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) + #endif + + #ifdef CONFIG_STRICT_DEVMEM ++static inline int page_is_allowed(unsigned long pfn) ++{ ++ return devmem_is_allowed(pfn); ++} + static inline int range_is_allowed(unsigned long pfn, unsigned long size) + { + u64 from = ((u64)pfn) << PAGE_SHIFT; +@@ -75,6 +79,10 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) + return 1; + } + #else ++static inline int page_is_allowed(unsigned long pfn) ++{ ++ return 1; ++} + static inline int range_is_allowed(unsigned long pfn, unsigned long size) + { + return 1; +@@ -122,23 +130,31 @@ static ssize_t read_mem(struct file *file, char __user *buf, + + while (count > 0) { + unsigned long remaining; ++ int allowed; + + sz = size_inside_page(p, count); + +- if (!range_is_allowed(p >> PAGE_SHIFT, count)) ++ allowed = page_is_allowed(p >> PAGE_SHIFT); ++ if (!allowed) + return -EPERM; ++ if (allowed == 2) { ++ /* Show zeros for restricted memory. */ ++ remaining = clear_user(buf, sz); ++ } else { ++ /* ++ * On ia64 if a page has been mapped somewhere as ++ * uncached, then it must also be accessed uncached ++ * by the kernel or data corruption may occur. ++ */ ++ ptr = xlate_dev_mem_ptr(p); ++ if (!ptr) ++ return -EFAULT; + +- /* +- * On ia64 if a page has been mapped somewhere as uncached, then +- * it must also be accessed uncached by the kernel or data +- * corruption may occur. +- */ +- ptr = xlate_dev_mem_ptr(p); +- if (!ptr) +- return -EFAULT; ++ remaining = copy_to_user(buf, ptr, sz); ++ ++ unxlate_dev_mem_ptr(p, ptr); ++ } + +- remaining = copy_to_user(buf, ptr, sz); +- unxlate_dev_mem_ptr(p, ptr); + if (remaining) + return -EFAULT; + +@@ -181,30 +197,36 @@ static ssize_t write_mem(struct file *file, const char __user *buf, + #endif + + while (count > 0) { ++ int allowed; ++ + sz = size_inside_page(p, count); + +- if (!range_is_allowed(p >> PAGE_SHIFT, sz)) ++ allowed = page_is_allowed(p >> PAGE_SHIFT); ++ if (!allowed) + return -EPERM; + +- /* +- * On ia64 if a page has been mapped somewhere as uncached, then +- * it must also be accessed uncached by the kernel or data +- * corruption may occur. +- */ +- ptr = xlate_dev_mem_ptr(p); +- if (!ptr) { +- if (written) +- break; +- return -EFAULT; +- } ++ /* Skip actual writing when a page is marked as restricted. */ ++ if (allowed == 1) { ++ /* ++ * On ia64 if a page has been mapped somewhere as ++ * uncached, then it must also be accessed uncached ++ * by the kernel or data corruption may occur. ++ */ ++ ptr = xlate_dev_mem_ptr(p); ++ if (!ptr) { ++ if (written) ++ break; ++ return -EFAULT; ++ } + +- copied = copy_from_user(ptr, buf, sz); +- unxlate_dev_mem_ptr(p, ptr); +- if (copied) { +- written += sz - copied; +- if (written) +- break; +- return -EFAULT; ++ copied = copy_from_user(ptr, buf, sz); ++ unxlate_dev_mem_ptr(p, ptr); ++ if (copied) { ++ written += sz - copied; ++ if (written) ++ break; ++ return -EFAULT; ++ } + } + + buf += sz; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-7979/0.patch b/Patches/Linux_CVEs/CVE-2017-7979/0.patch new file mode 100644 index 00000000..ef032c7c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-7979/0.patch @@ -0,0 +1,130 @@ +From e0535ce58b92d7baf0b33284a6c4f8f0338f943e Mon Sep 17 00:00:00 2001 +From: Wolfgang Bumiller +Date: Thu, 20 Apr 2017 14:08:26 +0200 +Subject: net sched actions: allocate act cookie early + +Policing filters do not use the TCA_ACT_* enum and the tb[] +nlattr array in tcf_action_init_1() doesn't get filled for +them so we should not try to look for a TCA_ACT_COOKIE +attribute in the then uninitialized array. +The error handling in cookie allocation then calls +tcf_hash_release() leading to invalid memory access later +on. +Additionally, if cookie allocation fails after an already +existing non-policing filter has successfully been changed, +tcf_action_release() should not be called, also we would +have to roll back the changes in the error handling, so +instead we now allocate the cookie early and assign it on +success at the end. + +CVE-2017-7979 +Fixes: 1045ba77a596 ("net sched actions: Add support for user cookies") +Signed-off-by: Wolfgang Bumiller +Acked-by: Jamal Hadi Salim +Signed-off-by: David S. Miller +--- + net/sched/act_api.c | 55 +++++++++++++++++++++++++++++++---------------------- + 1 file changed, 32 insertions(+), 23 deletions(-) + +diff --git a/net/sched/act_api.c b/net/sched/act_api.c +index b70aa57..e05b924 100644 +--- a/net/sched/act_api.c ++++ b/net/sched/act_api.c +@@ -529,20 +529,20 @@ errout: + return err; + } + +-static int nla_memdup_cookie(struct tc_action *a, struct nlattr **tb) ++static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb) + { +- a->act_cookie = kzalloc(sizeof(*a->act_cookie), GFP_KERNEL); +- if (!a->act_cookie) +- return -ENOMEM; ++ struct tc_cookie *c = kzalloc(sizeof(*c), GFP_KERNEL); ++ if (!c) ++ return NULL; + +- a->act_cookie->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL); +- if (!a->act_cookie->data) { +- kfree(a->act_cookie); +- return -ENOMEM; ++ c->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL); ++ if (!c->data) { ++ kfree(c); ++ return NULL; + } +- a->act_cookie->len = nla_len(tb[TCA_ACT_COOKIE]); ++ c->len = nla_len(tb[TCA_ACT_COOKIE]); + +- return 0; ++ return c; + } + + struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, +@@ -551,6 +551,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, + { + struct tc_action *a; + struct tc_action_ops *a_o; ++ struct tc_cookie *cookie = NULL; + char act_name[IFNAMSIZ]; + struct nlattr *tb[TCA_ACT_MAX + 1]; + struct nlattr *kind; +@@ -566,6 +567,18 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, + goto err_out; + if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) + goto err_out; ++ if (tb[TCA_ACT_COOKIE]) { ++ int cklen = nla_len(tb[TCA_ACT_COOKIE]); ++ ++ if (cklen > TC_COOKIE_MAX_SIZE) ++ goto err_out; ++ ++ cookie = nla_memdup_cookie(tb); ++ if (!cookie) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ } + } else { + err = -EINVAL; + if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) +@@ -604,20 +617,12 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, + if (err < 0) + goto err_mod; + +- if (tb[TCA_ACT_COOKIE]) { +- int cklen = nla_len(tb[TCA_ACT_COOKIE]); +- +- if (cklen > TC_COOKIE_MAX_SIZE) { +- err = -EINVAL; +- tcf_hash_release(a, bind); +- goto err_mod; +- } +- +- if (nla_memdup_cookie(a, tb) < 0) { +- err = -ENOMEM; +- tcf_hash_release(a, bind); +- goto err_mod; ++ if (name == NULL && tb[TCA_ACT_COOKIE]) { ++ if (a->act_cookie) { ++ kfree(a->act_cookie->data); ++ kfree(a->act_cookie); + } ++ a->act_cookie = cookie; + } + + /* module count goes up only when brand new policy is created +@@ -632,6 +637,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, + err_mod: + module_put(a_o->owner); + err_out: ++ if (cookie) { ++ kfree(cookie->data); ++ kfree(cookie); ++ } + return ERR_PTR(err); + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8233/0.patch b/Patches/Linux_CVEs/CVE-2017-8233/0.patch new file mode 100644 index 00000000..2646b4fa --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8233/0.patch @@ -0,0 +1,60 @@ +From 64b7bc25e019dd07e8042e0a6ec6dc6a1dd0c385 Mon Sep 17 00:00:00 2001 +From: Pratap Nirujogi +Date: Mon, 20 Feb 2017 17:29:33 +0530 +Subject: msm: camera: cpp: Fixing Heap overflow in output buffer + +Issue: +Missing bound check when writing into the output array +buffer, which can lead to out-of-bound heap write. + +Fix: +Addding hardcoded constant 8 in the MSM_OUTPUT_BUF_CNT +macro and size check to the place where the array is +accessed. Returning '0' if exceeds MSM_OUTPUT_BUF_CNT. +Caller will return -EINVAL for '0'. + +Change-Id: Ic03f86e3e47ece9ca7069527e741a75ad9a0f83f +CRs-Fixed: 2004036 +Signed-off-by: Pratap Nirujogi +--- + drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 2 ++ + include/uapi/media/msmb_pproc.h | 3 ++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +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 e35a744..19d9bbb 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 +@@ -2045,6 +2045,8 @@ static int msm_cpp_check_buf_type(struct msm_buf_mngr_info *buff_mgr_info, + /* More or equal bufs as Input buffer */ + num_output_bufs = new_frame->batch_info.batch_size; + } ++ if (num_output_bufs > MSM_OUTPUT_BUF_CNT) ++ return 0; + for (i = 0; i < num_output_bufs; i++) { + new_frame->output_buffer_info[i].index = + buff_mgr_info->user_buf.buf_idx[i]; +diff --git a/include/uapi/media/msmb_pproc.h b/include/uapi/media/msmb_pproc.h +index b65669b..8f45457 100644 +--- a/include/uapi/media/msmb_pproc.h ++++ b/include/uapi/media/msmb_pproc.h +@@ -16,6 +16,7 @@ + #define MSM_CPP_MAX_FRAME_LENGTH 4096 + #define MSM_CPP_MAX_FW_NAME_LEN 32 + #define MAX_FREQ_TBL 10 ++#define MSM_OUTPUT_BUF_CNT 8 + + enum msm_cpp_frame_type { + MSM_CPP_OFFLINE_FRAME, +@@ -76,7 +77,7 @@ struct msm_cpp_frame_info_t { + uint32_t feature_mask; + uint8_t we_disable; + struct msm_cpp_buffer_info_t input_buffer_info; +- struct msm_cpp_buffer_info_t output_buffer_info[8]; ++ struct msm_cpp_buffer_info_t output_buffer_info[MSM_OUTPUT_BUF_CNT]; + struct msm_cpp_buffer_info_t duplicate_buffer_info; + struct msm_cpp_buffer_info_t tnr_scratch_buffer_info[2]; + uint32_t reserved; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8234/0.patch b/Patches/Linux_CVEs/CVE-2017-8234/0.patch new file mode 100644 index 00000000..d6452b3a --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8234/0.patch @@ -0,0 +1,74 @@ +From 6266f954a52641f550ef71653ea83c80bdd083be Mon Sep 17 00:00:00 2001 +From: Ravi Kishore Tanuku +Date: Fri, 29 May 2015 11:49:26 +0530 +Subject: msm: camera: cci: Add out of boundary check + +While optimizing the cci transactions, we compare +i2c addresses in consecutive commands using pointer +to command. + if (cmd->reg_addr + 1 ==(cmd+1)->reg_addr) +Here, we need to have a out of boundary +check to see if the pointer to that command does not +go out of bounds. + +================================================================== +BUG: KASan: out of bounds access in msm_cci_i2c_write+0x644/0xe64 at addr ffffffc01ef225d0 +Read of size 2 by task mm-qcamera-daem/6458 +============================================================================= +BUG kmalloc-2048 (Not tainted): kasan: bad access detected +----------------------------------------------------------------------------- + +Disabling lock debugging due to kernel taint +INFO: Slab 0xffffffbc027bc800 objects=16 used=16 fp=0x (null) flags=0x4080 +INFO: Object 0xffffffc01ef22000 @offset=8192 fp=0x0000000000000101 +Call trace: +[] dump_backtrace+0x0/0x174 +[] show_stack+0x10/0x1c +[] dump_stack+0x1c/0x28 +[] print_trailer+0x138/0x14c +[] object_err+0x38/0x4c +[] kasan_report_error+0x21c/0x3f0 +[] kasan_report+0x68/0x78 +[] __asan_load2+0x78/0x84 +[] msm_cci_i2c_write+0x640/0xe64 +[] msm_cci_config+0xde0/0x18fc +[] msm_cci_subdev_ioctl+0x88/0xdc +[] msm_camera_cci_i2c_write_table+0x100/0x198 +[] msm_sensor_config32+0x684/0xe64 +[] msm_sensor_subdev_ioctl+0xf8/0x28c +[] msm_sensor_subdev_do_ioctl+0x3c/0x48 +[] video_usercopy+0x2e8/0x4d4 +[] msm_sensor_subdev_fops_ioctl+0x10/0x1c +[] v4l2_compat_ioctl32+0x668/0x684 +[] compat_sys_ioctl+0x13c/0x1998 +Memory state around the buggy address: + ffffffc01ef22480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffffffc01ef22500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +>ffffffc01ef22580: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc + ^ + ffffffc01ef22600: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ffffffc01ef22680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +================================================================== + +Change-Id: Id835bf3276c91cd80c3ef59e6648a6d6792d2567 +Signed-off-by: Ravi Kishore Tanuku +--- + drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +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 86561ce..05a4c0b 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 +@@ -330,7 +330,7 @@ static int32_t msm_cci_calc_cmd_len(struct cci_device *cci_dev, + pack_max_len = size < (cci_dev->payload_size-len) ? + size : (cci_dev->payload_size-len); + for (i = 0; i < pack_max_len;) { +- if (cmd->delay) ++ if (cmd->delay || ((cmd - i2c_cmd) >= (cmd_size-1))) + break; + if (cmd->reg_addr + 1 == + (cmd+1)->reg_addr) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8235/0.patch b/Patches/Linux_CVEs/CVE-2017-8235/0.patch new file mode 100644 index 00000000..0516ba37 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8235/0.patch @@ -0,0 +1,118 @@ +From 7e4424a1b5f6a6536066cca7aac2c3a23fd39f6f Mon Sep 17 00:00:00 2001 +From: Krishnankutty Kolathappilly +Date: Wed, 16 Nov 2016 15:10:18 -0800 +Subject: msm: camera: Synchronize jpeg ISR and userspace call + +This will fix the race between jpeg dma ISR and userspace call. +Without this fix jpeg dma may randomly crash due to invalid pointer +access. + +Change-Id: I559ae08b9a46d5d3c35f8be509976a25faa967f9 +CRs-Fixed: 1083323 +Signed-off-by: Krishnankutty Kolathappilly +--- + .../platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c | 14 +++++++++++--- + .../platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h | 1 + + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +index 3301fc4..4b48469 100644 +--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c ++++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +@@ -537,6 +537,7 @@ static int msm_jpegdma_open(struct file *file) + if (!ctx) + return -ENOMEM; + ++ mutex_init(&ctx->lock); + ctx->jdma_device = device; + dev_dbg(ctx->jdma_device->dev, "Jpeg v4l2 dma open\n"); + /* Set ctx defaults */ +@@ -835,12 +836,13 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh, + int ret; + + msm_jpegdma_cast_long_to_buff_ptr(buf->m.userptr, &up_buff); +- ++ mutex_lock(&ctx->lock); + if (!access_ok(VERIFY_READ, up_buff, + sizeof(struct msm_jpeg_dma_buff)) || + get_user(kp_buff.fd, &up_buff->fd) || + get_user(kp_buff.offset, &up_buff->offset)) { + dev_err(ctx->jdma_device->dev, "Error getting user data\n"); ++ mutex_unlock(&ctx->lock); + return -EFAULT; + } + +@@ -849,6 +851,7 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh, + put_user(kp_buff.fd, &up_buff->fd) || + put_user(kp_buff.offset, &up_buff->offset)) { + dev_err(ctx->jdma_device->dev, "Error putting user data\n"); ++ mutex_unlock(&ctx->lock); + return -EFAULT; + } + +@@ -871,7 +874,7 @@ static int msm_jpegdma_qbuf(struct file *file, void *fh, + ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); + if (ret < 0) + dev_err(ctx->jdma_device->dev, "QBuf fail\n"); +- ++ mutex_unlock(&ctx->lock); + return ret; + } + +@@ -1032,10 +1035,11 @@ static int msm_jpegdma_s_crop(struct file *file, void *fh, + if (crop->c.height % formats[ctx->format_idx].v_align) + return -EINVAL; + ++ mutex_lock(&ctx->lock); + ctx->crop = crop->c; + if (atomic_read(&ctx->active)) + ret = msm_jpegdma_update_hw_config(ctx); +- ++ mutex_unlock(&ctx->lock); + return ret; + } + +@@ -1240,12 +1244,14 @@ void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma) + + ctx = v4l2_m2m_get_curr_priv(dma->m2m_dev); + if (ctx) { ++ mutex_lock(&ctx->lock); + ctx->plane_idx++; + if (ctx->plane_idx >= formats[ctx->format_idx].num_planes) { + src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + if (src_buf == NULL || dst_buf == NULL) { + dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n"); ++ mutex_unlock(&ctx->lock); + mutex_unlock(&dma->lock); + return; + } +@@ -1261,11 +1267,13 @@ void msm_jpegdma_isr_processing_done(struct msm_jpegdma_device *dma) + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + if (src_buf == NULL || dst_buf == NULL) { + dev_err(ctx->jdma_device->dev, "Error, buffer list empty\n"); ++ mutex_unlock(&ctx->lock); + mutex_unlock(&dma->lock); + return; + } + msm_jpegdma_process_buffers(ctx, src_buf, dst_buf); + } ++ mutex_unlock(&ctx->lock); + } + mutex_unlock(&dma->lock); + } +diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h +index 6a1205d..4911ce3 100644 +--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h ++++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h +@@ -254,6 +254,7 @@ struct msm_jpegdma_buf_handle { + * @format_idx: Current format index. + */ + struct jpegdma_ctx { ++ struct mutex lock; + struct msm_jpegdma_device *jdma_device; + atomic_t active; + struct completion completion; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8236/0.patch b/Patches/Linux_CVEs/CVE-2017-8236/0.patch new file mode 100644 index 00000000..362151cd --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8236/0.patch @@ -0,0 +1,147 @@ +From cf0d31bc3b04cf2db7737d36b11a5bf50af0c1db Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Wed, 1 Mar 2017 16:08:27 -0800 +Subject: msm: IPA: add the check on intf query + +The ipa_ioc_query_intf_rx_props structure comes +from the ioctl handler, and it is verified that +the size of rx buffer does not exceed the +IPA_NUM_PROPS_MAX elements. It is also verified +that the "entry->rx" buffer does not exceed +IPA_NUM_PROPS_MAX when "entry" is allocated. +However, the sizes of the buffer "rx->rx" and +the buffer "entry->rx" are not guaranteed to +be the same and will lead memory corruption +issue. The fix is to add the check before +memcpy. + +Change-Id: Idf5c2d32f47c1a1cffeaa5607193855188893ddb +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa_v2/ipa_intf.c | 24 ++++++++++++++++++++++++ + drivers/platform/msm/ipa/ipa_v3/ipa_intf.c | 28 +++++++++++++++++++++++++--- + 2 files changed, 49 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c +index e0f4dcf..f8f8fd1 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c +@@ -272,6 +272,14 @@ int ipa_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx) + mutex_lock(&ipa_ctx->lock); + list_for_each_entry(entry, &ipa_ctx->intf_list, link) { + if (!strncmp(entry->name, tx->name, IPA_RESOURCE_NAME_MAX)) { ++ /* add the entry check */ ++ if (entry->num_tx_props != tx->num_tx_props) { ++ IPAERR("invalid entry number(%u %u)\n", ++ entry->num_tx_props, ++ tx->num_tx_props); ++ mutex_unlock(&ipa_ctx->lock); ++ return result; ++ } + memcpy(tx->tx, entry->tx, entry->num_tx_props * + sizeof(struct ipa_ioc_tx_intf_prop)); + result = 0; +@@ -305,6 +313,14 @@ int ipa_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx) + mutex_lock(&ipa_ctx->lock); + list_for_each_entry(entry, &ipa_ctx->intf_list, link) { + if (!strncmp(entry->name, rx->name, IPA_RESOURCE_NAME_MAX)) { ++ /* add the entry check */ ++ if (entry->num_rx_props != rx->num_rx_props) { ++ IPAERR("invalid entry number(%u %u)\n", ++ entry->num_rx_props, ++ rx->num_rx_props); ++ mutex_unlock(&ipa_ctx->lock); ++ return result; ++ } + memcpy(rx->rx, entry->rx, entry->num_rx_props * + sizeof(struct ipa_ioc_rx_intf_prop)); + result = 0; +@@ -338,6 +354,14 @@ int ipa_query_intf_ext_props(struct ipa_ioc_query_intf_ext_props *ext) + mutex_lock(&ipa_ctx->lock); + list_for_each_entry(entry, &ipa_ctx->intf_list, link) { + if (!strcmp(entry->name, ext->name)) { ++ /* add the entry check */ ++ if (entry->num_ext_props != ext->num_ext_props) { ++ IPAERR("invalid entry number(%u %u)\n", ++ entry->num_ext_props, ++ ext->num_ext_props); ++ mutex_unlock(&ipa_ctx->lock); ++ return result; ++ } + memcpy(ext->ext, entry->ext, entry->num_ext_props * + sizeof(struct ipa_ioc_ext_intf_prop)); + result = 0; +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c +index b9f5755..067a58c 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2017, The 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 +@@ -275,6 +275,14 @@ int ipa3_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx) + mutex_lock(&ipa3_ctx->lock); + list_for_each_entry(entry, &ipa3_ctx->intf_list, link) { + if (!strcmp(entry->name, tx->name)) { ++ /* add the entry check */ ++ if (entry->num_tx_props != tx->num_tx_props) { ++ IPAERR("invalid entry number(%u %u)\n", ++ entry->num_tx_props, ++ tx->num_tx_props); ++ mutex_unlock(&ipa3_ctx->lock); ++ return result; ++ } + memcpy(tx->tx, entry->tx, entry->num_tx_props * + sizeof(struct ipa_ioc_tx_intf_prop)); + result = 0; +@@ -282,7 +290,6 @@ int ipa3_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx) + } + } + mutex_unlock(&ipa3_ctx->lock); +- + return result; + } + +@@ -314,6 +321,14 @@ int ipa3_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx) + mutex_lock(&ipa3_ctx->lock); + list_for_each_entry(entry, &ipa3_ctx->intf_list, link) { + if (!strcmp(entry->name, rx->name)) { ++ /* add the entry check */ ++ if (entry->num_rx_props != rx->num_rx_props) { ++ IPAERR("invalid entry number(%u %u)\n", ++ entry->num_rx_props, ++ rx->num_rx_props); ++ mutex_unlock(&ipa3_ctx->lock); ++ return result; ++ } + memcpy(rx->rx, entry->rx, entry->num_rx_props * + sizeof(struct ipa_ioc_rx_intf_prop)); + result = 0; +@@ -321,7 +336,6 @@ int ipa3_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx) + } + } + mutex_unlock(&ipa3_ctx->lock); +- + return result; + } + +@@ -348,6 +362,14 @@ int ipa3_query_intf_ext_props(struct ipa_ioc_query_intf_ext_props *ext) + mutex_lock(&ipa3_ctx->lock); + list_for_each_entry(entry, &ipa3_ctx->intf_list, link) { + if (!strcmp(entry->name, ext->name)) { ++ /* add the entry check */ ++ if (entry->num_ext_props != ext->num_ext_props) { ++ IPAERR("invalid entry number(%u %u)\n", ++ entry->num_ext_props, ++ ext->num_ext_props); ++ mutex_unlock(&ipa3_ctx->lock); ++ return result; ++ } + memcpy(ext->ext, entry->ext, entry->num_ext_props * + sizeof(struct ipa_ioc_ext_intf_prop)); + result = 0; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8237/0.patch b/Patches/Linux_CVEs/CVE-2017-8237/0.patch new file mode 100644 index 00000000..60568bde --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8237/0.patch @@ -0,0 +1,476 @@ +From 342d16ac6fb01e304ec75344c693257e00628ecf Mon Sep 17 00:00:00 2001 +From: Ghanim Fodi +Date: Tue, 24 Jan 2017 15:42:30 +0200 +Subject: msm: ipa3: Validate IPA and GSI firmwares before loading + +IPA and GSI firmwares are saved on the file-system as an +ELF file. IPA driver extracts the firmwares and load +them during driver initialization. +This change adds validation steps to each firmware before +loading: load addresses, memory sizes, firmware sizes and +more... + +Change-Id: I7d7f66e8e8a9ca0efae08b1e57b25ae4e44cc5bb +CRs-fixed: 1110522 +Signed-off-by: Ghanim Fodi +--- + drivers/platform/msm/gsi/gsi.c | 10 ++ + drivers/platform/msm/gsi/gsi_reg.h | 4 +- + drivers/platform/msm/ipa/ipa_v3/ipa.c | 2 +- + drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 2 +- + drivers/platform/msm/ipa/ipa_v3/ipa_utils.c | 187 +++++++++++++++------ + drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c | 18 +- + drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h | 12 +- + drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h | 6 +- + .../platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c | 6 + + .../platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h | 4 +- + include/linux/msm_gsi.h | 21 ++- + 11 files changed, 215 insertions(+), 57 deletions(-) + +diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c +index 24fdd61..a30d806 100644 +--- a/drivers/platform/msm/gsi/gsi.c ++++ b/drivers/platform/msm/gsi/gsi.c +@@ -2742,6 +2742,16 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size, enum gsi_ver ver) + } + EXPORT_SYMBOL(gsi_enable_fw); + ++void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, ++ unsigned long *size) ++{ ++ if (base_offset) ++ *base_offset = GSI_GSI_INST_RAM_BASE_OFFS; ++ if (size) ++ *size = GSI_GSI_INST_RAM_SIZE; ++} ++EXPORT_SYMBOL(gsi_get_inst_ram_offset_and_size); ++ + static int msm_gsi_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +diff --git a/drivers/platform/msm/gsi/gsi_reg.h b/drivers/platform/msm/gsi/gsi_reg.h +index fa1e848..1acaf74 100644 +--- a/drivers/platform/msm/gsi/gsi_reg.h ++++ b/drivers/platform/msm/gsi/gsi_reg.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2017, The 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 +@@ -1838,5 +1838,7 @@ + #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_BMSK 0xffffffff + #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_SHFT 0x0 + ++#define GSI_GSI_INST_RAM_BASE_OFFS 0x4000 ++#define GSI_GSI_INST_RAM_SIZE 0x4000 + + #endif /* __GSI_REG_H__ */ +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c +index aa83cbd..82887d05 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c +@@ -4187,7 +4187,7 @@ static int ipa3_trigger_fw_loading_mdms(void) + + IPADBG("FWs are available for loading\n"); + +- result = ipa3_load_fws(fw); ++ result = ipa3_load_fws(fw, ipa3_res.transport_mem_base); + if (result) { + IPAERR("IPA FWs loading has failed\n"); + release_firmware(fw); +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +index 3f19c21..fa6dd64 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +@@ -2015,7 +2015,7 @@ int ipa3_uc_panic_notifier(struct notifier_block *this, + unsigned long event, void *ptr); + void ipa3_inc_acquire_wakelock(void); + void ipa3_dec_release_wakelock(void); +-int ipa3_load_fws(const struct firmware *firmware); ++int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base); + int ipa3_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data); + const char *ipa_hw_error_str(enum ipa3_hw_errors err_type); + int ipa_gsi_ch20_wa(void); +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +index 7b7ae75..ba255a2 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +@@ -6107,75 +6107,164 @@ int ipa3_generate_eq_from_hw_rule( + return 0; + } + ++static int ipa3_load_single_fw(const struct firmware *firmware, ++ const struct elf32_phdr *phdr) ++{ ++ uint32_t *fw_mem_base; ++ int index; ++ const uint32_t *elf_data_ptr; ++ ++ if (phdr->p_offset > firmware->size) { ++ IPAERR("Invalid ELF: offset=%u is beyond elf_size=%zu\n", ++ phdr->p_offset, firmware->size); ++ return -EINVAL; ++ } ++ if ((firmware->size - phdr->p_offset) < phdr->p_filesz) { ++ IPAERR("Invalid ELF: offset=%u filesz=%u elf_size=%zu\n", ++ phdr->p_offset, phdr->p_filesz, firmware->size); ++ return -EINVAL; ++ } ++ ++ if (phdr->p_memsz % sizeof(uint32_t)) { ++ IPAERR("FW mem size %u doesn't align to 32bit\n", ++ phdr->p_memsz); ++ return -EFAULT; ++ } ++ ++ if (phdr->p_filesz > phdr->p_memsz) { ++ IPAERR("FW image too big src_size=%u dst_size=%u\n", ++ phdr->p_filesz, phdr->p_memsz); ++ return -EFAULT; ++ } ++ ++ fw_mem_base = ioremap(phdr->p_vaddr, phdr->p_memsz); ++ if (!fw_mem_base) { ++ IPAERR("Failed to map 0x%x for the size of %u\n", ++ phdr->p_vaddr, phdr->p_memsz); ++ return -ENOMEM; ++ } ++ ++ /* Set the entire region to 0s */ ++ memset(fw_mem_base, 0, phdr->p_memsz); ++ ++ elf_data_ptr = (uint32_t *)(firmware->data + phdr->p_offset); ++ ++ /* Write the FW */ ++ for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); index++) { ++ writel_relaxed(*elf_data_ptr, &fw_mem_base[index]); ++ elf_data_ptr++; ++ } ++ ++ iounmap(fw_mem_base); ++ ++ return 0; ++} ++ + /** + * ipa3_load_fws() - Load the IPAv3 FWs into IPA&GSI SRAM. + * + * @firmware: Structure which contains the FW data from the user space. ++ * @gsi_mem_base: GSI base address + * + * Return value: 0 on success, negative otherwise + * + */ +-int ipa3_load_fws(const struct firmware *firmware) ++int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base) + { + const struct elf32_hdr *ehdr; + const struct elf32_phdr *phdr; +- const uint8_t *elf_phdr_ptr; +- uint32_t *elf_data_ptr; +- int phdr_idx, index; +- uint32_t *fw_mem_base; +- +- ehdr = (struct elf32_hdr *) firmware->data; +- +- elf_phdr_ptr = firmware->data + sizeof(*ehdr); ++ unsigned long gsi_iram_ofst; ++ unsigned long gsi_iram_size; ++ phys_addr_t ipa_reg_mem_base; ++ u32 ipa_reg_ofst; ++ int rc; ++ ++ if (!gsi_mem_base) { ++ IPAERR("Invalid GSI base address\n"); ++ return -EINVAL; ++ } + +- for (phdr_idx = 0; phdr_idx < ehdr->e_phnum; phdr_idx++) { +- /* +- * The ELF program header will contain the starting +- * address to which the firmware needs to copied. +- */ +- phdr = (struct elf32_phdr *)elf_phdr_ptr; ++ ipa_assert_on(!firmware); ++ /* One program header per FW image: GSI, DPS and HPS */ ++ if (firmware->size < (sizeof(*ehdr) + 3 * sizeof(*phdr))) { ++ IPAERR("Missing ELF and Program headers firmware size=%zu\n", ++ firmware->size); ++ return -EINVAL; ++ } + +- /* +- * p_vaddr will contain the starting address to which the +- * FW needs to be loaded. +- * p_memsz will contain the size of the IRAM. +- * p_filesz will contain the size of the FW image. +- */ +- fw_mem_base = ioremap(phdr->p_vaddr, phdr->p_memsz); +- if (!fw_mem_base) { +- IPAERR("Failed to map 0x%x for the size of %u\n", +- phdr->p_vaddr, phdr->p_memsz); +- return -ENOMEM; +- } ++ ehdr = (struct elf32_hdr *) firmware->data; ++ ipa_assert_on(!ehdr); ++ if (ehdr->e_phnum != 3) { ++ IPAERR("Unexpected number of ELF program headers\n"); ++ return -EINVAL; ++ } ++ phdr = (struct elf32_phdr *)(firmware->data + sizeof(*ehdr)); + +- /* Set the entire region to 0s */ +- memset(fw_mem_base, 0, phdr->p_memsz); ++ /* ++ * Each ELF program header represents a FW image and contains: ++ * p_vaddr : The starting address to which the FW needs to loaded. ++ * p_memsz : The size of the IRAM (where the image loaded) ++ * p_filesz: The size of the FW image embedded inside the ELF ++ * p_offset: Absolute offset to the image from the head of the ELF ++ */ + +- /* +- * p_offset will contain and absolute offset from the beginning +- * of the ELF file. +- */ +- elf_data_ptr = (uint32_t *) +- ((uint8_t *)firmware->data + phdr->p_offset); ++ /* Load GSI FW image */ ++ gsi_get_inst_ram_offset_and_size(&gsi_iram_ofst, &gsi_iram_size); ++ if (phdr->p_vaddr != (gsi_mem_base + gsi_iram_ofst)) { ++ IPAERR( ++ "Invalid GSI FW img load addr vaddr=0x%x gsi_mem_base=%pa gsi_iram_ofst=0x%lx\n" ++ , phdr->p_vaddr, &gsi_mem_base, gsi_iram_ofst); ++ return -EINVAL; ++ } ++ if (phdr->p_memsz > gsi_iram_size) { ++ IPAERR("Invalid GSI FW img size memsz=%d gsi_iram_size=%lu\n", ++ phdr->p_memsz, gsi_iram_size); ++ return -EINVAL; ++ } ++ rc = ipa3_load_single_fw(firmware, phdr); ++ if (rc) ++ return rc; + +- if (phdr->p_memsz % sizeof(uint32_t)) { +- IPAERR("FW size %u doesn't align to 32bit\n", +- phdr->p_memsz); +- return -EFAULT; +- } ++ phdr++; ++ ipa_reg_mem_base = ipa3_ctx->ipa_wrapper_base + ipahal_get_reg_base(); + +- /* Write the FW */ +- for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); +- index++) { +- writel_relaxed(*elf_data_ptr, &fw_mem_base[index]); +- elf_data_ptr++; +- } ++ /* Load IPA DPS FW image */ ++ ipa_reg_ofst = ipahal_get_reg_ofst(IPA_DPS_SEQUENCER_FIRST); ++ if (phdr->p_vaddr != (ipa_reg_mem_base + ipa_reg_ofst)) { ++ IPAERR( ++ "Invalid IPA DPS img load addr vaddr=0x%x ipa_reg_mem_base=%pa ipa_reg_ofst=%u\n" ++ , phdr->p_vaddr, &ipa_reg_mem_base, ipa_reg_ofst); ++ return -EINVAL; ++ } ++ if (phdr->p_memsz > ipahal_get_dps_img_mem_size()) { ++ IPAERR("Invalid IPA DPS img size memsz=%d dps_mem_size=%u\n", ++ phdr->p_memsz, ipahal_get_dps_img_mem_size()); ++ return -EINVAL; ++ } ++ rc = ipa3_load_single_fw(firmware, phdr); ++ if (rc) ++ return rc; + +- iounmap(fw_mem_base); ++ phdr++; + +- elf_phdr_ptr = elf_phdr_ptr + sizeof(*phdr); ++ /* Load IPA HPS FW image */ ++ ipa_reg_ofst = ipahal_get_reg_ofst(IPA_HPS_SEQUENCER_FIRST); ++ if (phdr->p_vaddr != (ipa_reg_mem_base + ipa_reg_ofst)) { ++ IPAERR( ++ "Invalid IPA HPS img load addr vaddr=0x%x ipa_reg_mem_base=%pa ipa_reg_ofst=%u\n" ++ , phdr->p_vaddr, &ipa_reg_mem_base, ipa_reg_ofst); ++ return -EINVAL; ++ } ++ if (phdr->p_memsz > ipahal_get_hps_img_mem_size()) { ++ IPAERR("Invalid IPA HPS img size memsz=%d dps_mem_size=%u\n", ++ phdr->p_memsz, ipahal_get_hps_img_mem_size()); ++ return -EINVAL; + } +- IPADBG("IPA FWs (GSI FW, HPS and DPS) were loaded\n"); ++ rc = ipa3_load_single_fw(firmware, phdr); ++ if (rc) ++ return rc; ++ ++ IPADBG("IPA FWs (GSI FW, DPS and HPS) loaded successfully\n"); + return 0; + } + +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c +index d023522..95a97ed 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2016-2017, The 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 +@@ -1253,6 +1253,22 @@ int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type) + return res; + } + ++/* ++ * Get IPA Data Processing Star image memory size at IPA SRAM ++ */ ++u32 ipahal_get_dps_img_mem_size(void) ++{ ++ return IPA_HW_DPS_IMG_MEM_SIZE_V3_0; ++} ++ ++/* ++ * Get IPA Header Processing Star image memory size at IPA SRAM ++ */ ++u32 ipahal_get_hps_img_mem_size(void) ++{ ++ return IPA_HW_HPS_IMG_MEM_SIZE_V3_0; ++} ++ + int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base) + { + int result; +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h +index 00b2058..746bc30 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h ++++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2016-2017, The 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 +@@ -634,6 +634,16 @@ void ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type, + */ + int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type); + ++/* ++ * Get IPA Data Processing Star image memory size at IPA SRAM ++ */ ++u32 ipahal_get_dps_img_mem_size(void); ++ ++/* ++ * Get IPA Header Processing Star image memory size at IPA SRAM ++ */ ++u32 ipahal_get_hps_img_mem_size(void); ++ + int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base); + void ipahal_destroy(void); + +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h +index 6a22240..5f02b4df 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h ++++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2016-2017, The 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 +@@ -542,4 +542,8 @@ struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq { + struct ipa_hw_hdr_proc_ctx_tlv end; + }; + ++/* IPA HW DPS/HPS image memory sizes */ ++#define IPA_HW_DPS_IMG_MEM_SIZE_V3_0 128 ++#define IPA_HW_HPS_IMG_MEM_SIZE_V3_0 320 ++ + #endif /* _IPAHAL_I_H_ */ +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +index 6b606ab..6a70fc0 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +@@ -1157,6 +1157,12 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { + [IPA_HW_v3_0][IPA_QSB_MAX_READS] = { + ipareg_construct_qsb_max_reads, ipareg_parse_dummy, + 0x00000078, 0}, ++ [IPA_HW_v3_0][IPA_DPS_SEQUENCER_FIRST] = { ++ ipareg_construct_dummy, ipareg_parse_dummy, ++ 0x0001e000, 0}, ++ [IPA_HW_v3_0][IPA_HPS_SEQUENCER_FIRST] = { ++ ipareg_construct_dummy, ipareg_parse_dummy, ++ 0x0001e080, 0}, + + + /* IPAv3.1 */ +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +index 98894c3..6ca16bf 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h ++++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -84,6 +84,8 @@ enum ipahal_reg_name { + IPA_QSB_MAX_READS, + IPA_TX_CFG, + IPA_IDLE_INDICATION_CFG, ++ IPA_DPS_SEQUENCER_FIRST, ++ IPA_HPS_SEQUENCER_FIRST, + IPA_REG_MAX, + }; + +diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h +index 4825fc7..18d4e72 100644 +--- a/include/linux/msm_gsi.h ++++ b/include/linux/msm_gsi.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2017, The 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 +@@ -1041,6 +1041,19 @@ int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, + */ + int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size, enum gsi_ver ver); + ++/** ++ * gsi_get_inst_ram_offset_and_size - Peripheral should call this function ++ * to get instruction RAM base address offset and size. Peripheral typically ++ * uses this info to load GSI FW into the IRAM. ++ * ++ * @base_offset:[OUT] - IRAM base offset address ++ * @size: [OUT] - IRAM size ++ ++ * @Return none ++ */ ++void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, ++ unsigned long *size); ++ + /* + * Here is a typical sequence of calls + * +@@ -1228,9 +1241,15 @@ static inline int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, + { + return -GSI_STATUS_UNSUPPORTED_OP; + } ++ + static inline int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size) + { + return -GSI_STATUS_UNSUPPORTED_OP; + } ++ ++static inline void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, ++ unsigned long *size) ++{ ++} + #endif + #endif +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8239/0.patch b/Patches/Linux_CVEs/CVE-2017-8239/0.patch new file mode 100644 index 00000000..74b18190 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8239/0.patch @@ -0,0 +1,75 @@ +From 01db0e012f86b8ba6974e5cb9905261a552a0610 Mon Sep 17 00:00:00 2001 +From: Sureshnaidu Laveti +Date: Thu, 15 Dec 2016 02:39:35 -0800 +Subject: msm: sensor: validating the flash initialization parameters + +Copying the flash initialization parameters from userspace memory to +kernel memory and in turn checking for the validity of the flash +initialization parameters pointer sent from userspace. + +CRs-Fixed: 1091603 +Change-Id: I17d57016c254fb6628844a152b0e7d45c0b23b2d +Signed-off-by: Sureshnaidu Laveti +--- + .../msm/camera_v2/sensor/flash/msm_flash.c | 38 +++++++++++++++++++++- + 1 file changed, 37 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +index ff0a0a5..71d3e61 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +@@ -491,6 +491,42 @@ static int32_t msm_flash_init( + return 0; + } + ++#ifdef CONFIG_COMPAT ++static int32_t msm_flash_init_prepare( ++ struct msm_flash_ctrl_t *flash_ctrl, ++ struct msm_flash_cfg_data_t *flash_data) ++{ ++ return msm_flash_init(flash_ctrl, flash_data); ++} ++#else ++static int32_t msm_flash_init_prepare( ++ struct msm_flash_ctrl_t *flash_ctrl, ++ struct msm_flash_cfg_data_t *flash_data) ++{ ++ struct msm_flash_cfg_data_t flash_data_k; ++ struct msm_flash_init_info_t flash_init_info; ++ int32_t i = 0; ++ ++ flash_data_k.cfg_type = flash_data->cfg_type; ++ for (i = 0; i < MAX_LED_TRIGGERS; i++) { ++ flash_data_k.flash_current[i] = ++ flash_data->flash_current[i]; ++ flash_data_k.flash_duration[i] = ++ flash_data->flash_duration[i]; ++ } ++ ++ flash_data_k.cfg.flash_init_info = &flash_init_info; ++ if (copy_from_user(&flash_init_info, ++ (void *)(flash_data->cfg.flash_init_info), ++ sizeof(struct msm_flash_init_info_t))) { ++ pr_err("%s copy_from_user failed %d\n", ++ __func__, __LINE__); ++ return -EFAULT; ++ } ++ return msm_flash_init(flash_ctrl, &flash_data_k); ++} ++#endif ++ + static int32_t msm_flash_low( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +@@ -592,7 +628,7 @@ static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl, + + switch (flash_data->cfg_type) { + case CFG_FLASH_INIT: +- rc = msm_flash_init(flash_ctrl, flash_data); ++ rc = msm_flash_init_prepare(flash_ctrl, flash_data); + break; + case CFG_FLASH_RELEASE: + if (flash_ctrl->flash_state != MSM_CAMERA_FLASH_RELEASE) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8240/0.patch b/Patches/Linux_CVEs/CVE-2017-8240/0.patch new file mode 100644 index 00000000..d5f7e5d0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8240/0.patch @@ -0,0 +1,31 @@ +From 22b8b6608174c1308208d5bc6c143f4998744547 Mon Sep 17 00:00:00 2001 +From: Patrick Daly +Date: Mon, 18 May 2015 14:52:47 -0700 +Subject: pinctrl: qcom: Fix bug in iteration through functions + +Fix iteration beyond array bounds when looping through +the pin functions + +Change-Id: I7e88eed814364062fd93daf03f24ccd4baabf125 +Signed-off-by: Patrick Daly +Signed-off-by: Hanumant Singh +--- + drivers/pinctrl/qcom/pinctrl-msm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c +index e0f86fb..cbea28c 100644 +--- a/drivers/pinctrl/qcom/pinctrl-msm.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm.c +@@ -895,7 +895,7 @@ static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl) + int i = 0; + const struct msm_function *func = pctrl->soc->functions; + +- for (; i <= pctrl->soc->nfunctions; i++) ++ for (; i < pctrl->soc->nfunctions; i++) + if (!strcmp(func[i].name, "ps_hold")) { + pctrl->restart_nb.notifier_call = msm_ps_hold_restart; + pctrl->restart_nb.priority = 128; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8241/0.patch b/Patches/Linux_CVEs/CVE-2017-8241/0.patch new file mode 100644 index 00000000..8c4583f2 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8241/0.patch @@ -0,0 +1,42 @@ +From 90213394b7efb28fa511b2eaebc1343ae3b54724 Mon Sep 17 00:00:00 2001 +From: Sreelakshmi Konamki +Date: Wed, 21 Sep 2016 15:17:42 +0530 +Subject: qcacld-2.0: Update correct msg length in oemData_SendMBOemDataReq API + +In oemData_SendMBOemDataReq(), messageLen of struct 'tSirOemDataReq' +is updated with more memory than allocated to the structure. + +Fix is to update messageLen with size of struct. + +Change-Id: Ib60fd07543f630985fe29427809d822275bbb8e0 +CRs-Fixed: 1069175 +--- + CORE/SME/src/oemData/oemDataApi.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/CORE/SME/src/oemData/oemDataApi.c b/CORE/SME/src/oemData/oemDataApi.c +index 3e42350..fc3f91c 100644 +--- a/CORE/SME/src/oemData/oemDataApi.c ++++ b/CORE/SME/src/oemData/oemDataApi.c +@@ -208,7 +208,6 @@ eHalStatus oemData_SendMBOemDataReq(tpAniSirGlobal pMac, tOemDataReq *pOemDataRe + { + eHalStatus status = eHAL_STATUS_SUCCESS; + tSirOemDataReq* pMsg; +- tANI_U16 msgLen; + tCsrRoamSession *pSession; + + smsLog(pMac, LOGW, "OEM_DATA: entering Function %s", __func__); +@@ -225,9 +224,8 @@ eHalStatus oemData_SendMBOemDataReq(tpAniSirGlobal pMac, tOemDataReq *pOemDataRe + return eHAL_STATUS_FAILURE; + } + +- msgLen = (uint16_t) (sizeof(*pMsg) + pOemDataReq->data_len); + pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_OEM_DATA_REQ); +- pMsg->messageLen = pal_cpu_to_be16(msgLen); ++ pMsg->messageLen = pal_cpu_to_be16((uint16_t) sizeof(*pMsg)); + vos_mem_copy(pMsg->selfMacAddr, pSession->selfMacAddr, sizeof(tSirMacAddr) ); + pMsg->data_len = pOemDataReq->data_len; + /* Incoming buffer ptr saved, set to null to avoid free by caller */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8242/0.patch b/Patches/Linux_CVEs/CVE-2017-8242/0.patch new file mode 100644 index 00000000..500a7e42 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8242/0.patch @@ -0,0 +1,34 @@ +From 6a3b8afdf97e77c0b64005b23fa6d32025d922e5 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Mon, 27 Feb 2017 13:41:07 -0800 +Subject: qseecom: add mutex around qseecom_set_client_mem_param + +Add mutex around qseecom_set_client_mem_param to prevent an +ioctl thread modifying and corrupting data which is being +processed by another ioctl in the other thread + +Change-Id: I0cfb8afab4001c2913be693dfe44c761b9568893 +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index f8819e4..2a4cc5b 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -6982,7 +6982,11 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg) + break; + } + pr_debug("SET_MEM_PARAM: qseecom addr = 0x%pK\n", data); ++ mutex_lock(&app_access_lock); ++ atomic_inc(&data->ioctl_count); + ret = qseecom_set_client_mem_param(data, argp); ++ atomic_dec(&data->ioctl_count); ++ mutex_unlock(&app_access_lock); + if (ret) + pr_err("failed Qqseecom_set_mem_param request: %d\n", + ret); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8244/0.patch b/Patches/Linux_CVEs/CVE-2017-8244/0.patch new file mode 100644 index 00000000..2586682d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8244/0.patch @@ -0,0 +1,185 @@ +From f51b0f3b9da62e96b0167a3eb3376fca39fc7baf Mon Sep 17 00:00:00 2001 +From: Abdulla Anam +Date: Wed, 22 Mar 2017 14:00:10 +0530 +Subject: msm: vidc: Protect debug_buffer access in core_info_read with lock. + +Serialize core_info_read with lock so that multiple concurrent +threads do not cause the write to overflow. Also have the bound +check to avoid overflow in write_str function. + +CRs-Fixed: 2013361 +Change-Id: Ia18a4b94cafd69af1d367861f2499fc202f18e9f +Signed-off-by: Abdulla Anam +Signed-off-by: Sanjay Singh +--- + drivers/media/platform/msm/vidc/msm_v4l2_vidc.c | 5 +++- + drivers/media/platform/msm/vidc/msm_vidc_debug.c | 37 ++++++++++++++++++++---- + drivers/media/platform/msm/vidc/msm_vidc_debug.h | 3 +- + 3 files changed, 37 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +index a46eda7..d845597 100644 +--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c ++++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -737,6 +737,8 @@ static int __init msm_vidc_init(void) + if (rc) { + dprintk(VIDC_ERR, + "Failed to register platform driver\n"); ++ msm_vidc_debugfs_deinit_drv(); ++ debugfs_remove_recursive(vidc_driver->debugfs_root); + kfree(vidc_driver); + vidc_driver = NULL; + } +@@ -747,6 +749,7 @@ static int __init msm_vidc_init(void) + static void __exit msm_vidc_exit(void) + { + platform_driver_unregister(&msm_vidc_driver); ++ msm_vidc_debugfs_deinit_drv(); + debugfs_remove_recursive(vidc_driver->debugfs_root); + kfree(vidc_driver); + vidc_driver = NULL; +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +index 509ea440c..e66fc8b 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -28,6 +28,7 @@ int msm_vidc_sys_idle_indicator = 0x0; + u32 msm_vidc_firmware_unload_delay = 15000; + + struct debug_buffer { ++ struct mutex lock; + char ptr[MAX_DBG_BUF_SIZE]; + char *curr; + u32 filled_size; +@@ -54,8 +55,12 @@ static u32 write_str(struct debug_buffer *buffer, const char *fmt, ...) + { + va_list args; + u32 size; ++ ++ char *curr = buffer->curr; ++ char *end = buffer->ptr + MAX_DBG_BUF_SIZE; ++ + va_start(args, fmt); +- size = vscnprintf(buffer->curr, MAX_DBG_BUF_SIZE - 1, fmt, args); ++ size = vscnprintf(curr, end - curr, fmt, args); + va_end(args); + buffer->curr += size; + buffer->filled_size += size; +@@ -69,12 +74,15 @@ static ssize_t core_info_read(struct file *file, char __user *buf, + struct hfi_device *hdev; + struct hal_fw_info fw_info; + int i = 0, rc = 0; ++ ssize_t len = 0; + + if (!core || !core->device) { + dprintk(VIDC_ERR, "Invalid params, core: %pK\n", core); + return 0; + } + hdev = core->device; ++ ++ mutex_lock(&dbg_buf.lock); + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); + write_str(&dbg_buf, "CORE %d: 0x%pK\n", core->id, core); +@@ -98,8 +106,11 @@ err_fw_info: + completion_done(&core->completions[SYS_MSG_INDEX(i)]) ? + "pending" : "done"); + } +- return simple_read_from_buffer(buf, count, ppos, ++ len = simple_read_from_buffer(buf, count, ppos, + dbg_buf.ptr, dbg_buf.filled_size); ++ ++ mutex_unlock(&dbg_buf.lock); ++ return len; + } + + static const struct file_operations core_info_fops = { +@@ -136,7 +147,10 @@ static const struct file_operations ssr_fops = { + + struct dentry *msm_vidc_debugfs_init_drv(void) + { +- struct dentry *dir = debugfs_create_dir("msm_vidc", NULL); ++ struct dentry *dir = NULL; ++ ++ mutex_init(&dbg_buf.lock); ++ dir = debugfs_create_dir("msm_vidc", NULL); + if (IS_ERR_OR_NULL(dir)) { + dir = NULL; + goto failed_create_dir; +@@ -219,6 +233,7 @@ struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core, + dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n"); + goto failed_create_dir; + } ++ + if (!debugfs_create_file("info", S_IRUGO, dir, core, &core_info_fops)) { + dprintk(VIDC_ERR, "debugfs_create_file: fail\n"); + goto failed_create_dir; +@@ -272,10 +287,14 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + { + struct msm_vidc_inst *inst = file->private_data; + int i, j; ++ ssize_t len = 0; ++ + if (!inst) { + dprintk(VIDC_ERR, "Invalid params, core: %pK\n", inst); + return 0; + } ++ ++ mutex_lock(&dbg_buf.lock); + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); + write_str(&dbg_buf, "INSTANCE: 0x%pK (%s)\n", inst, +@@ -332,9 +351,10 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + write_str(&dbg_buf, "FBD Count: %d\n", inst->count.fbd); + + publish_unreleased_reference(inst); +- +- return simple_read_from_buffer(buf, count, ppos, ++ len = simple_read_from_buffer(buf, count, ppos, + dbg_buf.ptr, dbg_buf.filled_size); ++ mutex_unlock(&dbg_buf.lock); ++ return len; + } + + static const struct file_operations inst_info_fops = { +@@ -411,3 +431,8 @@ void msm_vidc_debugfs_update(struct msm_vidc_inst *inst, + } + } + ++void msm_vidc_debugfs_deinit_drv(void) ++{ ++ mutex_destroy(&dbg_buf.lock); ++} ++ +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h +index bd8e3f6..e1a7ab3 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h ++++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014, 2017 The 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 +@@ -121,6 +121,7 @@ struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst, + struct dentry *parent); + void msm_vidc_debugfs_update(struct msm_vidc_inst *inst, + enum msm_vidc_debugfs_event e); ++void msm_vidc_debugfs_deinit_drv(void); + + static inline void tic(struct msm_vidc_inst *i, enum profiling_points p, + char *b) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8244/1.patch b/Patches/Linux_CVEs/CVE-2017-8244/1.patch new file mode 100644 index 00000000..4c3c9154 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8244/1.patch @@ -0,0 +1,175 @@ +From 01673e148223c10782b03c5485aff2a82b1900c4 Mon Sep 17 00:00:00 2001 +From: Abdulla Anam +Date: Wed, 22 Mar 2017 14:00:10 +0530 +Subject: msm: vidc: Protect debug_buffer access in core_info_read with lock. + +Serialize core_info_read with lock so that multiple concurrent +threads do not cause the write to overflow. Also have the bound +check to avoid overflow in write_str function. + +CRs-Fixed: 2013361 +Change-Id: Ia18a4b94cafd69af1d367861f2499fc202f18e9f +Signed-off-by: Abdulla Anam +--- + drivers/media/platform/msm/vidc/msm_v4l2_vidc.c | 3 ++ + drivers/media/platform/msm/vidc/msm_vidc_debug.c | 37 ++++++++++++++++++++---- + drivers/media/platform/msm/vidc/msm_vidc_debug.h | 1 + + 3 files changed, 35 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +index 319df5e..f77b943 100644 +--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c ++++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +@@ -789,6 +789,8 @@ static int __init msm_vidc_init(void) + if (rc) { + dprintk(VIDC_ERR, + "Failed to register platform driver\n"); ++ msm_vidc_debugfs_deinit_drv(); ++ debugfs_remove_recursive(vidc_driver->debugfs_root); + kfree(vidc_driver); + vidc_driver = NULL; + } +@@ -799,6 +801,7 @@ static int __init msm_vidc_init(void) + static void __exit msm_vidc_exit(void) + { + platform_driver_unregister(&msm_vidc_driver); ++ msm_vidc_debugfs_deinit_drv(); + debugfs_remove_recursive(vidc_driver->debugfs_root); + kfree(vidc_driver); + vidc_driver = NULL; +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +index d34da57..7780990 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -34,6 +34,7 @@ int msm_vidc_debug_timeout = 0; + #define MAX_DBG_BUF_SIZE 4096 + + struct debug_buffer { ++ struct mutex lock; + char ptr[MAX_DBG_BUF_SIZE]; + char *curr; + u32 filled_size; +@@ -60,8 +61,12 @@ static u32 write_str(struct debug_buffer *buffer, const char *fmt, ...) + { + va_list args; + u32 size; ++ ++ char *curr = buffer->curr; ++ char *end = buffer->ptr + MAX_DBG_BUF_SIZE; ++ + va_start(args, fmt); +- size = vscnprintf(buffer->curr, MAX_DBG_BUF_SIZE - 1, fmt, args); ++ size = vscnprintf(curr, end - curr, fmt, args); + va_end(args); + buffer->curr += size; + buffer->filled_size += size; +@@ -75,12 +80,15 @@ static ssize_t core_info_read(struct file *file, char __user *buf, + struct hfi_device *hdev; + struct hal_fw_info fw_info = { {0} }; + int i = 0, rc = 0; ++ ssize_t len = 0; + + if (!core || !core->device) { + dprintk(VIDC_ERR, "Invalid params, core: %pK\n", core); + return 0; + } + hdev = core->device; ++ ++ mutex_lock(&dbg_buf.lock); + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); + write_str(&dbg_buf, "CORE %d: %pK\n", core->id, core); +@@ -104,8 +112,11 @@ err_fw_info: + completion_done(&core->completions[SYS_MSG_INDEX(i)]) ? + "pending" : "done"); + } +- return simple_read_from_buffer(buf, count, ppos, ++ len = simple_read_from_buffer(buf, count, ppos, + dbg_buf.ptr, dbg_buf.filled_size); ++ ++ mutex_unlock(&dbg_buf.lock); ++ return len; + } + + static const struct file_operations core_info_fops = { +@@ -143,7 +154,10 @@ static const struct file_operations ssr_fops = { + struct dentry *msm_vidc_debugfs_init_drv(void) + { + bool ok = false; +- struct dentry *dir = debugfs_create_dir("msm_vidc", NULL); ++ struct dentry *dir = NULL; ++ ++ mutex_init(&dbg_buf.lock); ++ dir = debugfs_create_dir("msm_vidc", NULL); + if (IS_ERR_OR_NULL(dir)) { + dir = NULL; + goto failed_create_dir; +@@ -212,6 +226,7 @@ struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core, + dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n"); + goto failed_create_dir; + } ++ + if (!debugfs_create_file("info", S_IRUGO, dir, core, &core_info_fops)) { + dprintk(VIDC_ERR, "debugfs_create_file: fail\n"); + goto failed_create_dir; +@@ -266,6 +281,7 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + struct msm_vidc_inst *inst = file->private_data; + struct msm_vidc_core *core = inst ? inst->core : NULL; + int i, j; ++ ssize_t len = 0; + + if (!inst || !core) { + dprintk(VIDC_ERR, "Invalid params, core: %pK inst %pK\n", +@@ -277,6 +293,7 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + return 0; + } + ++ mutex_lock(&dbg_buf.lock); + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); + write_str(&dbg_buf, "INSTANCE: %pK (%s)\n", inst, +@@ -333,9 +350,12 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + write_str(&dbg_buf, "FBD Count: %d\n", inst->count.fbd); + + publish_unreleased_reference(inst); +- put_inst(inst); +- return simple_read_from_buffer(buf, count, ppos, ++ len = simple_read_from_buffer(buf, count, ppos, + dbg_buf.ptr, dbg_buf.filled_size); ++ ++ mutex_unlock(&dbg_buf.lock); ++ put_inst(inst); ++ return len; + } + + static const struct file_operations inst_info_fops = { +@@ -416,3 +436,8 @@ void msm_vidc_debugfs_update(struct msm_vidc_inst *inst, + } + } + ++void msm_vidc_debugfs_deinit_drv(void) ++{ ++ mutex_destroy(&dbg_buf.lock); ++} ++ +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h +index 55485c6..abf8d3a 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h ++++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h +@@ -126,6 +126,7 @@ struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst, + struct dentry *parent); + void msm_vidc_debugfs_update(struct msm_vidc_inst *inst, + enum msm_vidc_debugfs_event e); ++void msm_vidc_debugfs_deinit_drv(void); + + static inline void tic(struct msm_vidc_inst *i, enum profiling_points p, + char *b) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8244/2.patch b/Patches/Linux_CVEs/CVE-2017-8244/2.patch new file mode 100644 index 00000000..9c60f33d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8244/2.patch @@ -0,0 +1,165 @@ +From fe3bdd12315656347d1bca82d920b3df1a2b0e8a Mon Sep 17 00:00:00 2001 +From: Abdulla Anam +Date: Wed, 22 Mar 2017 14:00:10 +0530 +Subject: msm: vidc: Protect debug_buffer access in info_read with lock + +Serialize core_info_read & inst_info_read with lock so that +multiple concurrent threads do not cause the write to +overflow. Also have the bound check to avoid overflow in +write_str function.. + +Change-Id: Ia18a4b94cafd69af1d367861f2499fc202f18e9f +Signed-off-by: Abdulla Anam +--- + drivers/media/platform/msm/vidc/msm_v4l2_vidc.c | 3 +++ + drivers/media/platform/msm/vidc/msm_vidc_debug.c | 33 +++++++++++++++++++++--- + drivers/media/platform/msm/vidc/msm_vidc_debug.h | 1 + + 3 files changed, 33 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +index a632797..a8dc1d0 100644 +--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c ++++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +@@ -766,6 +766,8 @@ static int __init msm_vidc_init(void) + if (rc) { + dprintk(VIDC_ERR, + "Failed to register platform driver\n"); ++ msm_vidc_debugfs_deinit_drv(); ++ debugfs_remove_recursive(vidc_driver->debugfs_root); + kfree(vidc_driver); + vidc_driver = NULL; + } +@@ -776,6 +778,7 @@ static int __init msm_vidc_init(void) + static void __exit msm_vidc_exit(void) + { + platform_driver_unregister(&msm_vidc_driver); ++ msm_vidc_debugfs_deinit_drv(); + debugfs_remove_recursive(vidc_driver->debugfs_root); + mutex_destroy(&vidc_driver->lock); + kfree(vidc_driver); +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +index 1248a1c..a9b367d 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c ++++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c +@@ -38,6 +38,7 @@ bool msm_vidc_debug_timeout = false; + #define MAX_DBG_BUF_SIZE 4096 + + struct debug_buffer { ++ struct mutex lock; + char ptr[MAX_DBG_BUF_SIZE]; + char *curr; + u32 filled_size; +@@ -64,8 +65,12 @@ static u32 write_str(struct debug_buffer *buffer, const char *fmt, ...) + { + va_list args; + u32 size; ++ ++ char *curr = buffer->curr; ++ char *end = buffer->ptr + MAX_DBG_BUF_SIZE; ++ + va_start(args, fmt); +- size = vscnprintf(buffer->curr, MAX_DBG_BUF_SIZE - 1, fmt, args); ++ size = vscnprintf(curr, end - curr, fmt, args); + va_end(args); + buffer->curr += size; + buffer->filled_size += size; +@@ -79,12 +84,15 @@ static ssize_t core_info_read(struct file *file, char __user *buf, + struct hfi_device *hdev; + struct hal_fw_info fw_info = { {0} }; + int i = 0, rc = 0; ++ ssize_t len = 0; + + if (!core || !core->device) { + dprintk(VIDC_ERR, "Invalid params, core: %pK\n", core); + return 0; + } + hdev = core->device; ++ ++ mutex_lock(&dbg_buf.lock); + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); + write_str(&dbg_buf, "CORE %d: %pK\n", core->id, core); +@@ -108,8 +116,11 @@ err_fw_info: + completion_done(&core->completions[SYS_MSG_INDEX(i)]) ? + "pending" : "done"); + } +- return simple_read_from_buffer(buf, count, ppos, ++ len = simple_read_from_buffer(buf, count, ppos, + dbg_buf.ptr, dbg_buf.filled_size); ++ ++ mutex_unlock(&dbg_buf.lock); ++ return len; + } + + static const struct file_operations core_info_fops = { +@@ -147,7 +158,10 @@ static const struct file_operations ssr_fops = { + struct dentry *msm_vidc_debugfs_init_drv(void) + { + bool ok = false; +- struct dentry *dir = debugfs_create_dir("msm_vidc", NULL); ++ struct dentry *dir = NULL; ++ ++ mutex_init(&dbg_buf.lock); ++ dir = debugfs_create_dir("msm_vidc", NULL); + if (IS_ERR_OR_NULL(dir)) { + dir = NULL; + goto failed_create_dir; +@@ -216,6 +230,7 @@ struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core, + dprintk(VIDC_ERR, "Failed to create debugfs for msm_vidc\n"); + goto failed_create_dir; + } ++ + if (!debugfs_create_file("info", S_IRUGO, dir, core, &core_info_fops)) { + dprintk(VIDC_ERR, "debugfs_create_file: fail\n"); + goto failed_create_dir; +@@ -269,11 +284,14 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + { + struct msm_vidc_inst *inst = file->private_data; + int i, j; ++ ssize_t len = 0; + + if (!inst) { + dprintk(VIDC_ERR, "Invalid params, inst %pK\n", inst); + return 0; + } ++ ++ mutex_lock(&dbg_buf.lock); + INIT_DBG_BUF(dbg_buf); + write_str(&dbg_buf, "===============================\n"); + write_str(&dbg_buf, "INSTANCE: %pK (%s)\n", inst, +@@ -331,8 +349,10 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, + + publish_unreleased_reference(inst); + +- return simple_read_from_buffer(buf, count, ppos, ++ len = simple_read_from_buffer(buf, count, ppos, + dbg_buf.ptr, dbg_buf.filled_size); ++ mutex_unlock(&dbg_buf.lock); ++ return len; + } + + static const struct file_operations inst_info_fops = { +@@ -413,3 +433,8 @@ void msm_vidc_debugfs_update(struct msm_vidc_inst *inst, + } + } + ++void msm_vidc_debugfs_deinit_drv(void) ++{ ++ mutex_destroy(&dbg_buf.lock); ++} ++ +diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h +index 39ac627..853ce4b 100644 +--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h ++++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h +@@ -126,6 +126,7 @@ struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst, + struct dentry *parent); + void msm_vidc_debugfs_update(struct msm_vidc_inst *inst, + enum msm_vidc_debugfs_event e); ++void msm_vidc_debugfs_deinit_drv(void); + + static inline void tic(struct msm_vidc_inst *i, enum profiling_points p, + char *b) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8245/0.patch b/Patches/Linux_CVEs/CVE-2017-8245/0.patch new file mode 100644 index 00000000..5d5d5ed8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8245/0.patch @@ -0,0 +1,106 @@ +From ececf97911515114030bef1fc6df630dbb706f17 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Tue, 28 Feb 2017 12:52:30 -0800 +Subject: drivers: soc: add size check + +Add size check to ensure the payload fits inside the declared payload +size to prevent loss of data when copying. + +CRs-Fixed: 2009224 +Signed-off-by: Siena Richard +Change-Id: I4275c626605272941143b54a7b8861b25f8e750a +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 57 ++++++++++++++++++++++++++++-------- + 1 file changed, 44 insertions(+), 13 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index 10f71b8..fe54589 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -368,6 +368,9 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + struct voice_svc_prvt *prtd; + struct voice_svc_write_msg *data = NULL; + uint32_t cmd; ++ struct voice_svc_register *register_data = NULL; ++ struct voice_svc_cmd_request *request_data = NULL; ++ uint32_t request_payload_size; + + pr_debug("%s\n", __func__); + +@@ -416,12 +419,19 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + */ + if (count == (sizeof(struct voice_svc_write_msg) + + sizeof(struct voice_svc_register))) { +- ret = process_reg_cmd( +- (struct voice_svc_register *)data->payload, prtd); ++ register_data = ++ (struct voice_svc_register *)data->payload; ++ if (register_data == NULL) { ++ pr_err("%s: register data is NULL", __func__); ++ ret = -EINVAL; ++ goto done; ++ } ++ ret = process_reg_cmd(register_data, prtd); + if (!ret) + ret = count; + } else { +- pr_err("%s: invalid payload size\n", __func__); ++ pr_err("%s: invalid data payload size for register command\n", ++ __func__); + ret = -EINVAL; + goto done; + } +@@ -430,19 +440,40 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + /* + * Check that count reflects the expected size to ensure + * sufficient memory was allocated. Since voice_svc_cmd_request +- * has a variable size, check the minimum value count must be. ++ * has a variable size, check the minimum value count must be to ++ * parse the message request then check the minimum size to hold ++ * the payload of the message request. + */ + if (count >= (sizeof(struct voice_svc_write_msg) + + sizeof(struct voice_svc_cmd_request))) { +- ret = voice_svc_send_req( +- (struct voice_svc_cmd_request *)data->payload, prtd); +- if (!ret) +- ret = count; +- } else { +- pr_err("%s: invalid payload size\n", __func__); +- ret = -EINVAL; +- goto done; +- } ++ request_data = ++ (struct voice_svc_cmd_request *)data->payload; ++ if (request_data == NULL) { ++ pr_err("%s: request data is NULL", __func__); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ request_payload_size = request_data->payload_size; ++ ++ if (count >= (sizeof(struct voice_svc_write_msg) + ++ sizeof(struct voice_svc_cmd_request) + ++ request_payload_size)) { ++ ret = voice_svc_send_req(request_data, prtd); ++ if (!ret) ++ ret = count; ++ } else { ++ pr_err("%s: invalid request payload size\n", ++ __func__); ++ ret = -EINVAL; ++ goto done; ++ } ++ } else { ++ pr_err("%s: invalid data payload size for request command\n", ++ __func__); ++ ret = -EINVAL; ++ goto done; ++ } + break; + default: + pr_debug("%s: Invalid command: %u\n", __func__, cmd); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8245/1.patch b/Patches/Linux_CVEs/CVE-2017-8245/1.patch new file mode 100644 index 00000000..b7272ac3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8245/1.patch @@ -0,0 +1,99 @@ +From f53af3805879292423465cd0877cc7a75131ce10 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Tue, 28 Feb 2017 12:52:30 -0800 +Subject: drivers: soc: add size check + +Add size check to ensure the payload fits inside the declared payload +size to prevent loss of data when copying. + +CRs-Fixed: 2009224 +Signed-off-by: Siena Richard +Change-Id: I4275c626605272941143b54a7b8861b25f8e750a +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 49 +++++++++++++++++++++++++++++------- + 1 file changed, 40 insertions(+), 9 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index fbd90bc..fe54589 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -368,6 +368,9 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + struct voice_svc_prvt *prtd; + struct voice_svc_write_msg *data = NULL; + uint32_t cmd; ++ struct voice_svc_register *register_data = NULL; ++ struct voice_svc_cmd_request *request_data = NULL; ++ uint32_t request_payload_size; + + pr_debug("%s\n", __func__); + +@@ -416,12 +419,19 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + */ + if (count == (sizeof(struct voice_svc_write_msg) + + sizeof(struct voice_svc_register))) { +- ret = process_reg_cmd( +- (struct voice_svc_register *)data->payload, prtd); ++ register_data = ++ (struct voice_svc_register *)data->payload; ++ if (register_data == NULL) { ++ pr_err("%s: register data is NULL", __func__); ++ ret = -EINVAL; ++ goto done; ++ } ++ ret = process_reg_cmd(register_data, prtd); + if (!ret) + ret = count; + } else { +- pr_err("%s: invalid payload size\n", __func__); ++ pr_err("%s: invalid data payload size for register command\n", ++ __func__); + ret = -EINVAL; + goto done; + } +@@ -430,16 +440,37 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + /* + * Check that count reflects the expected size to ensure + * sufficient memory was allocated. Since voice_svc_cmd_request +- * has a variable size, check the minimum value count must be. ++ * has a variable size, check the minimum value count must be to ++ * parse the message request then check the minimum size to hold ++ * the payload of the message request. + */ + if (count >= (sizeof(struct voice_svc_write_msg) + + sizeof(struct voice_svc_cmd_request))) { +- ret = voice_svc_send_req( +- (struct voice_svc_cmd_request *)data->payload, prtd); +- if (!ret) +- ret = count; ++ request_data = ++ (struct voice_svc_cmd_request *)data->payload; ++ if (request_data == NULL) { ++ pr_err("%s: request data is NULL", __func__); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ request_payload_size = request_data->payload_size; ++ ++ if (count >= (sizeof(struct voice_svc_write_msg) + ++ sizeof(struct voice_svc_cmd_request) + ++ request_payload_size)) { ++ ret = voice_svc_send_req(request_data, prtd); ++ if (!ret) ++ ret = count; ++ } else { ++ pr_err("%s: invalid request payload size\n", ++ __func__); ++ ret = -EINVAL; ++ goto done; ++ } + } else { +- pr_err("%s: invalid payload size\n", __func__); ++ pr_err("%s: invalid data payload size for request command\n", ++ __func__); + ret = -EINVAL; + goto done; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8245/2.patch b/Patches/Linux_CVEs/CVE-2017-8245/2.patch new file mode 100644 index 00000000..84c63526 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8245/2.patch @@ -0,0 +1,106 @@ +From 5b2f6e011ba92f28e8d7dbeb11c4ee7344c33186 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Tue, 28 Feb 2017 12:52:30 -0800 +Subject: drivers: soc: add size check + +Add size check to ensure the payload fits inside the declared payload +size to prevent loss of data when copying. + +CRs-Fixed: 2009224 +Signed-off-by: Siena Richard +Change-Id: I4275c626605272941143b54a7b8861b25f8e750a +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 57 ++++++++++++++++++++++++++++-------- + 1 file changed, 44 insertions(+), 13 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index 10f71b8..fe54589 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -368,6 +368,9 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + struct voice_svc_prvt *prtd; + struct voice_svc_write_msg *data = NULL; + uint32_t cmd; ++ struct voice_svc_register *register_data = NULL; ++ struct voice_svc_cmd_request *request_data = NULL; ++ uint32_t request_payload_size; + + pr_debug("%s\n", __func__); + +@@ -416,12 +419,19 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + */ + if (count == (sizeof(struct voice_svc_write_msg) + + sizeof(struct voice_svc_register))) { +- ret = process_reg_cmd( +- (struct voice_svc_register *)data->payload, prtd); ++ register_data = ++ (struct voice_svc_register *)data->payload; ++ if (register_data == NULL) { ++ pr_err("%s: register data is NULL", __func__); ++ ret = -EINVAL; ++ goto done; ++ } ++ ret = process_reg_cmd(register_data, prtd); + if (!ret) + ret = count; + } else { +- pr_err("%s: invalid payload size\n", __func__); ++ pr_err("%s: invalid data payload size for register command\n", ++ __func__); + ret = -EINVAL; + goto done; + } +@@ -430,19 +440,40 @@ static ssize_t voice_svc_write(struct file *file, const char __user *buf, + /* + * Check that count reflects the expected size to ensure + * sufficient memory was allocated. Since voice_svc_cmd_request +- * has a variable size, check the minimum value count must be. ++ * has a variable size, check the minimum value count must be to ++ * parse the message request then check the minimum size to hold ++ * the payload of the message request. + */ + if (count >= (sizeof(struct voice_svc_write_msg) + + sizeof(struct voice_svc_cmd_request))) { +- ret = voice_svc_send_req( +- (struct voice_svc_cmd_request *)data->payload, prtd); +- if (!ret) +- ret = count; +- } else { +- pr_err("%s: invalid payload size\n", __func__); +- ret = -EINVAL; +- goto done; +- } ++ request_data = ++ (struct voice_svc_cmd_request *)data->payload; ++ if (request_data == NULL) { ++ pr_err("%s: request data is NULL", __func__); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ request_payload_size = request_data->payload_size; ++ ++ if (count >= (sizeof(struct voice_svc_write_msg) + ++ sizeof(struct voice_svc_cmd_request) + ++ request_payload_size)) { ++ ret = voice_svc_send_req(request_data, prtd); ++ if (!ret) ++ ret = count; ++ } else { ++ pr_err("%s: invalid request payload size\n", ++ __func__); ++ ret = -EINVAL; ++ goto done; ++ } ++ } else { ++ pr_err("%s: invalid data payload size for request command\n", ++ __func__); ++ ret = -EINVAL; ++ goto done; ++ } + break; + default: + pr_debug("%s: Invalid command: %u\n", __func__, cmd); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8246/0.patch b/Patches/Linux_CVEs/CVE-2017-8246/0.patch new file mode 100644 index 00000000..050ef057 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8246/0.patch @@ -0,0 +1,116 @@ +From 578eb74435eccdc3df516fd744941a7d872fac6c Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Fri, 24 Feb 2017 16:13:20 +0800 +Subject: ASoC: msm: qdsp6v2: set pointer to NULL after free. + +Pointer after kfree is not sanitized. +Set pointer to NULL. + +CRs-Fixed: 2008031 +Change-Id: Ia59a57fcd142a6ed18d168992b8da4019314afa4 +Signed-off-by: Xiaojun Sang +Signed-off-by: Bikshapathi Kothapeta +--- + sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 1 + + sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c | 3 ++- + sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c | 3 ++- + sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c | 3 ++- + sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c | 5 ++++- + 5 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +index 245d2f5..0cd60c8 100644 +--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +@@ -1138,6 +1138,7 @@ static int msm_compr_free(struct snd_compr_stream *cstream) + kfree(pdata->dec_params[soc_prtd->dai_link->be_id]); + pdata->dec_params[soc_prtd->dai_link->be_id] = NULL; + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +index d3d18917..8ab83d2 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -499,6 +499,7 @@ done: + mutex_unlock(&prtd->lock); + prtd->prepared--; + kfree(prtd); ++ runtime->private_data = NULL; + return 0; + } + static int msm_afe_prepare(struct snd_pcm_substream *substream) +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c +index 64d3fe0..507d01a 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2014, 2017, The 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 +@@ -497,6 +497,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) + + pr_debug("%s\n", __func__); + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +index 7c69081..de126e1 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2016-2017, The 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 +@@ -517,6 +517,7 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) + SNDRV_PCM_STREAM_PLAYBACK : + SNDRV_PCM_STREAM_CAPTURE); + kfree(prtd); ++ runtime->private_data = NULL; + return 0; + } + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +index 455607b..b8dbc63 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -721,6 +721,8 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) + msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, + SNDRV_PCM_STREAM_PLAYBACK); + kfree(prtd); ++ runtime->private_data = NULL; ++ + return 0; + } + +@@ -824,6 +826,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream) + msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, + SNDRV_PCM_STREAM_CAPTURE); + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8246/1.patch b/Patches/Linux_CVEs/CVE-2017-8246/1.patch new file mode 100644 index 00000000..7955c943 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8246/1.patch @@ -0,0 +1,124 @@ +From 30baaec8afb05abf9f794c631ad944838d498ab8 Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Fri, 24 Feb 2017 16:13:20 +0800 +Subject: ASoC: msm: qdsp6v2: set pointer to NULL after free + +Pointer after kfree is not sanitized. +Set pointer to NULL. + +CRs-Fixed: 2008031 +Change-Id: Ia59a57fcd142a6ed18d168992b8da4019314afa4 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 2 ++ + sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c | 3 ++- + sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c | 3 ++- + sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c | 4 +++- + sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c | 5 ++++- + 5 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +index c49a4de..90741ce 100644 +--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +@@ -1599,6 +1599,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream) + kfree(pdata->dec_params[soc_prtd->dai_link->be_id]); + pdata->dec_params[soc_prtd->dai_link->be_id] = NULL; + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +@@ -1658,6 +1659,7 @@ static int msm_compr_capture_free(struct snd_compr_stream *cstream) + q6asm_audio_client_free(ac); + + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +index d65108e..b1a1ea5 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -684,6 +684,7 @@ done: + mutex_unlock(&prtd->lock); + prtd->prepared--; + kfree(prtd); ++ runtime->private_data = NULL; + return 0; + } + static int msm_afe_prepare(struct snd_pcm_substream *substream) +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c +index 65c0e51..a7619fd 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -478,6 +478,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) + + pr_debug("%s\n", __func__); + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +index 0612318..289049c 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2016-2017, The 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 +@@ -544,6 +544,8 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) + SNDRV_PCM_STREAM_PLAYBACK : + SNDRV_PCM_STREAM_CAPTURE); + kfree(prtd); ++ runtime->private_data = NULL; ++ + return 0; + } + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +index 07f82952..b9a1d57 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -755,6 +755,8 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) + msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, + SNDRV_PCM_STREAM_PLAYBACK); + kfree(prtd); ++ runtime->private_data = NULL; ++ + return 0; + } + +@@ -860,6 +862,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream) + msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, + SNDRV_PCM_STREAM_CAPTURE); + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8246/2.patch b/Patches/Linux_CVEs/CVE-2017-8246/2.patch new file mode 100644 index 00000000..2db95a61 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8246/2.patch @@ -0,0 +1,93 @@ +From 9734b72ae21eca557540c3c42d356dd131a20004 Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Fri, 24 Feb 2017 16:13:20 +0800 +Subject: ASoC: msm: qdsp6v2: set pointer to NULL after free + +Unsanitized pointer after kfree leads to potential risk. +Set pointer to NULL. + +CRs-Fixed: 2008031 +Change-Id: Ia59a57fcd142a6ed18d168992b8da4019314afa4 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 2 ++ + sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c | 3 ++- + sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c | 2 ++ + sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c | 3 +++ + 4 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +index 7f032dc..9a40dad 100644 +--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +@@ -1586,6 +1586,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream) + kfree(pdata->dec_params[soc_prtd->dai_link->be_id]); + pdata->dec_params[soc_prtd->dai_link->be_id] = NULL; + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +@@ -1645,6 +1646,7 @@ static int msm_compr_capture_free(struct snd_compr_stream *cstream) + q6asm_audio_client_free(ac); + + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +index d65108e..b1a1ea5 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The 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 +@@ -684,6 +684,7 @@ done: + mutex_unlock(&prtd->lock); + prtd->prepared--; + kfree(prtd); ++ runtime->private_data = NULL; + return 0; + } + static int msm_afe_prepare(struct snd_pcm_substream *substream) +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +index 33c5b64..9c24712 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +@@ -570,6 +570,8 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) + SNDRV_PCM_STREAM_PLAYBACK : + SNDRV_PCM_STREAM_CAPTURE); + kfree(prtd); ++ runtime->private_data = NULL; ++ + return 0; + } + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +index e14f410..7928c37 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +@@ -804,6 +804,8 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) + msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, + SNDRV_PCM_STREAM_PLAYBACK); + kfree(prtd); ++ runtime->private_data = NULL; ++ + return 0; + } + +@@ -909,6 +911,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream) + msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, + SNDRV_PCM_STREAM_CAPTURE); + kfree(prtd); ++ runtime->private_data = NULL; + + return 0; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8247/0.patch b/Patches/Linux_CVEs/CVE-2017-8247/0.patch new file mode 100644 index 00000000..b7337300 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8247/0.patch @@ -0,0 +1,35 @@ +From 84f8c42e5d848b1d04f49d253f98296e8c2280b9 Mon Sep 17 00:00:00 2001 +From: Trishansh Bhardwaj +Date: Fri, 7 Apr 2017 11:16:29 +0530 +Subject: msm: camera: Allow driver file to be opend only once. + +Use proper synchronization to ensure driver file is opened +only once. + +CRs-Fixed: 2023513 +Change-Id: I71e55e2d487fe561d3f596590b3e8102c5e921b5 +Signed-off-by: Trishansh Bhardwaj +--- + drivers/media/platform/msm/camera_v2/msm.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c +index c2b42a8..d8bdef5 100644 +--- a/drivers/media/platform/msm/camera_v2/msm.c ++++ b/drivers/media/platform/msm/camera_v2/msm.c +@@ -1012,11 +1012,9 @@ static int msm_open(struct file *filep) + BUG_ON(!pvdev); + + /* !!! only ONE open is allowed !!! */ +- if (atomic_read(&pvdev->opened)) ++ if (atomic_cmpxchg(&pvdev->opened, 0, 1)) + return -EBUSY; + +- atomic_set(&pvdev->opened, 1); +- + spin_lock_irqsave(&msm_pid_lock, flags); + msm_pid = get_pid(task_pid(current)); + spin_unlock_irqrestore(&msm_pid_lock, flags); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8250/0.patch b/Patches/Linux_CVEs/CVE-2017-8250/0.patch new file mode 100644 index 00000000..93ed6a1d --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8250/0.patch @@ -0,0 +1,40 @@ +From 9be5b16de622c2426408425e3df29e945cd21d37 Mon Sep 17 00:00:00 2001 +From: Kasin Li +Date: Wed, 22 Feb 2017 18:25:36 +0800 +Subject: drm/msm: Fix potential buffer overflow issue + +In function submit_create, if nr_cmds or nr_bos is assigned with +negative value, the allocated buffer may be small than intended. +Using this buffer will lead to buffer overflow issue. + +Change-Id: I0b61cccffd836e2dd3c859446470af4b6451b9ed +Signed-off-by: Kasin Li +--- + drivers/gpu/drm/msm/msm_gem_submit.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index adbb0cb..fa9b641 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -34,12 +34,15 @@ static inline void __user *to_user_ptr(u64 address) + } + + static struct msm_gem_submit *submit_create(struct drm_device *dev, +- struct msm_gpu *gpu, int nr_cmds, int nr_bos) ++ struct msm_gpu *gpu, uint32_t nr_cmds, uint32_t nr_bos) + { + struct msm_gem_submit *submit; +- int sz = sizeof(*submit) + (nr_bos * sizeof(submit->bos[0])) + ++ uint64_t sz = sizeof(*submit) + (nr_bos * sizeof(submit->bos[0])) + + (nr_cmds * sizeof(submit->cmd[0])); + ++ if (sz > SIZE_MAX) ++ return NULL; ++ + submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); + if (submit) { + submit->dev = dev; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8251/0.patch b/Patches/Linux_CVEs/CVE-2017-8251/0.patch new file mode 100644 index 00000000..8a334400 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8251/0.patch @@ -0,0 +1,64 @@ +From 3a42f1b79ed696f29350f170c00f27712ae84a36 Mon Sep 17 00:00:00 2001 +From: Maggie White +Date: Wed, 5 Jul 2017 13:00:40 -0700 +Subject: msm: camera: isp: fix for out of bound access array + +There is no bound check in stream_cfg_cmd->num_streams and it's used in +several places as a maximum index into the stream_cfg_cmd->stream_handle +array which has a size of 15. Current code didn't check the maximum +index to make sure it didn't exceed the array size. + +Bug: 62379525 +Change-Id: Idcf639486d235551882dafc34d9e798d78c70bf0 +Signed-off-by: Maggie White +--- + .../platform/msm/camera_v2/isp/msm_isp_stats_util.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +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 82da3e0..43a2c77 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 +@@ -550,6 +550,12 @@ static int msm_isp_stats_update_cgc_override(struct vfe_device *vfe_dev, + int i; + uint32_t stats_mask = 0, idx; + ++ if (stream_cfg_cmd->num_streams > MSM_ISP_STATS_MAX) { ++ pr_err("%s invalid num_streams %d\n", __func__, ++ stream_cfg_cmd->num_streams); ++ return -EINVAL; ++ } ++ + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { + idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); + +@@ -630,6 +636,13 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, + stats_data->stream_info); + if (rc < 0) + return rc; ++ ++ if (stream_cfg_cmd->num_streams > MSM_ISP_STATS_MAX) { ++ pr_err("%s invalid num_streams %d\n", __func__, ++ stream_cfg_cmd->num_streams); ++ return -EINVAL; ++ } ++ + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { + idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); + +@@ -702,6 +715,12 @@ static int msm_isp_stop_stats_stream(struct vfe_device *vfe_dev, + num_stats_comp_mask = + vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask; + ++ if (stream_cfg_cmd->num_streams > MSM_ISP_STATS_MAX) { ++ pr_err("%s invalid num_streams %d\n", __func__, ++ stream_cfg_cmd->num_streams); ++ return -EINVAL; ++ } ++ + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { + + idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8253/0.patch b/Patches/Linux_CVEs/CVE-2017-8253/0.patch new file mode 100644 index 00000000..f13ac465 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8253/0.patch @@ -0,0 +1,69 @@ +From a5f07894058c4198f61e533d727b343c5be879b0 Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Tue, 15 Nov 2016 12:26:47 -0800 +Subject: msm: camera: sensor: Add boundary check for cci master + +Add boundary check for cci master in i2c_read. +This value is passed from userpsace. If user sends an +invalid number for master there is a possibility of +accessing unintended buffer. + +This change addresses the issue. + +Crs-Fixed: 1086764 +Signed-off-by: Rajesh Bondugula +Change-Id: Ice3bde902aea96382ceb4dfddfd28a5ea89c183d +--- + .../media/platform/msm/camera_v2/sensor/cci/msm_cci.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 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 b1c2382..2412ed2 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 +@@ -776,10 +776,18 @@ static int32_t msm_cci_i2c_read(struct v4l2_subdev *sd, + enum cci_i2c_queue_t queue = QUEUE_1; + struct cci_device *cci_dev = NULL; + struct msm_camera_cci_i2c_read_cfg *read_cfg = NULL; ++ + CDBG("%s line %d\n", __func__, __LINE__); + cci_dev = v4l2_get_subdevdata(sd); + master = c_ctrl->cci_info->cci_i2c_master; + read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg; ++ ++ if (master >= MASTER_MAX || master < 0) { ++ pr_err("%s:%d Invalid I2C master %d\n", ++ __func__, __LINE__, master); ++ return -EINVAL; ++ } ++ + mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]); + + /* Set the I2C Frequency */ +@@ -1004,11 +1012,6 @@ static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd, + enum cci_i2c_master_t master; + + cci_dev = v4l2_get_subdevdata(sd); +- if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX +- || c_ctrl->cci_info->cci_i2c_master < 0) { +- pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__); +- return -EINVAL; +- } + if (cci_dev->cci_state != CCI_STATE_ENABLED) { + pr_err("%s invalid cci state %d\n", + __func__, cci_dev->cci_state); +@@ -1539,6 +1542,11 @@ static int32_t msm_cci_write(struct v4l2_subdev *sd, + return rc; + } + ++ if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX ++ || c_ctrl->cci_info->cci_i2c_master < 0) { ++ pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__); ++ return -EINVAL; ++ } + master = c_ctrl->cci_info->cci_i2c_master; + cci_master_info = &cci_dev->cci_master_info[master]; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8254/0.patch b/Patches/Linux_CVEs/CVE-2017-8254/0.patch new file mode 100644 index 00000000..9e7246e8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8254/0.patch @@ -0,0 +1,41 @@ +From 70afce1d9be745005c48fd565c01ce452a565e7e Mon Sep 17 00:00:00 2001 +From: Aravind Kumar +Date: Mon, 11 May 2015 15:26:27 +0530 +Subject: ASoC: msm: qdsp6v2: check audio client pointer before accessing + +In the registered callback for q6asm, we are checking if +the audio client pointer is valid and also, dereferencing it +to get the session ID even though it could be invalid or expired. +Return and exit immediately if the audio client pointer is +invalid. + +CRs-Fixed: 832914 +Change-Id: I96b722b584a4b5adf8a33891abd75a320e76ea25 +Signed-off-by: Aravind Kumar +--- + sound/soc/msm/qdsp6v2/q6asm.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c +index 9a1e0e7..f6a5cb0 100644 +--- a/sound/soc/msm/qdsp6v2/q6asm.c ++++ b/sound/soc/msm/qdsp6v2/q6asm.c +@@ -1451,8 +1451,13 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv) + pr_err("%s: data NULL\n", __func__); + return -EINVAL; + } +- if (ac->session <= 0 || ac->session > 8 || +- !q6asm_is_valid_audio_client(ac)) { ++ if (!q6asm_is_valid_audio_client(ac)) { ++ pr_err("%s: audio client pointer is invalid, ac = %p\n", ++ __func__, ac); ++ return -EINVAL; ++ } ++ ++ if (ac->session <= 0 || ac->session > 8) { + pr_err("%s: Session ID is invalid, session = %d\n", __func__, + ac->session); + return -EINVAL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8256/0.patch b/Patches/Linux_CVEs/CVE-2017-8256/0.patch new file mode 100644 index 00000000..4a4f5b64 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8256/0.patch @@ -0,0 +1,32 @@ +From 75e1e00d6b3cd4cb89fd5314a60c333aa0b03230 Mon Sep 17 00:00:00 2001 +From: Manjeet Singh +Date: Thu, 22 Dec 2016 18:17:17 +0530 +Subject: qcacld-2.0: Add bounday check for multicastAddr array + +In hdd_set_rx_filter API multicastAddr array being accessed beyond +its size. + +Add boundary check for multicastAddr. + +CRs-Fixed: 1104565 +Change-Id: I8e1543a8f42ac40c04d2c6a17e69718d13cbd706 +--- + CORE/HDD/src/wlan_hdd_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c +index 4020488..fab1eac 100644 +--- a/CORE/HDD/src/wlan_hdd_main.c ++++ b/CORE/HDD/src/wlan_hdd_main.c +@@ -4722,6 +4722,8 @@ static int hdd_set_rx_filter(hdd_adapter_t *adapter, bool action, + MAC_ADDR_ARRAY(filter->multicastAddr[j])); + j++; + } ++ if (j == SIR_MAX_NUM_MULTICAST_ADDRESS) ++ break; + } + filter->ulMulticastAddrCnt = j; + /* Set rx filter */ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8257/0.patch b/Patches/Linux_CVEs/CVE-2017-8257/0.patch new file mode 100644 index 00000000..d8298314 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8257/0.patch @@ -0,0 +1,182 @@ +From 0f19fbd00c6679bbc524f7a6d0fc3d54cfd1c9ae Mon Sep 17 00:00:00 2001 +From: Benjamin Chan +Date: Fri, 17 Feb 2017 14:49:45 -0500 +Subject: msm: sde: Add mutex lock for debug buffer access in rotator + +Adding mutex lock access protection to debug buffer for SDE rotator. The +buffer can be shared between multiple processes, and it is possible that +one process try to free the buffer while another process is still +accessing it. + +CRs-Fixed: 2003129 +Change-Id: Ib20767f02ba7f14fb972d5c50ab264b2309a1ec2 +Signed-off-by: Benjamin Chan +--- + .../platform/msm/sde/rotator/sde_rotator_debug.c | 39 +++++++++++++++++++--- + .../platform/msm/sde/rotator/sde_rotator_debug.h | 3 +- + 2 files changed, 36 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c +index a2da663..f41382b 100644 +--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c ++++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c +@@ -990,11 +990,14 @@ static int sde_rotator_debug_base_release(struct inode *inode, + { + struct sde_rotator_debug_base *dbg = file->private_data; + +- if (dbg && dbg->buf) { ++ if (dbg) { ++ mutex_lock(&dbg->buflock); + kfree(dbg->buf); + dbg->buf_len = 0; + dbg->buf = NULL; ++ mutex_unlock(&dbg->buflock); + } ++ + return 0; + } + +@@ -1026,8 +1029,10 @@ static ssize_t sde_rotator_debug_base_offset_write(struct file *file, + if (cnt > (dbg->max_offset - off)) + cnt = dbg->max_offset - off; + ++ mutex_lock(&dbg->buflock); + dbg->off = off; + dbg->cnt = cnt; ++ mutex_unlock(&dbg->buflock); + + SDEROT_DBG("offset=%x cnt=%x\n", off, cnt); + +@@ -1047,7 +1052,10 @@ static ssize_t sde_rotator_debug_base_offset_read(struct file *file, + if (*ppos) + return 0; /* the end */ + ++ mutex_lock(&dbg->buflock); + len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt); ++ mutex_unlock(&dbg->buflock); ++ + if (len < 0 || len >= sizeof(buf)) + return 0; + +@@ -1086,6 +1094,8 @@ static ssize_t sde_rotator_debug_base_reg_write(struct file *file, + if (off >= dbg->max_offset) + return -EFAULT; + ++ mutex_lock(&dbg->buflock); ++ + /* Enable Clock for register access */ + sde_rotator_clk_ctrl(dbg->mgr, true); + +@@ -1094,6 +1104,8 @@ static ssize_t sde_rotator_debug_base_reg_write(struct file *file, + /* Disable Clock after register access */ + sde_rotator_clk_ctrl(dbg->mgr, false); + ++ mutex_unlock(&dbg->buflock); ++ + SDEROT_DBG("addr=%zx data=%x\n", off, data); + + return count; +@@ -1104,12 +1116,14 @@ static ssize_t sde_rotator_debug_base_reg_read(struct file *file, + { + struct sde_rotator_debug_base *dbg = file->private_data; + size_t len; ++ int rc = 0; + + if (!dbg) { + SDEROT_ERR("invalid handle\n"); + return -ENODEV; + } + ++ mutex_lock(&dbg->buflock); + if (!dbg->buf) { + char dump_buf[64]; + char *ptr; +@@ -1121,7 +1135,8 @@ static ssize_t sde_rotator_debug_base_reg_read(struct file *file, + + if (!dbg->buf) { + SDEROT_ERR("not enough memory to hold reg dump\n"); +- return -ENOMEM; ++ rc = -ENOMEM; ++ goto debug_read_error; + } + + ptr = dbg->base + dbg->off; +@@ -1151,18 +1166,26 @@ static ssize_t sde_rotator_debug_base_reg_read(struct file *file, + dbg->buf_len = tot; + } + +- if (*ppos >= dbg->buf_len) +- return 0; /* done reading */ ++ if (*ppos >= dbg->buf_len) { ++ rc = 0; /* done reading */ ++ goto debug_read_error; ++ } + + len = min(count, dbg->buf_len - (size_t) *ppos); + if (copy_to_user(user_buf, dbg->buf + *ppos, len)) { + SDEROT_ERR("failed to copy to user\n"); +- return -EFAULT; ++ rc = -EFAULT; ++ goto debug_read_error; + } + + *ppos += len; /* increase offset */ + ++ mutex_unlock(&dbg->buflock); + return len; ++ ++debug_read_error: ++ mutex_unlock(&dbg->buflock); ++ return rc; + } + + static const struct file_operations sde_rotator_off_fops = { +@@ -1196,6 +1219,9 @@ int sde_rotator_debug_register_base(struct sde_rotator_device *rot_dev, + if (!dbg) + return -ENOMEM; + ++ mutex_init(&dbg->buflock); ++ mutex_lock(&dbg->buflock); ++ + if (name) + strlcpy(dbg->name, name, sizeof(dbg->name)); + dbg->base = io_data->base; +@@ -1217,6 +1243,7 @@ int sde_rotator_debug_register_base(struct sde_rotator_device *rot_dev, + dbg->base += rot_dev->mdata->regdump ? + rot_dev->mdata->regdump[0].offset : 0; + } ++ mutex_unlock(&dbg->buflock); + + strlcpy(dbgname + prefix_len, "off", sizeof(dbgname) - prefix_len); + ent_off = debugfs_create_file(dbgname, 0644, debugfs_root, dbg, +@@ -1234,7 +1261,9 @@ int sde_rotator_debug_register_base(struct sde_rotator_device *rot_dev, + goto reg_fail; + } + ++ mutex_lock(&dbg->buflock); + dbg->mgr = rot_dev->mgr; ++ mutex_unlock(&dbg->buflock); + + return 0; + reg_fail: +diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h +index c2c6f97..c6d0151 100644 +--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h ++++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2017, The 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 +@@ -53,6 +53,7 @@ struct sde_rotator_debug_base { + char *buf; + size_t buf_len; + struct sde_rot_mgr *mgr; ++ struct mutex buflock; + }; + + #if defined(CONFIG_DEBUG_FS) +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8259/0.patch b/Patches/Linux_CVEs/CVE-2017-8259/0.patch new file mode 100644 index 00000000..0e034318 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8259/0.patch @@ -0,0 +1,50 @@ +From 68020103af00280393da10039b968c95d68e526c Mon Sep 17 00:00:00 2001 +From: Puja Gupta +Date: Mon, 6 Mar 2017 15:04:11 -0800 +Subject: soc: qcom: Avoid possible buffer overflow in service-locator + +Fix possible buffer overflow by reading 'resp->total_domains' from the +qmi response message since 'resp->total_domains' indicate total number +of matching domains found by servreg. +'resp->domain_list_len' indicates the domains that could be sent in one +response which should not be greater than 'resp->total_domains'. + +CRs-Fixed: 2009016 +Change-Id: I614561c5f9bc996689129bc098baaffc9b59c377 +Signed-off-by: Puja Gupta +--- + drivers/soc/qcom/service-locator.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c +index 8581ed5..0d6c1d6 100644 +--- a/drivers/soc/qcom/service-locator.c ++++ b/drivers/soc/qcom/service-locator.c +@@ -266,10 +266,9 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd) + if (!domains_read) { + db_rev_count = pd->db_rev_count = resp->db_rev_count; + pd->total_domains = resp->total_domains; +- if (!pd->total_domains && resp->domain_list_len) { +- pr_err("total domains not set\n"); +- pd->total_domains = resp->domain_list_len; +- } ++ if (!resp->total_domains) ++ pr_info("No matching domains found\n"); ++ + pd->domain_list = kmalloc( + sizeof(struct servreg_loc_entry_v01) * + resp->total_domains, GFP_KERNEL); +@@ -286,6 +285,10 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd) + rc = -EAGAIN; + goto out; + } ++ if (resp->domain_list_len > resp->total_domains) { ++ /* Always read total_domains from the response msg */ ++ resp->domain_list_len = resp->total_domains; ++ } + /* Copy the response*/ + store_get_domain_list_response(pd, resp, domains_read); + domains_read += resp->domain_list_len; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8260/0.patch b/Patches/Linux_CVEs/CVE-2017-8260/0.patch new file mode 100644 index 00000000..4dcd6ac3 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8260/0.patch @@ -0,0 +1,82 @@ +From 52a2a62a5b0e9dd917bcd9a6d86d674833cc91b7 Mon Sep 17 00:00:00 2001 +From: Gaoxiang Chen +Date: Fri, 31 Mar 2017 14:28:33 +0800 +Subject: msm: camera: don't cut to 8bits for validating enum variable + +In msm_ispif_is_intf_valid(), +we convert a enum variable msm_ispif_vfe_intf, +to uint8_t type for validating. + +This could cause potential issue, +if the value is crafted in such a way that lower 8bits pass the validation. + +Don't use uint8_t as input parm to avoid such vulnerability. + +CRs-Fixed: 2008469 +Change-Id: I4ee400ac0edd830decfbe5712966d968976a268a +Signed-off-by: Gaoxiang Chen +--- + drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +index 4e07d4d..8409a64 100644 +--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c ++++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +@@ -64,7 +64,7 @@ static void msm_ispif_io_dump_reg(struct ispif_device *ispif) + + + static inline int msm_ispif_is_intf_valid(uint32_t csid_version, +- uint8_t intf_type) ++ enum msm_ispif_vfe_intf intf_type) + { + return ((csid_version <= CSID_VERSION_V22 && intf_type != VFE0) || + (intf_type >= VFE_MAX)) ? false : true; +@@ -347,7 +347,7 @@ static int msm_ispif_subdev_g_chip_ident(struct v4l2_subdev *sd, + } + + static void msm_ispif_sel_csid_core(struct ispif_device *ispif, +- uint8_t intftype, uint8_t csid, uint8_t vfe_intf) ++ uint8_t intftype, uint8_t csid, enum msm_ispif_vfe_intf vfe_intf) + { + uint32_t data; + +@@ -387,7 +387,7 @@ static void msm_ispif_sel_csid_core(struct ispif_device *ispif, + } + + static void msm_ispif_enable_crop(struct ispif_device *ispif, +- uint8_t intftype, uint8_t vfe_intf, uint16_t start_pixel, ++ uint8_t intftype, enum msm_ispif_vfe_intf vfe_intf, uint16_t start_pixel, + uint16_t end_pixel) + { + uint32_t data; +@@ -419,7 +419,7 @@ static void msm_ispif_enable_crop(struct ispif_device *ispif, + } + + static void msm_ispif_enable_intf_cids(struct ispif_device *ispif, +- uint8_t intftype, uint16_t cid_mask, uint8_t vfe_intf, uint8_t enable) ++ uint8_t intftype, uint16_t cid_mask, enum msm_ispif_vfe_intf vfe_intf, uint8_t enable) + { + uint32_t intf_addr, data; + +@@ -461,7 +461,7 @@ static void msm_ispif_enable_intf_cids(struct ispif_device *ispif, + } + + static int msm_ispif_validate_intf_status(struct ispif_device *ispif, +- uint8_t intftype, uint8_t vfe_intf) ++ uint8_t intftype, enum msm_ispif_vfe_intf vfe_intf) + { + int rc = 0; + uint32_t data = 0; +@@ -501,7 +501,7 @@ static int msm_ispif_validate_intf_status(struct ispif_device *ispif, + } + + static void msm_ispif_select_clk_mux(struct ispif_device *ispif, +- uint8_t intftype, uint8_t csid, uint8_t vfe_intf) ++ uint8_t intftype, uint8_t csid, enum msm_ispif_vfe_intf vfe_intf) + { + uint32_t data = 0; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8261/0.patch b/Patches/Linux_CVEs/CVE-2017-8261/0.patch new file mode 100644 index 00000000..8480a4d8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8261/0.patch @@ -0,0 +1,33 @@ +From 8576feebaf688dadf0548b9a16d2b90b76ed714c Mon Sep 17 00:00:00 2001 +From: Trishansh Bhardwaj +Date: Tue, 18 Apr 2017 14:44:43 +0530 +Subject: msm: camera: Fix kernel overwrite GET_BUF_BY_IDX ioctl + +Assign address of buf_info into ioctl_ptr. +Previously we were copying first 8 bytes of buf_info (content) +into ioctl_ptr. Which is dereferenced and written later causing +kernel overwrite vulnerability. + +Change-Id: Ie5deae249da8208523027f8ec5632f960757e9bd +Signed-off-by: Trishansh Bhardwaj +--- + drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c +index 882ab03..d0b265a 100644 +--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c ++++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c +@@ -554,8 +554,7 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd, + sizeof(struct msm_buf_mngr_info))) { + return -EFAULT; + } +- MSM_CAM_GET_IOCTL_ARG_PTR(&k_ioctl.ioctl_ptr, +- &buf_info, sizeof(void *)); ++ k_ioctl.ioctl_ptr = (uintptr_t)&buf_info; + argp = &k_ioctl; + rc = msm_cam_buf_mgr_ops(cmd, argp); + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8262/0.patch b/Patches/Linux_CVEs/CVE-2017-8262/0.patch new file mode 100644 index 00000000..580dc9b9 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8262/0.patch @@ -0,0 +1,107 @@ +From 9ef4ee8e3dfaf4e796bda781826851deebbd89bd Mon Sep 17 00:00:00 2001 +From: Sunil Khatri +Date: Fri, 7 Apr 2017 17:00:55 +0530 +Subject: msm: kgsl: Fix kgsl memory allocation and free race condition + +When allocating userspace memory keep reference to memory +allocation till it is completely initialized and info is sent back +to userspace. + +Change-Id: Id72c82bf98c094ecbd4722813c732a998dcbb188 +Signed-off-by: Tarun Karra +Signed-off-by: Sunil Khatri +--- + drivers/gpu/msm/kgsl.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index 1de8e21..e49b39f 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -260,9 +260,12 @@ kgsl_mem_entry_create(void) + { + struct kgsl_mem_entry *entry = kzalloc(sizeof(*entry), GFP_KERNEL); + +- if (entry != NULL) ++ if (entry != NULL) { + kref_init(&entry->refcount); + ++ /* put this ref in the caller functions after init */ ++ kref_get(&entry->refcount); ++ } + return entry; + } + #ifdef CONFIG_DMA_SHARED_BUFFER +@@ -2399,6 +2402,9 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, + trace_kgsl_mem_map(entry, fd); + + kgsl_mem_entry_commit_process(entry); ++ ++ /* put the extra refcount for kgsl_mem_entry_create() */ ++ kgsl_mem_entry_put(entry); + return 0; + + unmap: +@@ -2705,6 +2711,9 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, + trace_kgsl_mem_map(entry, param->fd); + + kgsl_mem_entry_commit_process(entry); ++ ++ /* put the extra refcount for kgsl_mem_entry_create() */ ++ kgsl_mem_entry_put(entry); + return result; + + error_attach: +@@ -3143,6 +3152,9 @@ long kgsl_ioctl_gpuobj_alloc(struct kgsl_device_private *dev_priv, + param->mmapsize = kgsl_memdesc_footprint(&entry->memdesc); + param->id = entry->id; + ++ /* put the extra refcount for kgsl_mem_entry_create() */ ++ kgsl_mem_entry_put(entry); ++ + return 0; + } + +@@ -3166,6 +3178,9 @@ long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, + param->size = (size_t) entry->memdesc.size; + param->flags = (unsigned int) entry->memdesc.flags; + ++ /* put the extra refcount for kgsl_mem_entry_create() */ ++ kgsl_mem_entry_put(entry); ++ + return 0; + } + +@@ -3189,6 +3204,9 @@ long kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, + param->mmapsize = (size_t) kgsl_memdesc_footprint(&entry->memdesc); + param->gpuaddr = (unsigned long) entry->memdesc.gpuaddr; + ++ /* put the extra refcount for kgsl_mem_entry_create() */ ++ kgsl_mem_entry_put(entry); ++ + return 0; + } + +@@ -3306,6 +3324,9 @@ long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv, + trace_sparse_phys_alloc(entry->id, param->size, param->pagesize); + kgsl_mem_entry_commit_process(entry); + ++ /* put the extra refcount for kgsl_mem_entry_create() */ ++ kgsl_mem_entry_put(entry); ++ + return 0; + + err_invalid_pages: +@@ -3385,6 +3406,9 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv, + trace_sparse_virt_alloc(entry->id, param->size, param->pagesize); + kgsl_mem_entry_commit_process(entry); + ++ /* put the extra refcount for kgsl_mem_entry_create() */ ++ kgsl_mem_entry_put(entry); ++ + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8264/0.patch b/Patches/Linux_CVEs/CVE-2017-8264/0.patch new file mode 100644 index 00000000..f5bb668f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8264/0.patch @@ -0,0 +1,235 @@ +From 4268b75208ca04bc63dcfadbb9a1eca8e964a697 Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Wed, 10 May 2017 11:39:45 -0700 +Subject: BACKPORT: msm: camera: Add regulator enable and disable independent + of CSID + +Regulator enable and disable of CSIPHY depends on the CSID module. +Make the enable and disable of clk regulator independent of CSIPHY. + +Bug: 33299365 +CRs-Fixed: 1107702 +Change-Id: Iabb5eb28d63b34a4c3201c53be17054a1907f4fe +Signed-off-by: Ravi Kishore Tanuku +Signed-off-by: VijayaKumar T M +Signed-off-by: Dennis Cagle +(cherry picked from commit b1bb44c9cca61e48ec6158abad6e7969a8e58abf) +--- + arch/arm/boot/dts/qcom/apq8084-camera.dtsi | 6 ++ + .../msm/camera_v2/sensor/csiphy/msm_csiphy.c | 95 +++++++++++++++++++++- + .../msm/camera_v2/sensor/csiphy/msm_csiphy.h | 2 + + 3 files changed, 102 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/qcom/apq8084-camera.dtsi b/arch/arm/boot/dts/qcom/apq8084-camera.dtsi +index 2d7e126..abc85bf9 100644 +--- a/arch/arm/boot/dts/qcom/apq8084-camera.dtsi ++++ b/arch/arm/boot/dts/qcom/apq8084-camera.dtsi +@@ -26,6 +26,8 @@ + reg-names = "csiphy", "csiphy_clk_mux"; + interrupts = <0 78 0>; + interrupt-names = "csiphy"; ++ qcom,csi-vdd-voltage = <1800000>; ++ qcom,mipi-csi-vdd-supply = <&pma8084_l12>; + }; + + qcom,csiphy@fda0b000 { +@@ -36,6 +38,8 @@ + reg-names = "csiphy", "csiphy_clk_mux"; + interrupts = <0 79 0>; + interrupt-names = "csiphy"; ++ qcom,csi-vdd-voltage = <1800000>; ++ qcom,mipi-csi-vdd-supply = <&pma8084_l12>; + }; + + qcom,csiphy@fda0b400 { +@@ -46,6 +50,8 @@ + reg-names = "csiphy", "csiphy_clk_mux"; + interrupts = <0 80 0>; + interrupt-names = "csiphy"; ++ qcom,csi-vdd-voltage = <1800000>; ++ qcom,mipi-csi-vdd-supply = <&pma8084_l12>; + }; + + qcom,csid@fda08000 { +diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +index 8aac9b6..5301b33 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2014, 2017 The 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 +@@ -28,6 +28,10 @@ + #define CSIPHY_VERSION_V30 0x10 + #define MSM_CSIPHY_DRV_NAME "msm_csiphy" + ++static struct camera_vreg_t csiphy_vreg_info[] = { ++ {"qcom,mipi-csi-vdd", 0, 0, 12000}, ++}; ++ + #undef CDBG + #ifdef CONFIG_MSMB_CAMERA_DEBUG + #define CDBG(fmt, args...) pr_err(fmt, ##args) +@@ -205,6 +209,21 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + } + CDBG("%s:%d called\n", __func__, __LINE__); + ++ rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 1); ++ if (rc < 0) { ++ pr_err("%s: regulator config failed\n", __func__); ++ goto csiphy_vreg_config_fail; ++ } ++ rc = msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 1); ++ if (rc < 0) { ++ pr_err("%s: regulator enable failed\n", __func__); ++ goto csiphy_vreg_enable_fail; ++ } ++ + if (CSIPHY_VERSION == CSIPHY_VERSION_V22) { + rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, + csiphy_8610_clk_info, csiphy_dev->csiphy_clk, +@@ -268,6 +287,16 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + csiphy_dev->hw_version); + csiphy_dev->csiphy_state = CSIPHY_POWER_UP; + return 0; ++ ++csiphy_vreg_enable_fail: ++ rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 0); ++csiphy_vreg_config_fail: ++ iounmap(csiphy_dev->base); ++ csiphy_dev->base = NULL; ++ return rc; ++ + } + #else + static int msm_csiphy_init(struct csiphy_device *csiphy_dev) +@@ -303,6 +332,22 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + rc = -ENOMEM; + return rc; + } ++ ++ rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 1); ++ if (rc < 0) { ++ pr_err("%s: regulator config failed\n", __func__); ++ goto csiphy_vreg_config_fail; ++ } ++ rc = msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 1); ++ if (rc < 0) { ++ pr_err("%s: regulator enable failed\n", __func__); ++ goto csiphy_vreg_enable_fail; ++ } ++ + if (CSIPHY_VERSION == CSIPHY_VERSION_V22) { + rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, + csiphy_8610_clk_info, csiphy_dev->csiphy_clk, +@@ -364,6 +409,15 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + csiphy_dev->hw_version); + csiphy_dev->csiphy_state = CSIPHY_POWER_UP; + return 0; ++ ++csiphy_vreg_enable_fail: ++ rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 0); ++csiphy_vreg_config_fail: ++ iounmap(csiphy_dev->base); ++ csiphy_dev->base = NULL; ++ return rc; + } + #endif + +@@ -445,6 +499,19 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) + ARRAY_SIZE(csiphy_clk_info), 0); + iounmap(csiphy_dev->clk_mux_base); + } ++ ++ msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 0); ++ msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 0); ++ ++ if (!IS_ERR_OR_NULL(csiphy_dev->reg_ptr)) { ++ regulator_disable(csiphy_dev->reg_ptr); ++ regulator_put(csiphy_dev->reg_ptr); ++ } ++ + iounmap(csiphy_dev->base); + csiphy_dev->base = NULL; + csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN; +@@ -527,6 +594,18 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) + iounmap(csiphy_dev->clk_mux_base); + } + ++ msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 0); ++ msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_vreg_info, ARRAY_SIZE(csiphy_vreg_info), ++ NULL, 0, &csiphy_dev->csi_vdd, 0); ++ ++ if (!IS_ERR_OR_NULL(csiphy_dev->reg_ptr)) { ++ regulator_disable(csiphy_dev->reg_ptr); ++ regulator_put(csiphy_dev->reg_ptr); ++ } ++ + iounmap(csiphy_dev->base); + csiphy_dev->base = NULL; + csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN; +@@ -630,6 +709,7 @@ static const struct v4l2_subdev_ops msm_csiphy_subdev_ops = { + static int csiphy_probe(struct platform_device *pdev) + { + struct csiphy_device *new_csiphy_dev; ++ uint32_t csi_vdd_voltage = 0; + int rc = 0; + + new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL); +@@ -649,6 +729,19 @@ static int csiphy_probe(struct platform_device *pdev) + "cell-index", &pdev->id); + CDBG("%s: device id = %d\n", __func__, pdev->id); + ++ rc = of_property_read_u32((&pdev->dev)->of_node, ++ "qcom,csi-vdd-voltage", &csi_vdd_voltage); ++ if (rc < 0) { ++ pr_err("%s:%d failed to read qcom,csi-vdd-voltage\n", ++ __func__, __LINE__); ++ return rc; ++ } ++ CDBG("%s:%d reading mipi_csi_vdd is %d\n", __func__, __LINE__, ++ csi_vdd_voltage); ++ ++ csiphy_vreg_info[0].min_voltage = csi_vdd_voltage; ++ csiphy_vreg_info[0].max_voltage = csi_vdd_voltage; ++ + new_csiphy_dev->mem = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "csiphy"); + if (!new_csiphy_dev->mem) { +diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h +index ff97ab7..3c843a2 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h ++++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h +@@ -47,6 +47,8 @@ struct csiphy_device { + + int32_t ref_count; + uint16_t lane_mask[MAX_CSIPHY]; ++ struct regulator *csi_vdd; ++ struct regulator *reg_ptr; + }; + + #define VIDIOC_MSM_CSIPHY_RELEASE \ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8264/1.patch b/Patches/Linux_CVEs/CVE-2017-8264/1.patch new file mode 100644 index 00000000..0fda518e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8264/1.patch @@ -0,0 +1,316 @@ +From 53c6b89349730765a71722d274fc3fa41287d21f Mon Sep 17 00:00:00 2001 +From: Ravi Kishore Tanuku +Date: Wed, 22 Feb 2017 20:00:13 +0530 +Subject: msm: camera: Add regulator enable and disable independent of CSID + +Regulator enable and disable of CSIPHY depends on the CSID module. +Make the enable and disable of clk regulator independent of CSIPHY. + +CRs-Fixed: 1107702 +Change-Id: Iabb5eb28d63b34a4c3201c53be17054a1907f4fe +Signed-off-by: Ravi Kishore Tanuku +--- + arch/arm/boot/dts/qcom/msm8996-camera.dtsi | 38 ++++++--- + .../msm/camera_v2/sensor/csiphy/msm_csiphy.c | 94 ++++++++++++++++++++-- + .../msm/camera_v2/sensor/csiphy/msm_csiphy.h | 6 +- + 3 files changed, 120 insertions(+), 18 deletions(-) + +diff --git a/arch/arm/boot/dts/qcom/msm8996-camera.dtsi b/arch/arm/boot/dts/qcom/msm8996-camera.dtsi +index 3e1a889..e4960d0 100644 +--- a/arch/arm/boot/dts/qcom/msm8996-camera.dtsi ++++ b/arch/arm/boot/dts/qcom/msm8996-camera.dtsi +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2017, The 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 +@@ -28,18 +28,24 @@ + reg-names = "csiphy", "csiphy_clk_mux"; + interrupts = <0 78 0>; + interrupt-names = "csiphy"; +- clocks = <&clock_mmss clk_camss_top_ahb_clk>, ++ qcom,csi-vdd-voltage = <1250000>; ++ qcom,mipi-csi-vdd-supply = <&pm8994_l2>; ++ mmagic-supply = <&gdsc_mmagic_camss>; ++ gdscr-supply = <&gdsc_camss_top>; ++ qcom,cam-vreg-name = "mmagic", "gdscr"; ++ clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>, ++ <&clock_mmss clk_camss_top_ahb_clk>, + <&clock_mmss clk_camss_ispif_ahb_clk>, + <&clock_mmss clk_csi0phytimer_clk_src>, + <&clock_mmss clk_camss_csi0phytimer_clk>, + <&clock_mmss clk_camss_ahb_clk>, + <&clock_mmss clk_csiphy0_3p_clk_src>, + <&clock_mmss clk_camss_csiphy0_3p_clk>; +- clock-names = "camss_top_ahb_clk", ++ clock-names = "mmagic_ahb_clk", "camss_top_ahb_clk", + "ispif_ahb_clk", "csiphy_timer_src_clk", + "csiphy_timer_clk", "camss_ahb_clk", + "csiphy_3p_clk_src", "csi_phy_3p_clk"; +- qcom,clock-rates = <0 0 200000000 0 0 100000000 0>; ++ qcom,clock-rates = <0 0 0 200000000 0 0 100000000 0>; + }; + + qcom,csiphy@a35000 { +@@ -49,18 +55,24 @@ + reg-names = "csiphy", "csiphy_clk_mux"; + interrupts = <0 79 0>; + interrupt-names = "csiphy"; +- clocks = <&clock_mmss clk_camss_top_ahb_clk>, ++ qcom,csi-vdd-voltage = <1250000>; ++ qcom,mipi-csi-vdd-supply = <&pm8994_l2>; ++ mmagic-supply = <&gdsc_mmagic_camss>; ++ gdscr-supply = <&gdsc_camss_top>; ++ qcom,cam-vreg-name = "mmagic", "gdscr"; ++ clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>, ++ <&clock_mmss clk_camss_top_ahb_clk>, + <&clock_mmss clk_camss_ispif_ahb_clk>, + <&clock_mmss clk_csi1phytimer_clk_src>, + <&clock_mmss clk_camss_csi1phytimer_clk>, + <&clock_mmss clk_camss_ahb_clk>, + <&clock_mmss clk_csiphy1_3p_clk_src>, + <&clock_mmss clk_camss_csiphy1_3p_clk>; +- clock-names = "camss_top_ahb_clk", ++ clock-names = "mmagic_ahb_clk", "camss_top_ahb_clk", + "ispif_ahb_clk", "csiphy_timer_src_clk", + "csiphy_timer_clk", "camss_ahb_clk", + "csiphy_3p_clk_src", "csi_phy_3p_clk"; +- qcom,clock-rates = <0 0 200000000 0 0 100000000 0>; ++ qcom,clock-rates = <0 0 0 200000000 0 0 100000000 0>; + }; + + qcom,csiphy@a36000 { +@@ -70,18 +82,24 @@ + reg-names = "csiphy", "csiphy_clk_mux"; + interrupts = <0 80 0>; + interrupt-names = "csiphy"; +- clocks = <&clock_mmss clk_camss_top_ahb_clk>, ++ qcom,csi-vdd-voltage = <1250000>; ++ qcom,mipi-csi-vdd-supply = <&pm8994_l2>; ++ mmagic-supply = <&gdsc_mmagic_camss>; ++ gdscr-supply = <&gdsc_camss_top>; ++ qcom,cam-vreg-name = "mmagic", "gdscr"; ++ clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>, ++ <&clock_mmss clk_camss_top_ahb_clk>, + <&clock_mmss clk_camss_ispif_ahb_clk>, + <&clock_mmss clk_csi2phytimer_clk_src>, + <&clock_mmss clk_camss_csi2phytimer_clk>, + <&clock_mmss clk_camss_ahb_clk>, + <&clock_mmss clk_csiphy2_3p_clk_src>, + <&clock_mmss clk_camss_csiphy2_3p_clk>; +- clock-names = "camss_top_ahb_clk", ++ clock-names = "mmagic_ahb_clk", "camss_top_ahb_clk", + "ispif_ahb_clk", "csiphy_timer_src_clk", + "csiphy_timer_clk", "camss_ahb_clk", + "csiphy_3p_clk_src", "csi_phy_3p_clk"; +- qcom,clock-rates = <0 0 200000000 0 0 100000000 0>; ++ qcom,clock-rates = <0 0 0 200000000 0 0 100000000 0>; + }; + + qcom,csid@a30000 { +diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +index 9d6952ee..d1bb9af 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2017, The 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 +@@ -782,6 +782,25 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + + CDBG("%s:%d called\n", __func__, __LINE__); + ++ rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 1); ++ if (rc < 0) { ++ pr_err("%s:%d csiphy config_vreg failed\n", ++ __func__, __LINE__); ++ goto csiphy_vreg_config_fail; ++ } ++ rc = msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 1); ++ if (rc < 0) { ++ pr_err("%s:%d csiphy enable_vreg failed\n", ++ __func__, __LINE__); ++ goto top_vreg_enable_failed; ++ } ++ + rc = msm_camera_clk_enable(&csiphy_dev->pdev->dev, + csiphy_dev->csiphy_clk_info, csiphy_dev->csiphy_clk, + csiphy_dev->num_clk, true); +@@ -790,7 +809,7 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + if (rc < 0) { + pr_err("%s: csiphy clk enable failed\n", __func__); + csiphy_dev->ref_count--; +- goto csiphy_resource_fail; ++ goto csiphy_enable_clk_fail; + } + CDBG("%s:%d called\n", __func__, __LINE__); + +@@ -818,7 +837,17 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + csiphy_dev->csiphy_state = CSIPHY_POWER_UP; + return 0; + +-csiphy_resource_fail: ++csiphy_enable_clk_fail: ++ msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 0); ++top_vreg_enable_failed: ++ msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 0); ++csiphy_vreg_config_fail: + if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY, + CAM_AHB_SUSPEND_VOTE) < 0) + pr_err("%s: failed to vote for AHB\n", __func__); +@@ -856,6 +885,24 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + pr_err("%s: failed to vote for AHB\n", __func__); + return rc; + } ++ rc = msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 1); ++ if (rc < 0) { ++ pr_err("%s:%d csiphy config_vreg failed\n", ++ __func__, __LINE__); ++ goto csiphy_vreg_config_fail; ++ } ++ rc = msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 1); ++ if (rc < 0) { ++ pr_err("%s:%d csiphy enable_vreg failed\n", ++ __func__, __LINE__); ++ goto top_vreg_enable_failed; ++ } + + rc = msm_camera_clk_enable(&csiphy_dev->pdev->dev, + csiphy_dev->csiphy_clk_info, csiphy_dev->csiphy_clk, +@@ -865,9 +912,9 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + if (rc < 0) { + pr_err("%s: csiphy clk enable failed\n", __func__); + csiphy_dev->ref_count--; +- goto csiphy_resource_fail; ++ goto csiphy_enable_clk_fail; + } +- CDBG("%s:%d called\n", __func__, __LINE__); ++ CDBG("%s:%d clk enable success\n", __func__, __LINE__); + + if (csiphy_dev->csiphy_3phase == CSI_3PHASE_HW) + msm_csiphy_3ph_reset(csiphy_dev); +@@ -890,7 +937,17 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev) + csiphy_dev->csiphy_state = CSIPHY_POWER_UP; + return 0; + +-csiphy_resource_fail: ++csiphy_enable_clk_fail: ++ msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 0); ++top_vreg_enable_failed: ++ msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 0); ++csiphy_vreg_config_fail: + if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY, + CAM_AHB_SUSPEND_VOTE) < 0) + pr_err("%s: failed to vote for AHB\n", __func__); +@@ -998,6 +1055,14 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) + csiphy_dev->csiphy_3p_clk, 2, false); + } + ++ msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, ++ csiphy_dev->regulator_count, NULL, 0, ++ &csiphy_dev->csiphy_reg_ptr[0], 0); ++ msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, csiphy_dev->regulator_count, ++ NULL, 0, &csiphy_dev->csiphy_reg_ptr[0], 0); ++ + csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN; + + if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY, +@@ -1104,6 +1169,13 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg) + csiphy_dev->csiphy_3p_clk, 2, false); + } + ++ msm_camera_enable_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, csiphy_dev->regulator_count, ++ NULL, 0, &csiphy_dev->csiphy_reg_ptr[0], 0); ++ msm_camera_config_vreg(&csiphy_dev->pdev->dev, ++ csiphy_dev->csiphy_vreg, csiphy_dev->regulator_count, ++ NULL, 0, &csiphy_dev->csiphy_reg_ptr[0], 0); ++ + csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN; + + if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY, +@@ -1419,6 +1491,14 @@ static int csiphy_probe(struct platform_device *pdev) + goto csiphy_no_resource; + } + ++ rc = msm_camera_get_dt_vreg_data(pdev->dev.of_node, ++ &(new_csiphy_dev->csiphy_vreg), ++ &(new_csiphy_dev->regulator_count)); ++ if (rc < 0) { ++ pr_err("%s: get vreg data from dtsi fail\n", __func__); ++ rc = -EFAULT; ++ goto csiphy_no_resource; ++ } + /* ToDo: Enable 3phase clock for dynamic clock enable/disable */ + rc = msm_csiphy_get_clk_info(new_csiphy_dev, pdev); + if (rc < 0) { +@@ -1493,7 +1573,7 @@ static int msm_csiphy_exit(struct platform_device *pdev) + &csiphy_dev->csiphy_all_clk, + csiphy_dev->num_all_clk); + +- msm_camera_put_reg_base(pdev, csiphy_dev->base, "csid", true); ++ msm_camera_put_reg_base(pdev, csiphy_dev->base, "csiphy", true); + if (csiphy_dev->hw_dts_version >= CSIPHY_VERSION_V30) { + msm_camera_put_reg_base(pdev, csiphy_dev->clk_mux_base, + "csiphy_clk_mux", true); +diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h +index 4b3c407..07a0811 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h ++++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2017, The 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 +@@ -20,6 +20,7 @@ + #include + #include "msm_sd.h" + #include "msm_camera_io_util.h" ++#include "msm_camera_dt_util.h" + #include "cam_soc_api.h" + + #define MAX_CSIPHY 3 +@@ -168,6 +169,9 @@ struct csiphy_device { + uint8_t num_irq_registers; + uint32_t csiphy_sof_debug; + uint32_t csiphy_sof_debug_count; ++ struct camera_vreg_t *csiphy_vreg; ++ struct regulator *csiphy_reg_ptr[MAX_REGULATOR]; ++ int32_t regulator_count; + }; + + #define VIDIOC_MSM_CSIPHY_RELEASE \ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8265/0.patch b/Patches/Linux_CVEs/CVE-2017-8265/0.patch new file mode 100644 index 00000000..ac55f011 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8265/0.patch @@ -0,0 +1,62 @@ +From 193813a21453ccc7fb6b04bedf881a6feaaa015f Mon Sep 17 00:00:00 2001 +From: Vasantha Balla +Date: Tue, 28 Mar 2017 16:04:06 +0530 +Subject: msm-vidc: Allocate bus vote data during initialization + +Dynamic reallocation of vote_data memory can cause double free +problem if multiple instances try to reallocate simultaneously. +So allocate this memory statically. + +Change-Id: Ib5ff08c600a4b69a38b519688bbc153de9f50090 +Signed-off-by: Vasantha Balla +--- + drivers/media/platform/msm/vidc/venus_hfi.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c +index 4df4f35..8b98c41d 100644 +--- a/drivers/media/platform/msm/vidc/venus_hfi.c ++++ b/drivers/media/platform/msm/vidc/venus_hfi.c +@@ -929,15 +929,12 @@ static int venus_hfi_vote_active_buses(void *dev, + return -EINVAL; + } + +- /* (Re-)alloc memory to store the new votes (in case we internally +- * re-vote after power collapse, which is transparent to client) */ +- cached_vote_data = krealloc(device->bus_load.vote_data, num_data * +- sizeof(*cached_vote_data), GFP_KERNEL); +- if (!cached_vote_data) { +- dprintk(VIDC_ERR, "Can't alloc memory to cache bus votes\n"); +- rc = -ENOMEM; +- goto err_no_mem; +- } ++ cached_vote_data = device->bus_load.vote_data; ++ if (!cached_vote_data) { ++ dprintk(VIDC_ERR,"Invalid bus load vote data\n"); ++ rc = -ENOMEM; ++ goto err_no_mem; ++ } + + /* Alloc & init the load table */ + num_bus = device->res->bus_set.count; +@@ -3746,9 +3743,15 @@ static int venus_hfi_init_bus(struct venus_hfi_device *device) + dprintk(VIDC_DBG, "Registered bus client %s\n", name); + } + +- device->bus_load.vote_data = NULL; +- device->bus_load.vote_data_count = 0; ++ device->bus_load.vote_data = (struct vidc_bus_vote_data *) ++ kzalloc(sizeof(struct vidc_bus_vote_data)*MAX_SUPPORTED_INSTANCES_COUNT, GFP_KERNEL); + ++ if (device->bus_load.vote_data == NULL) { ++ dprintk(VIDC_ERR,"Failed to allocate memory for vote_data\n"); ++ rc = -ENOMEM; ++ goto err_init_bus; ++ } ++ device->bus_load.vote_data_count = 0; + return rc; + err_init_bus: + venus_hfi_deinit_bus(device); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8266/0.patch b/Patches/Linux_CVEs/CVE-2017-8266/0.patch new file mode 100644 index 00000000..508dd353 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8266/0.patch @@ -0,0 +1,52 @@ +From 42627c94cf8c189332a6f5bfdd465ea662777911 Mon Sep 17 00:00:00 2001 +From: Harsh Sahu +Date: Thu, 13 Apr 2017 15:38:46 -0700 +Subject: msm: mdss: fix race condition during mdp debugfs release + +Fix race condition in the release of the mdp debugfs functions +panel_debug_base_release and mdss_debug_base_release by adding +the lock for unpreempted freeing of the buffer so that multiple +concurrent processes cannot affect the release which can possibly +lead to use-after-free operation on the buffer. + +Change-Id: I9586081b65ae2eb0e7f6e30c606ee748ae9ef7e8 +Signed-off-by: Harsh Sahu +--- + drivers/video/msm/mdss/mdss_debug.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c +index 920babf..78bfe50 100644 +--- a/drivers/video/msm/mdss/mdss_debug.c ++++ b/drivers/video/msm/mdss/mdss_debug.c +@@ -57,11 +57,13 @@ static int panel_debug_base_open(struct inode *inode, struct file *file) + static int panel_debug_base_release(struct inode *inode, struct file *file) + { + struct mdss_debug_base *dbg = file->private_data; ++ mutex_lock(&mdss_debug_lock); + if (dbg && dbg->buf) { + kfree(dbg->buf); + dbg->buf_len = 0; + dbg->buf = NULL; + } ++ mutex_unlock(&mdss_debug_lock); + return 0; + } + +@@ -386,11 +388,13 @@ static int mdss_debug_base_open(struct inode *inode, struct file *file) + static int mdss_debug_base_release(struct inode *inode, struct file *file) + { + struct mdss_debug_base *dbg = file->private_data; ++ mutex_lock(&mdss_debug_lock); + if (dbg && dbg->buf) { + kfree(dbg->buf); + dbg->buf_len = 0; + dbg->buf = NULL; + } ++ mutex_unlock(&mdss_debug_lock); + return 0; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8266/1.patch b/Patches/Linux_CVEs/CVE-2017-8266/1.patch new file mode 100644 index 00000000..c620412f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8266/1.patch @@ -0,0 +1,182 @@ +From aa23820b001ab1cfb86b79014e9fc44cd2be9ece Mon Sep 17 00:00:00 2001 +From: Ingrid Gallardo +Date: Wed, 1 Mar 2017 12:24:06 -0800 +Subject: msm: mdss: fix race condition in mdp debugfs + +Fix race condition in mdp debugfs properties +during the read and write of the panel and +mdp registers. This race condition can cause +accessing memory out bounderies. + +Change-Id: I97a90a154237343d4aaf237c11f525bcc2c3a8e3 +Signed-off-by: Ingrid Gallardo +Signed-off-by: Nirmal Abraham +--- + drivers/video/msm/mdss/mdss_debug.c | 48 ++++++++++++++++++++++++++++++------- + 1 file changed, 40 insertions(+), 8 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c +index a95fa43..cedd40cd 100644 +--- a/drivers/video/msm/mdss/mdss_debug.c ++++ b/drivers/video/msm/mdss/mdss_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2009-2017, The 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 +@@ -39,6 +39,8 @@ + #define PANEL_CMD_MIN_TX_COUNT 2 + #define PANEL_DATA_NODE_LEN 80 + ++static DEFINE_MUTEX(mdss_debug_lock); ++ + static char panel_reg[2] = {DEFAULT_READ_PANEL_POWER_MODE_REG, 0x00}; + + static int panel_debug_base_open(struct inode *inode, struct file *file) +@@ -88,8 +90,10 @@ static ssize_t panel_debug_base_offset_write(struct file *file, + if (cnt > (dbg->max_offset - off)) + cnt = dbg->max_offset - off; + ++ mutex_lock(&mdss_debug_lock); + dbg->off = off; + dbg->cnt = cnt; ++ mutex_unlock(&mdss_debug_lock); + + pr_debug("offset=%x cnt=%d\n", off, cnt); + +@@ -109,15 +113,21 @@ static ssize_t panel_debug_base_offset_read(struct file *file, + if (*ppos) + return 0; /* the end */ + ++ mutex_lock(&mdss_debug_lock); + len = snprintf(buf, sizeof(buf), "0x%02zx %zx\n", dbg->off, dbg->cnt); +- if (len < 0 || len >= sizeof(buf)) ++ if (len < 0 || len >= sizeof(buf)) { ++ mutex_unlock(&mdss_debug_lock); + return 0; ++ } + +- if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) ++ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) { ++ mutex_unlock(&mdss_debug_lock); + return -EFAULT; ++ } + + *ppos += len; /* increase offset */ + ++ mutex_unlock(&mdss_debug_lock); + return len; + } + +@@ -206,11 +216,16 @@ static ssize_t panel_debug_base_reg_read(struct file *file, + if (!dbg) + return -ENODEV; + +- if (!dbg->cnt) ++ mutex_lock(&mdss_debug_lock); ++ if (!dbg->cnt) { ++ mutex_unlock(&mdss_debug_lock); + return 0; ++ } + +- if (*ppos) ++ if (*ppos) { ++ mutex_unlock(&mdss_debug_lock); + return 0; /* the end */ ++ } + + /* '0x' + 2 digit + blank = 5 bytes for each number */ + reg_buf_len = (dbg->cnt * PANEL_REG_FORMAT_LEN) +@@ -251,11 +266,13 @@ static ssize_t panel_debug_base_reg_read(struct file *file, + kfree(panel_reg_buf); + + *ppos += len; /* increase offset */ ++ mutex_unlock(&mdss_debug_lock); + return len; + + read_reg_fail: + kfree(rx_buf); + kfree(panel_reg_buf); ++ mutex_unlock(&mdss_debug_lock); + return rc; + } + +@@ -386,8 +403,10 @@ static ssize_t mdss_debug_base_offset_write(struct file *file, + if (cnt > (dbg->max_offset - off)) + cnt = dbg->max_offset - off; + ++ mutex_lock(&mdss_debug_lock); + dbg->off = off; + dbg->cnt = cnt; ++ mutex_unlock(&mdss_debug_lock); + + pr_debug("offset=%x cnt=%x\n", off, cnt); + +@@ -407,15 +426,21 @@ static ssize_t mdss_debug_base_offset_read(struct file *file, + if (*ppos) + return 0; /* the end */ + ++ mutex_lock(&mdss_debug_lock); + len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt); +- if (len < 0 || len >= sizeof(buf)) ++ if (len < 0 || len >= sizeof(buf)) { ++ mutex_unlock(&mdss_debug_lock); + return 0; ++ } + +- if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) ++ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) { ++ mutex_unlock(&mdss_debug_lock); + return -EFAULT; ++ } + + *ppos += len; /* increase offset */ + ++ mutex_unlock(&mdss_debug_lock); + return len; + } + +@@ -472,6 +497,8 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, + return -ENODEV; + } + ++ mutex_lock(&mdss_debug_lock); ++ + if (!dbg->buf) { + char dump_buf[64]; + char *ptr; +@@ -483,6 +510,7 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, + + if (!dbg->buf) { + pr_err("not enough memory to hold reg dump\n"); ++ mutex_unlock(&mdss_debug_lock); + return -ENOMEM; + } + +@@ -513,17 +541,21 @@ static ssize_t mdss_debug_base_reg_read(struct file *file, + dbg->buf_len = tot; + } + +- if (*ppos >= dbg->buf_len) ++ if (*ppos >= dbg->buf_len) { ++ mutex_unlock(&mdss_debug_lock); + return 0; /* done reading */ ++ } + + len = min(count, dbg->buf_len - (size_t) *ppos); + if (copy_to_user(user_buf, dbg->buf + *ppos, len)) { + pr_err("failed to copy to user\n"); ++ mutex_unlock(&mdss_debug_lock); + return -EFAULT; + } + + *ppos += len; /* increase offset */ + ++ mutex_unlock(&mdss_debug_lock); + return len; + } + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8268/0.patch b/Patches/Linux_CVEs/CVE-2017-8268/0.patch new file mode 100644 index 00000000..ae5c451f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8268/0.patch @@ -0,0 +1,79 @@ +From 5f3b68da4c8f6474df2497b6d912465d640904b8 Mon Sep 17 00:00:00 2001 +From: Ravi kumar Koyyana +Date: Tue, 11 Apr 2017 18:47:44 -0700 +Subject: msm: camera2: cpp: Fix out-of-bounds frame or command buffer access + +When user application provides invalid (out of range) stripe size and +stripe indices, while submitting requests for the stripe based image +processing by the CPP kernel driver, the driver could perform out of +bounds access of the internal buffers. + +This fix ensures that stripe size and indices of frame/command buffer +are properly validated during the configuration and before processing +such requests through the CPP hardware block. + +CRs-fixed: 2002207 +Change-Id: Ib79e36fb507d8e75d8fc28afb990020a0e1bf845 +Signed-off-by: Ravi kumar Koyyana +--- + .../platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 33 ++++++++++++++++++---- + 1 file changed, 27 insertions(+), 6 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 79a8e8e..8269dc7 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 +@@ -2281,9 +2281,29 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + return -EINVAL; + } + +- if (stripe_base == UINT_MAX || new_frame->num_strips > +- (UINT_MAX - 1 - stripe_base) / stripe_size) { +- pr_err("Invalid frame message,num_strips %d is large\n", ++ /* Stripe index starts at zero */ ++ if ((!new_frame->num_strips) || ++ (new_frame->first_stripe_index >= new_frame->num_strips) || ++ (new_frame->last_stripe_index >= new_frame->num_strips) || ++ (new_frame->first_stripe_index > ++ new_frame->last_stripe_index)) { ++ pr_err("Invalid frame message, #stripes=%d, stripe indices=[%d,%d]\n", ++ new_frame->num_strips, ++ new_frame->first_stripe_index, ++ new_frame->last_stripe_index); ++ return -EINVAL; ++ } ++ ++ if (!stripe_size) { ++ pr_err("Invalid frame message, invalid stripe_size (%d)!\n", ++ stripe_size); ++ return -EINVAL; ++ } ++ ++ if ((stripe_base == UINT_MAX) || ++ (new_frame->num_strips > ++ (UINT_MAX - 1 - stripe_base) / stripe_size)) { ++ pr_err("Invalid frame message, num_strips %d is large\n", + new_frame->num_strips); + return -EINVAL; + } +@@ -2523,13 +2543,14 @@ static int msm_cpp_cfg(struct cpp_device *cpp_dev, + struct msm_cpp_frame_info_t *frame = NULL; + struct msm_cpp_frame_info_t k_frame_info; + int32_t rc = 0; +- int32_t i = 0; +- int32_t num_buff = sizeof(k_frame_info.output_buffer_info)/ ++ uint32_t i = 0; ++ uint32_t num_buff = sizeof(k_frame_info.output_buffer_info) / + sizeof(struct msm_cpp_buffer_info_t); ++ + if (copy_from_user(&k_frame_info, + (void __user *)ioctl_ptr->ioctl_ptr, + sizeof(k_frame_info))) +- return -EFAULT; ++ return -EFAULT; + + frame = msm_cpp_get_frame(ioctl_ptr); + if (!frame) { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8269/0.patch b/Patches/Linux_CVEs/CVE-2017-8269/0.patch new file mode 100644 index 00000000..686acd01 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8269/0.patch @@ -0,0 +1,38 @@ +From b925d9f76164475abb6f6a557327095156c9b249 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Fri, 14 Apr 2017 19:23:05 -0700 +Subject: msm: rmnet_ipa: fix security issue + +Fix the security issue where mux channel name might +not be null-terminated in ipa wan driver. + +Change-Id: I3ef440b62cf3861464fb60c1e7f65f2be5e39ed0 +Acked-by: Shihuan Liu +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/rmnet_ipa.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/msm/ipa/rmnet_ipa.c b/drivers/platform/msm/ipa/rmnet_ipa.c +index 3f073f2..a2c838b 100644 +--- a/drivers/platform/msm/ipa/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/rmnet_ipa.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2017, The 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 +@@ -1236,6 +1236,9 @@ static int ipa_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + memcpy(mux_channel[rmnet_index].vchannel_name, + extend_ioctl_data.u.rmnet_mux_val.vchannel_name, + sizeof(mux_channel[rmnet_index].vchannel_name)); ++ mux_channel[rmnet_index].vchannel_name[ ++ IFNAMSIZ - 1] = '\0'; ++ + IPAWANDBG("cashe device[%s:%d] in IPA_wan[%d]\n", + mux_channel[rmnet_index].vchannel_name, + mux_channel[rmnet_index].mux_id, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8277/0.patch b/Patches/Linux_CVEs/CVE-2017-8277/0.patch new file mode 100644 index 00000000..aba95594 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8277/0.patch @@ -0,0 +1,43 @@ +From c9a6f09f1030cec591df837622cb54bbb2d24ddc Mon Sep 17 00:00:00 2001 +From: Sandeep Panda +Date: Fri, 12 May 2017 10:56:32 +0530 +Subject: msm: mdss: remove client from device list if failed to register + +If there is any failure while registering a DBA client with MDSS +driver, then remove the client from device client list first and +then free the client. Otherwise driver might crash when +traversing the device client list in later stage, because of an +uninitialized entry in the list. + +Change-Id: I60666f4c3dea5c7ea7b7c77bcb14b080ee25b54d +Signed-off-by: Sandeep Panda +--- + drivers/video/fbdev/msm/msm_dba/msm_dba.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/msm/msm_dba/msm_dba.c b/drivers/video/fbdev/msm/msm_dba/msm_dba.c +index 7a5c9d9..cc6512a 100644 +--- a/drivers/video/fbdev/msm/msm_dba/msm_dba.c ++++ b/drivers/video/fbdev/msm/msm_dba/msm_dba.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2015,2017, The 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 +@@ -80,6 +80,11 @@ void *msm_dba_register_client(struct msm_dba_reg_info *info, + if (rc) { + pr_err("%s: Client register failed (%s, %d)\n", + __func__, info->chip_name, info->instance_id); ++ /* remove the client from list before freeing */ ++ mutex_lock_nested(&device->dev_mutex, ++ SINGLE_DEPTH_NESTING); ++ list_del(&client->list); ++ mutex_unlock(&device->dev_mutex); + kfree(client); + mutex_unlock(®ister_mutex); + return ERR_PTR(rc); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8280/0.patch b/Patches/Linux_CVEs/CVE-2017-8280/0.patch new file mode 100644 index 00000000..b598d592 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8280/0.patch @@ -0,0 +1,191 @@ +From 49b9a02eaaeb0b70608c6fbcadff7d83833b9614 Mon Sep 17 00:00:00 2001 +From: Sarada Prasanna Garnayak +Date: Mon, 17 Apr 2017 14:29:57 +0530 +Subject: wcnss: fix the potential memory leak and heap overflow + +The wcnss platform driver update the wlan calibration data +by the user space wlan daemon. The wlan user space daemon store +the updated wlan calibration data reported by wlan firmware in +user space and write it back to the wcnss platform calibration +data buffer for the calibration data download and update. + +During the wlan calibration data store and retrieve operation +there are some potential race condition which leads to memory leak +and buffer overflow during the context switch. + +Fix the above issue by adding protection code and avoid usage of +global pointer during the device file read and write operation. + +CRs-Fixed: 2015858 +Change-Id: Ib5b57eb86dcb4e6ed799b5222d06396eaabfaad3 +Signed-off-by: Sarada Prasanna Garnayak +--- + drivers/net/wireless/wcnss/wcnss_wlan.c | 87 +++++++++++++++++++-------------- + 1 file changed, 51 insertions(+), 36 deletions(-) + +diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c +index 11ba537..3171a40 100644 +--- a/drivers/net/wireless/wcnss/wcnss_wlan.c ++++ b/drivers/net/wireless/wcnss/wcnss_wlan.c +@@ -396,7 +396,6 @@ static struct { + int user_cal_available; + u32 user_cal_rcvd; + int user_cal_exp_size; +- int device_opened; + int iris_xo_mode_set; + int fw_vbatt_state; + char wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE]; +@@ -3284,14 +3283,6 @@ static int wcnss_node_open(struct inode *inode, struct file *file) + return -EFAULT; + } + +- mutex_lock(&penv->dev_lock); +- penv->user_cal_rcvd = 0; +- penv->user_cal_read = 0; +- penv->user_cal_available = false; +- penv->user_cal_data = NULL; +- penv->device_opened = 1; +- mutex_unlock(&penv->dev_lock); +- + return rc; + } + +@@ -3300,7 +3291,7 @@ static ssize_t wcnss_wlan_read(struct file *fp, char __user + { + int rc = 0; + +- if (!penv || !penv->device_opened) ++ if (!penv) + return -EFAULT; + + rc = wait_event_interruptible(penv->read_wait, penv->fw_cal_rcvd +@@ -3337,55 +3328,66 @@ static ssize_t wcnss_wlan_write(struct file *fp, const char __user + *user_buffer, size_t count, loff_t *position) + { + int rc = 0; +- u32 size = 0; ++ char *cal_data = NULL; + +- if (!penv || !penv->device_opened || penv->user_cal_available) ++ if (!penv || penv->user_cal_available) + return -EFAULT; + +- if (penv->user_cal_rcvd == 0 && count >= 4 +- && !penv->user_cal_data) { +- rc = copy_from_user((void *)&size, user_buffer, 4); +- if (!size || size > MAX_CALIBRATED_DATA_SIZE) { +- pr_err(DEVICE " invalid size to write %d\n", size); ++ if (!penv->user_cal_rcvd && count >= 4 && !penv->user_cal_exp_size) { ++ mutex_lock(&penv->dev_lock); ++ rc = copy_from_user((void *)&penv->user_cal_exp_size, ++ user_buffer, 4); ++ if (!penv->user_cal_exp_size || ++ penv->user_cal_exp_size > MAX_CALIBRATED_DATA_SIZE) { ++ pr_err(DEVICE " invalid size to write %d\n", ++ penv->user_cal_exp_size); ++ penv->user_cal_exp_size = 0; ++ mutex_unlock(&penv->dev_lock); + return -EFAULT; + } +- +- rc += count; +- count -= 4; +- penv->user_cal_exp_size = size; +- penv->user_cal_data = kmalloc(size, GFP_KERNEL); +- if (penv->user_cal_data == NULL) { +- pr_err(DEVICE " no memory to write\n"); +- return -ENOMEM; +- } +- if (0 == count) +- goto exit; +- +- } else if (penv->user_cal_rcvd == 0 && count < 4) ++ mutex_unlock(&penv->dev_lock); ++ return count; ++ } else if (!penv->user_cal_rcvd && count < 4) { + return -EFAULT; ++ } + ++ mutex_lock(&penv->dev_lock); + if ((UINT32_MAX - count < penv->user_cal_rcvd) || + (penv->user_cal_exp_size < count + penv->user_cal_rcvd)) { + pr_err(DEVICE " invalid size to write %zu\n", count + + penv->user_cal_rcvd); +- rc = -ENOMEM; +- goto exit; ++ mutex_unlock(&penv->dev_lock); ++ return -ENOMEM; + } +- rc = copy_from_user((void *)penv->user_cal_data + +- penv->user_cal_rcvd, user_buffer, count); +- if (0 == rc) { ++ ++ cal_data = kmalloc(count, GFP_KERNEL); ++ if (!cal_data) { ++ mutex_unlock(&penv->dev_lock); ++ return -ENOMEM; ++ } ++ ++ rc = copy_from_user(cal_data, user_buffer, count); ++ if (!rc) { ++ memcpy(penv->user_cal_data + penv->user_cal_rcvd, ++ cal_data, count); + penv->user_cal_rcvd += count; + rc += count; + } ++ ++ kfree(cal_data); + if (penv->user_cal_rcvd == penv->user_cal_exp_size) { + penv->user_cal_available = true; + pr_info_ratelimited("wcnss: user cal written"); + } ++ mutex_unlock(&penv->dev_lock); + +-exit: + return rc; + } + ++static int wcnss_node_release(struct inode *inode, struct file *file) ++{ ++ return 0; ++} + + static int wcnss_notif_cb(struct notifier_block *this, unsigned long code, + void *ss_handle) +@@ -3444,6 +3446,7 @@ static const struct file_operations wcnss_node_fops = { + .open = wcnss_node_open, + .read = wcnss_wlan_read, + .write = wcnss_wlan_write, ++ .release = wcnss_node_release, + }; + + static struct miscdevice wcnss_misc = { +@@ -3471,6 +3474,13 @@ wcnss_wlan_probe(struct platform_device *pdev) + } + penv->pdev = pdev; + ++ penv->user_cal_data = ++ devm_kzalloc(&pdev->dev, MAX_CALIBRATED_DATA_SIZE, GFP_KERNEL); ++ if (!penv->user_cal_data) { ++ dev_err(&pdev->dev, "Failed to alloc memory for cal data.\n"); ++ return -ENOMEM; ++ } ++ + /* register sysfs entries */ + ret = wcnss_create_sysfs(&pdev->dev); + if (ret) { +@@ -3491,6 +3501,11 @@ wcnss_wlan_probe(struct platform_device *pdev) + mutex_init(&penv->pm_qos_mutex); + init_waitqueue_head(&penv->read_wait); + ++ penv->user_cal_rcvd = 0; ++ penv->user_cal_read = 0; ++ penv->user_cal_exp_size = 0; ++ penv->user_cal_available = false; ++ + /* Since we were built into the kernel we'll be called as part + * of kernel initialization. We don't know if userspace + * applications are available to service PIL at this time +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8281/0.patch b/Patches/Linux_CVEs/CVE-2017-8281/0.patch new file mode 100644 index 00000000..87e22688 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8281/0.patch @@ -0,0 +1,95 @@ +From 14290556e50c3264d633f79f9d998aa34d5049d6 Mon Sep 17 00:00:00 2001 +From: Arnaldo Carvalho de Melo +Date: Mon, 14 Mar 2016 09:56:35 -0300 +Subject: net: Fix use after free in the recvmmsg exit path + +The syzkaller fuzzer hit the following use-after-free: + + Call Trace: + [] __asan_report_load8_noabort+0x3e/0x40 mm/kasan/report.c:295 + [] __sys_recvmmsg+0x6fa/0x7f0 net/socket.c:2261 + [< inline >] SYSC_recvmmsg net/socket.c:2281 + [] SyS_recvmmsg+0x16f/0x180 net/socket.c:2270 + [] entry_SYSCALL_64_fastpath+0x16/0x7a + arch/x86/entry/entry_64.S:185 + +And, as Dmitry rightly assessed, that is because we can drop the +reference and then touch it when the underlying recvmsg calls return +some packets and then hit an error, which will make recvmmsg to set +sock->sk->sk_err, oops, fix it. + +Reported-and-Tested-by: Dmitry Vyukov +Cc: Alexander Potapenko +Cc: Eric Dumazet +Cc: Kostya Serebryany +Cc: Sasha Levin +Fixes: a2e2725541fa ("net: Introduce recvmmsg socket syscall") +http://lkml.kernel.org/r/20160122211644.GC2470@redhat.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: David S. Miller +Change-Id: I447302392f46841f31c374bdb560fe5ee9c2d687 +Git-repo: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git +Git-commit: 34b88a68f26a75e4fded796f1a49c40f82234b7d +Signed-off-by: Dennis Cagle +--- + net/socket.c | 38 +++++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +diff --git a/net/socket.c b/net/socket.c +index be0d5a2..09ae8ba 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -2447,31 +2447,31 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, + break; + } + +-out_put: +- fput_light(sock->file, fput_needed); +- + if (err == 0) +- return datagrams; ++ goto out_put; + +- if (datagrams != 0) { ++ if (datagrams == 0) { ++ datagrams = err; ++ goto out_put; ++ } ++ ++ /* ++ * We may return less entries than requested (vlen) if the ++ * sock is non block and there aren't enough datagrams... ++ */ ++ if (err != -EAGAIN) { + /* +- * We may return less entries than requested (vlen) if the +- * sock is non block and there aren't enough datagrams... ++ * ... or if recvmsg returns an error after we ++ * received some datagrams, where we record the ++ * error to return on the next call or if the ++ * app asks about it using getsockopt(SO_ERROR). + */ +- if (err != -EAGAIN) { +- /* +- * ... or if recvmsg returns an error after we +- * received some datagrams, where we record the +- * error to return on the next call or if the +- * app asks about it using getsockopt(SO_ERROR). +- */ +- sock->sk->sk_err = -err; +- } +- +- return datagrams; ++ sock->sk->sk_err = -err; + } ++out_put: ++ fput_light(sock->file, fput_needed); + +- return err; ++ return datagrams; + } + + SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-8281/1.patch b/Patches/Linux_CVEs/CVE-2017-8281/1.patch new file mode 100644 index 00000000..529968fd --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-8281/1.patch @@ -0,0 +1,34 @@ +From d4ff2f45e486f532f4c9a01deb1c79f659ef3438 Mon Sep 17 00:00:00 2001 +From: Mohit Aggarwal +Date: Sat, 22 Apr 2017 10:49:18 +0530 +Subject: diag: dci: Add protection while querying event status + +Currently, protection is missing when querying event +status due to which already removed dci client entry +might be accessed. This patch takes care of issue by +taking proper locking. + +CRs-Fixed: 2015892 +Change-Id: I4195c4c6198d85e96559f1728d74419527a76bc5 +Signed-off-by: Mohit Aggarwal +--- + drivers/char/diag/diagchar_core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c +index ffb34fb..ed473f9 100644 +--- a/drivers/char/diag/diagchar_core.c ++++ b/drivers/char/diag/diagchar_core.c +@@ -1379,7 +1379,9 @@ long diagchar_ioctl(struct file *filp, + result = diag_ioctl_dci_log_status(ioarg); + break; + case DIAG_IOCTL_DCI_EVENT_STATUS: ++ mutex_lock(&driver->dci_mutex); + result = diag_ioctl_dci_event_status(ioarg); ++ mutex_unlock(&driver->dci_mutex); + break; + case DIAG_IOCTL_DCI_CLEAR_LOGS: + if (copy_from_user((void *)&client_id, (void __user *)ioarg, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9074/0.patch b/Patches/Linux_CVEs/CVE-2017-9074/0.patch new file mode 100644 index 00000000..b4c2bb80 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9074/0.patch @@ -0,0 +1,231 @@ +From 2423496af35d94a87156b063ea5cedffc10a70a1 Mon Sep 17 00:00:00 2001 +From: Craig Gallek +Date: Tue, 16 May 2017 14:36:23 -0400 +Subject: ipv6: Prevent overrun when parsing v6 header options + +The KASAN warning repoted below was discovered with a syzkaller +program. The reproducer is basically: + int s = socket(AF_INET6, SOCK_RAW, NEXTHDR_HOP); + send(s, &one_byte_of_data, 1, MSG_MORE); + send(s, &more_than_mtu_bytes_data, 2000, 0); + +The socket() call sets the nexthdr field of the v6 header to +NEXTHDR_HOP, the first send call primes the payload with a non zero +byte of data, and the second send call triggers the fragmentation path. + +The fragmentation code tries to parse the header options in order +to figure out where to insert the fragment option. Since nexthdr points +to an invalid option, the calculation of the size of the network header +can made to be much larger than the linear section of the skb and data +is read outside of it. + +This fix makes ip6_find_1stfrag return an error if it detects +running out-of-bounds. + +[ 42.361487] ================================================================== +[ 42.364412] BUG: KASAN: slab-out-of-bounds in ip6_fragment+0x11c8/0x3730 +[ 42.365471] Read of size 840 at addr ffff88000969e798 by task ip6_fragment-oo/3789 +[ 42.366469] +[ 42.366696] CPU: 1 PID: 3789 Comm: ip6_fragment-oo Not tainted 4.11.0+ #41 +[ 42.367628] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014 +[ 42.368824] Call Trace: +[ 42.369183] dump_stack+0xb3/0x10b +[ 42.369664] print_address_description+0x73/0x290 +[ 42.370325] kasan_report+0x252/0x370 +[ 42.370839] ? ip6_fragment+0x11c8/0x3730 +[ 42.371396] check_memory_region+0x13c/0x1a0 +[ 42.371978] memcpy+0x23/0x50 +[ 42.372395] ip6_fragment+0x11c8/0x3730 +[ 42.372920] ? nf_ct_expect_unregister_notifier+0x110/0x110 +[ 42.373681] ? ip6_copy_metadata+0x7f0/0x7f0 +[ 42.374263] ? ip6_forward+0x2e30/0x2e30 +[ 42.374803] ip6_finish_output+0x584/0x990 +[ 42.375350] ip6_output+0x1b7/0x690 +[ 42.375836] ? ip6_finish_output+0x990/0x990 +[ 42.376411] ? ip6_fragment+0x3730/0x3730 +[ 42.376968] ip6_local_out+0x95/0x160 +[ 42.377471] ip6_send_skb+0xa1/0x330 +[ 42.377969] ip6_push_pending_frames+0xb3/0xe0 +[ 42.378589] rawv6_sendmsg+0x2051/0x2db0 +[ 42.379129] ? rawv6_bind+0x8b0/0x8b0 +[ 42.379633] ? _copy_from_user+0x84/0xe0 +[ 42.380193] ? debug_check_no_locks_freed+0x290/0x290 +[ 42.380878] ? ___sys_sendmsg+0x162/0x930 +[ 42.381427] ? rcu_read_lock_sched_held+0xa3/0x120 +[ 42.382074] ? sock_has_perm+0x1f6/0x290 +[ 42.382614] ? ___sys_sendmsg+0x167/0x930 +[ 42.383173] ? lock_downgrade+0x660/0x660 +[ 42.383727] inet_sendmsg+0x123/0x500 +[ 42.384226] ? inet_sendmsg+0x123/0x500 +[ 42.384748] ? inet_recvmsg+0x540/0x540 +[ 42.385263] sock_sendmsg+0xca/0x110 +[ 42.385758] SYSC_sendto+0x217/0x380 +[ 42.386249] ? SYSC_connect+0x310/0x310 +[ 42.386783] ? __might_fault+0x110/0x1d0 +[ 42.387324] ? lock_downgrade+0x660/0x660 +[ 42.387880] ? __fget_light+0xa1/0x1f0 +[ 42.388403] ? __fdget+0x18/0x20 +[ 42.388851] ? sock_common_setsockopt+0x95/0xd0 +[ 42.389472] ? SyS_setsockopt+0x17f/0x260 +[ 42.390021] ? entry_SYSCALL_64_fastpath+0x5/0xbe +[ 42.390650] SyS_sendto+0x40/0x50 +[ 42.391103] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.391731] RIP: 0033:0x7fbbb711e383 +[ 42.392217] RSP: 002b:00007ffff4d34f28 EFLAGS: 00000246 ORIG_RAX: 000000000000002c +[ 42.393235] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fbbb711e383 +[ 42.394195] RDX: 0000000000001000 RSI: 00007ffff4d34f60 RDI: 0000000000000003 +[ 42.395145] RBP: 0000000000000046 R08: 00007ffff4d34f40 R09: 0000000000000018 +[ 42.396056] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000400aad +[ 42.396598] R13: 0000000000000066 R14: 00007ffff4d34ee0 R15: 00007fbbb717af00 +[ 42.397257] +[ 42.397411] Allocated by task 3789: +[ 42.397702] save_stack_trace+0x16/0x20 +[ 42.398005] save_stack+0x46/0xd0 +[ 42.398267] kasan_kmalloc+0xad/0xe0 +[ 42.398548] kasan_slab_alloc+0x12/0x20 +[ 42.398848] __kmalloc_node_track_caller+0xcb/0x380 +[ 42.399224] __kmalloc_reserve.isra.32+0x41/0xe0 +[ 42.399654] __alloc_skb+0xf8/0x580 +[ 42.400003] sock_wmalloc+0xab/0xf0 +[ 42.400346] __ip6_append_data.isra.41+0x2472/0x33d0 +[ 42.400813] ip6_append_data+0x1a8/0x2f0 +[ 42.401122] rawv6_sendmsg+0x11ee/0x2db0 +[ 42.401505] inet_sendmsg+0x123/0x500 +[ 42.401860] sock_sendmsg+0xca/0x110 +[ 42.402209] ___sys_sendmsg+0x7cb/0x930 +[ 42.402582] __sys_sendmsg+0xd9/0x190 +[ 42.402941] SyS_sendmsg+0x2d/0x50 +[ 42.403273] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.403718] +[ 42.403871] Freed by task 1794: +[ 42.404146] save_stack_trace+0x16/0x20 +[ 42.404515] save_stack+0x46/0xd0 +[ 42.404827] kasan_slab_free+0x72/0xc0 +[ 42.405167] kfree+0xe8/0x2b0 +[ 42.405462] skb_free_head+0x74/0xb0 +[ 42.405806] skb_release_data+0x30e/0x3a0 +[ 42.406198] skb_release_all+0x4a/0x60 +[ 42.406563] consume_skb+0x113/0x2e0 +[ 42.406910] skb_free_datagram+0x1a/0xe0 +[ 42.407288] netlink_recvmsg+0x60d/0xe40 +[ 42.407667] sock_recvmsg+0xd7/0x110 +[ 42.408022] ___sys_recvmsg+0x25c/0x580 +[ 42.408395] __sys_recvmsg+0xd6/0x190 +[ 42.408753] SyS_recvmsg+0x2d/0x50 +[ 42.409086] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.409513] +[ 42.409665] The buggy address belongs to the object at ffff88000969e780 +[ 42.409665] which belongs to the cache kmalloc-512 of size 512 +[ 42.410846] The buggy address is located 24 bytes inside of +[ 42.410846] 512-byte region [ffff88000969e780, ffff88000969e980) +[ 42.411941] The buggy address belongs to the page: +[ 42.412405] page:ffffea000025a780 count:1 mapcount:0 mapping: (null) index:0x0 compound_mapcount: 0 +[ 42.413298] flags: 0x100000000008100(slab|head) +[ 42.413729] raw: 0100000000008100 0000000000000000 0000000000000000 00000001800c000c +[ 42.414387] raw: ffffea00002a9500 0000000900000007 ffff88000c401280 0000000000000000 +[ 42.415074] page dumped because: kasan: bad access detected +[ 42.415604] +[ 42.415757] Memory state around the buggy address: +[ 42.416222] ffff88000969e880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 42.416904] ffff88000969e900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 42.417591] >ffff88000969e980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ 42.418273] ^ +[ 42.418588] ffff88000969ea00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ 42.419273] ffff88000969ea80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ 42.419882] ================================================================== + +Reported-by: Andrey Konovalov +Signed-off-by: Craig Gallek +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_offload.c | 2 ++ + net/ipv6/ip6_output.c | 4 ++++ + net/ipv6/output_core.c | 14 ++++++++------ + net/ipv6/udp_offload.c | 2 ++ + 4 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index 93e58a5..eab36ab 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -117,6 +117,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, + + if (udpfrag) { + unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (unfrag_ip6hlen < 0) ++ return ERR_PTR(unfrag_ip6hlen); + fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); + fptr->frag_off = htons(offset); + if (skb->next) +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 58f6288..01deecd 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -598,6 +598,10 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, + u8 *prevhdr, nexthdr = 0; + + hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (hlen < 0) { ++ err = hlen; ++ goto fail; ++ } + nexthdr = *prevhdr; + + mtu = ip6_skb_dst_mtu(skb); +diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c +index cd42523..e9065b8 100644 +--- a/net/ipv6/output_core.c ++++ b/net/ipv6/output_core.c +@@ -79,14 +79,13 @@ EXPORT_SYMBOL(ipv6_select_ident); + int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + { + u16 offset = sizeof(struct ipv6hdr); +- struct ipv6_opt_hdr *exthdr = +- (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); + unsigned int packet_len = skb_tail_pointer(skb) - + skb_network_header(skb); + int found_rhdr = 0; + *nexthdr = &ipv6_hdr(skb)->nexthdr; + +- while (offset + 1 <= packet_len) { ++ while (offset <= packet_len) { ++ struct ipv6_opt_hdr *exthdr; + + switch (**nexthdr) { + +@@ -107,13 +106,16 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + return offset; + } + +- offset += ipv6_optlen(exthdr); +- *nexthdr = &exthdr->nexthdr; ++ if (offset + sizeof(struct ipv6_opt_hdr) > packet_len) ++ return -EINVAL; ++ + exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + + offset); ++ offset += ipv6_optlen(exthdr); ++ *nexthdr = &exthdr->nexthdr; + } + +- return offset; ++ return -EINVAL; + } + EXPORT_SYMBOL(ip6_find_1stfragopt); + +diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c +index ac858c4..b348cff 100644 +--- a/net/ipv6/udp_offload.c ++++ b/net/ipv6/udp_offload.c +@@ -91,6 +91,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, + * bytes to insert fragment header. + */ + unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (unfrag_ip6hlen < 0) ++ return ERR_PTR(unfrag_ip6hlen); + nexthdr = *prevhdr; + *prevhdr = NEXTHDR_FRAGMENT; + unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9074/1.patch b/Patches/Linux_CVEs/CVE-2017-9074/1.patch new file mode 100644 index 00000000..b95d9264 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9074/1.patch @@ -0,0 +1,229 @@ +From ad8a4d9d3f255a783d534a47d4b4ac611bb291d8 Mon Sep 17 00:00:00 2001 +From: Craig Gallek +Date: Tue, 16 May 2017 14:36:23 -0400 +Subject: ipv6: Prevent overrun when parsing v6 header options + +commit 2423496af35d94a87156b063ea5cedffc10a70a1 upstream. + +The KASAN warning repoted below was discovered with a syzkaller +program. The reproducer is basically: + int s = socket(AF_INET6, SOCK_RAW, NEXTHDR_HOP); + send(s, &one_byte_of_data, 1, MSG_MORE); + send(s, &more_than_mtu_bytes_data, 2000, 0); + +The socket() call sets the nexthdr field of the v6 header to +NEXTHDR_HOP, the first send call primes the payload with a non zero +byte of data, and the second send call triggers the fragmentation path. + +The fragmentation code tries to parse the header options in order +to figure out where to insert the fragment option. Since nexthdr points +to an invalid option, the calculation of the size of the network header +can made to be much larger than the linear section of the skb and data +is read outside of it. + +This fix makes ip6_find_1stfrag return an error if it detects +running out-of-bounds. + +[ 42.361487] ================================================================== +[ 42.364412] BUG: KASAN: slab-out-of-bounds in ip6_fragment+0x11c8/0x3730 +[ 42.365471] Read of size 840 at addr ffff88000969e798 by task ip6_fragment-oo/3789 +[ 42.366469] +[ 42.366696] CPU: 1 PID: 3789 Comm: ip6_fragment-oo Not tainted 4.11.0+ #41 +[ 42.367628] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014 +[ 42.368824] Call Trace: +[ 42.369183] dump_stack+0xb3/0x10b +[ 42.369664] print_address_description+0x73/0x290 +[ 42.370325] kasan_report+0x252/0x370 +[ 42.370839] ? ip6_fragment+0x11c8/0x3730 +[ 42.371396] check_memory_region+0x13c/0x1a0 +[ 42.371978] memcpy+0x23/0x50 +[ 42.372395] ip6_fragment+0x11c8/0x3730 +[ 42.372920] ? nf_ct_expect_unregister_notifier+0x110/0x110 +[ 42.373681] ? ip6_copy_metadata+0x7f0/0x7f0 +[ 42.374263] ? ip6_forward+0x2e30/0x2e30 +[ 42.374803] ip6_finish_output+0x584/0x990 +[ 42.375350] ip6_output+0x1b7/0x690 +[ 42.375836] ? ip6_finish_output+0x990/0x990 +[ 42.376411] ? ip6_fragment+0x3730/0x3730 +[ 42.376968] ip6_local_out+0x95/0x160 +[ 42.377471] ip6_send_skb+0xa1/0x330 +[ 42.377969] ip6_push_pending_frames+0xb3/0xe0 +[ 42.378589] rawv6_sendmsg+0x2051/0x2db0 +[ 42.379129] ? rawv6_bind+0x8b0/0x8b0 +[ 42.379633] ? _copy_from_user+0x84/0xe0 +[ 42.380193] ? debug_check_no_locks_freed+0x290/0x290 +[ 42.380878] ? ___sys_sendmsg+0x162/0x930 +[ 42.381427] ? rcu_read_lock_sched_held+0xa3/0x120 +[ 42.382074] ? sock_has_perm+0x1f6/0x290 +[ 42.382614] ? ___sys_sendmsg+0x167/0x930 +[ 42.383173] ? lock_downgrade+0x660/0x660 +[ 42.383727] inet_sendmsg+0x123/0x500 +[ 42.384226] ? inet_sendmsg+0x123/0x500 +[ 42.384748] ? inet_recvmsg+0x540/0x540 +[ 42.385263] sock_sendmsg+0xca/0x110 +[ 42.385758] SYSC_sendto+0x217/0x380 +[ 42.386249] ? SYSC_connect+0x310/0x310 +[ 42.386783] ? __might_fault+0x110/0x1d0 +[ 42.387324] ? lock_downgrade+0x660/0x660 +[ 42.387880] ? __fget_light+0xa1/0x1f0 +[ 42.388403] ? __fdget+0x18/0x20 +[ 42.388851] ? sock_common_setsockopt+0x95/0xd0 +[ 42.389472] ? SyS_setsockopt+0x17f/0x260 +[ 42.390021] ? entry_SYSCALL_64_fastpath+0x5/0xbe +[ 42.390650] SyS_sendto+0x40/0x50 +[ 42.391103] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.391731] RIP: 0033:0x7fbbb711e383 +[ 42.392217] RSP: 002b:00007ffff4d34f28 EFLAGS: 00000246 ORIG_RAX: 000000000000002c +[ 42.393235] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fbbb711e383 +[ 42.394195] RDX: 0000000000001000 RSI: 00007ffff4d34f60 RDI: 0000000000000003 +[ 42.395145] RBP: 0000000000000046 R08: 00007ffff4d34f40 R09: 0000000000000018 +[ 42.396056] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000400aad +[ 42.396598] R13: 0000000000000066 R14: 00007ffff4d34ee0 R15: 00007fbbb717af00 +[ 42.397257] +[ 42.397411] Allocated by task 3789: +[ 42.397702] save_stack_trace+0x16/0x20 +[ 42.398005] save_stack+0x46/0xd0 +[ 42.398267] kasan_kmalloc+0xad/0xe0 +[ 42.398548] kasan_slab_alloc+0x12/0x20 +[ 42.398848] __kmalloc_node_track_caller+0xcb/0x380 +[ 42.399224] __kmalloc_reserve.isra.32+0x41/0xe0 +[ 42.399654] __alloc_skb+0xf8/0x580 +[ 42.400003] sock_wmalloc+0xab/0xf0 +[ 42.400346] __ip6_append_data.isra.41+0x2472/0x33d0 +[ 42.400813] ip6_append_data+0x1a8/0x2f0 +[ 42.401122] rawv6_sendmsg+0x11ee/0x2db0 +[ 42.401505] inet_sendmsg+0x123/0x500 +[ 42.401860] sock_sendmsg+0xca/0x110 +[ 42.402209] ___sys_sendmsg+0x7cb/0x930 +[ 42.402582] __sys_sendmsg+0xd9/0x190 +[ 42.402941] SyS_sendmsg+0x2d/0x50 +[ 42.403273] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.403718] +[ 42.403871] Freed by task 1794: +[ 42.404146] save_stack_trace+0x16/0x20 +[ 42.404515] save_stack+0x46/0xd0 +[ 42.404827] kasan_slab_free+0x72/0xc0 +[ 42.405167] kfree+0xe8/0x2b0 +[ 42.405462] skb_free_head+0x74/0xb0 +[ 42.405806] skb_release_data+0x30e/0x3a0 +[ 42.406198] skb_release_all+0x4a/0x60 +[ 42.406563] consume_skb+0x113/0x2e0 +[ 42.406910] skb_free_datagram+0x1a/0xe0 +[ 42.407288] netlink_recvmsg+0x60d/0xe40 +[ 42.407667] sock_recvmsg+0xd7/0x110 +[ 42.408022] ___sys_recvmsg+0x25c/0x580 +[ 42.408395] __sys_recvmsg+0xd6/0x190 +[ 42.408753] SyS_recvmsg+0x2d/0x50 +[ 42.409086] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.409513] +[ 42.409665] The buggy address belongs to the object at ffff88000969e780 +[ 42.409665] which belongs to the cache kmalloc-512 of size 512 +[ 42.410846] The buggy address is located 24 bytes inside of +[ 42.410846] 512-byte region [ffff88000969e780, ffff88000969e980) +[ 42.411941] The buggy address belongs to the page: +[ 42.412405] page:ffffea000025a780 count:1 mapcount:0 mapping: (null) index:0x0 compound_mapcount: 0 +[ 42.413298] flags: 0x100000000008100(slab|head) +[ 42.413729] raw: 0100000000008100 0000000000000000 0000000000000000 00000001800c000c +[ 42.414387] raw: ffffea00002a9500 0000000900000007 ffff88000c401280 0000000000000000 +[ 42.415074] page dumped because: kasan: bad access detected +[ 42.415604] +[ 42.415757] Memory state around the buggy address: +[ 42.416222] ffff88000969e880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 42.416904] ffff88000969e900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 42.417591] >ffff88000969e980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ 42.418273] ^ +[ 42.418588] ffff88000969ea00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ 42.419273] ffff88000969ea80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ 42.419882] ================================================================== + +Reported-by: Andrey Konovalov +Signed-off-by: Craig Gallek +Signed-off-by: David S. Miller +[bwh: Backported to 3.2: adjust filenames, context] +Signed-off-by: Ben Hutchings +--- + net/ipv6/af_inet6.c | 2 ++ + net/ipv6/ip6_output.c | 18 ++++++++++++------ + net/ipv6/udp.c | 2 ++ + 3 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index 8657823..914c7d5 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -825,6 +825,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features) + sizeof(*ipv6h)); + if (proto == IPPROTO_UDP) { + unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (unfrag_ip6hlen < 0) ++ return ERR_PTR(unfrag_ip6hlen); + fptr = (struct frag_hdr *)(skb_network_header(skb) + + unfrag_ip6hlen); + fptr->frag_off = htons(offset); +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index c59f646..dd31060 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -562,13 +562,12 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) + int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + { + u16 offset = sizeof(struct ipv6hdr); +- struct ipv6_opt_hdr *exthdr = +- (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); + unsigned int packet_len = skb->tail - skb->network_header; + int found_rhdr = 0; + *nexthdr = &ipv6_hdr(skb)->nexthdr; + +- while (offset + 1 <= packet_len) { ++ while (offset <= packet_len) { ++ struct ipv6_opt_hdr *exthdr; + + switch (**nexthdr) { + +@@ -589,13 +588,16 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + return offset; + } + +- offset += ipv6_optlen(exthdr); +- *nexthdr = &exthdr->nexthdr; ++ if (offset + sizeof(struct ipv6_opt_hdr) > packet_len) ++ return -EINVAL; ++ + exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + + offset); ++ offset += ipv6_optlen(exthdr); ++ *nexthdr = &exthdr->nexthdr; + } + +- return offset; ++ return -EINVAL; + } + + void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) +@@ -630,6 +632,10 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) + struct net *net = dev_net(skb_dst(skb)->dev); + + hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (hlen < 0) { ++ err = hlen; ++ goto fail; ++ } + nexthdr = *prevhdr; + + mtu = ip6_skb_dst_mtu(skb); +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 03a7ed1..8157ae0 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1353,6 +1353,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) + * bytes to insert fragment header. + */ + unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (unfrag_ip6hlen < 0) ++ return ERR_PTR(unfrag_ip6hlen); + nexthdr = *prevhdr; + *prevhdr = NEXTHDR_FRAGMENT; + unfrag_len = skb_network_header(skb) - skb_mac_header(skb) + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9074/2.patch b/Patches/Linux_CVEs/CVE-2017-9074/2.patch new file mode 100644 index 00000000..7a5f14cb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9074/2.patch @@ -0,0 +1,97 @@ +From f7c2d2d7ebf9a110cafbe53199457c318f61a192 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Wed, 17 May 2017 22:54:11 -0400 +Subject: ipv6: Check ip6_find_1stfragopt() return value properly. + +commit 7dd7eb9513bd02184d45f000ab69d78cb1fa1531 upstream. + +Do not use unsigned variables to see if it returns a negative +error or not. + +Fixes: 2423496af35d ("ipv6: Prevent overrun when parsing v6 header options") +Reported-by: Julia Lawall +Signed-off-by: David S. Miller +[bwh: Backported to 3.2: adjust filenames, context] +Signed-off-by: Ben Hutchings +--- + net/ipv6/af_inet6.c | 9 ++++----- + net/ipv6/ip6_output.c | 7 +++---- + net/ipv6/udp.c | 8 +++++--- + 3 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c +index 914c7d5..b0e4fb8 100644 +--- a/net/ipv6/af_inet6.c ++++ b/net/ipv6/af_inet6.c +@@ -785,7 +785,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features) + const struct inet6_protocol *ops; + int proto; + struct frag_hdr *fptr; +- unsigned int unfrag_ip6hlen; + u8 *prevhdr; + int offset = 0; + +@@ -824,11 +823,11 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features) + ipv6h->payload_len = htons(skb->len - skb->mac_len - + sizeof(*ipv6h)); + if (proto == IPPROTO_UDP) { +- unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); +- if (unfrag_ip6hlen < 0) +- return ERR_PTR(unfrag_ip6hlen); ++ int err = ip6_find_1stfragopt(skb, &prevhdr); ++ if (err < 0) ++ return ERR_PTR(err); + fptr = (struct frag_hdr *)(skb_network_header(skb) + +- unfrag_ip6hlen); ++ err); + fptr->frag_off = htons(offset); + if (skb->next != NULL) + fptr->frag_off |= htons(IP6_MF); +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index dd31060..81a7803 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -631,11 +631,10 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) + u8 *prevhdr, nexthdr = 0; + struct net *net = dev_net(skb_dst(skb)->dev); + +- hlen = ip6_find_1stfragopt(skb, &prevhdr); +- if (hlen < 0) { +- err = hlen; ++ err = ip6_find_1stfragopt(skb, &prevhdr); ++ if (err < 0) + goto fail; +- } ++ hlen = err; + nexthdr = *prevhdr; + + mtu = ip6_skb_dst_mtu(skb); +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 8157ae0..5f0d519 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1316,6 +1316,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) + u8 frag_hdr_sz = sizeof(struct frag_hdr); + int offset; + __wsum csum; ++ int err; + + mss = skb_shinfo(skb)->gso_size; + if (unlikely(skb->len <= mss)) +@@ -1352,9 +1353,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) + /* Find the unfragmentable header and shift it left by frag_hdr_sz + * bytes to insert fragment header. + */ +- unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); +- if (unfrag_ip6hlen < 0) +- return ERR_PTR(unfrag_ip6hlen); ++ err = ip6_find_1stfragopt(skb, &prevhdr); ++ if (err < 0) ++ return ERR_PTR(err); ++ unfrag_ip6hlen = err; + nexthdr = *prevhdr; + *prevhdr = NEXTHDR_FRAGMENT; + unfrag_len = skb_network_header(skb) - skb_mac_header(skb) + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9075/0.patch b/Patches/Linux_CVEs/CVE-2017-9075/0.patch new file mode 100644 index 00000000..238ab02f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9075/0.patch @@ -0,0 +1,33 @@ +From fdcee2cbb8438702ea1b328fb6e0ac5e9a40c7f8 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 17 May 2017 07:16:40 -0700 +Subject: sctp: do not inherit ipv6_{mc|ac|fl}_list from parent + +SCTP needs fixes similar to 83eaddab4378 ("ipv6/dccp: do not inherit +ipv6_mc_list from parent"), otherwise bad things can happen. + +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: David S. Miller +--- + net/sctp/ipv6.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c +index 142b70e..f5b45b8 100644 +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -677,6 +677,9 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, + newnp = inet6_sk(newsk); + + memcpy(newnp, np, sizeof(struct ipv6_pinfo)); ++ newnp->ipv6_mc_list = NULL; ++ newnp->ipv6_ac_list = NULL; ++ newnp->ipv6_fl_list = NULL; + + rcu_read_lock(); + opt = rcu_dereference(np->opt); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9076/0.patch b/Patches/Linux_CVEs/CVE-2017-9076/0.patch new file mode 100644 index 00000000..828a8905 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9076/0.patch @@ -0,0 +1,64 @@ +From 83eaddab4378db256d00d295bda6ca997cd13a52 Mon Sep 17 00:00:00 2001 +From: WANG Cong +Date: Tue, 9 May 2017 16:59:54 -0700 +Subject: ipv6/dccp: do not inherit ipv6_mc_list from parent + +Like commit 657831ffc38e ("dccp/tcp: do not inherit mc_list from parent") +we should clear ipv6_mc_list etc. for IPv6 sockets too. + +Cc: Eric Dumazet +Signed-off-by: Cong Wang +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/dccp/ipv6.c | 6 ++++++ + net/ipv6/tcp_ipv6.c | 2 ++ + 2 files changed, 8 insertions(+) + +diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c +index d9b6a4e..b6bbb71 100644 +--- a/net/dccp/ipv6.c ++++ b/net/dccp/ipv6.c +@@ -426,6 +426,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, + newsk->sk_backlog_rcv = dccp_v4_do_rcv; + newnp->pktoptions = NULL; + newnp->opt = NULL; ++ newnp->ipv6_mc_list = NULL; ++ newnp->ipv6_ac_list = NULL; ++ newnp->ipv6_fl_list = NULL; + newnp->mcast_oif = inet6_iif(skb); + newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; + +@@ -490,6 +493,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, + /* Clone RX bits */ + newnp->rxopt.all = np->rxopt.all; + ++ newnp->ipv6_mc_list = NULL; ++ newnp->ipv6_ac_list = NULL; ++ newnp->ipv6_fl_list = NULL; + newnp->pktoptions = NULL; + newnp->opt = NULL; + newnp->mcast_oif = inet6_iif(skb); +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index aeb9497..df5a9ff 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1062,6 +1062,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * + newtp->af_specific = &tcp_sock_ipv6_mapped_specific; + #endif + ++ newnp->ipv6_mc_list = NULL; + newnp->ipv6_ac_list = NULL; + newnp->ipv6_fl_list = NULL; + newnp->pktoptions = NULL; +@@ -1131,6 +1132,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * + First: no IPv4 options. + */ + newinet->inet_opt = NULL; ++ newnp->ipv6_mc_list = NULL; + newnp->ipv6_ac_list = NULL; + newnp->ipv6_fl_list = NULL; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9077/0.patch b/Patches/Linux_CVEs/CVE-2017-9077/0.patch new file mode 100644 index 00000000..828a8905 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9077/0.patch @@ -0,0 +1,64 @@ +From 83eaddab4378db256d00d295bda6ca997cd13a52 Mon Sep 17 00:00:00 2001 +From: WANG Cong +Date: Tue, 9 May 2017 16:59:54 -0700 +Subject: ipv6/dccp: do not inherit ipv6_mc_list from parent + +Like commit 657831ffc38e ("dccp/tcp: do not inherit mc_list from parent") +we should clear ipv6_mc_list etc. for IPv6 sockets too. + +Cc: Eric Dumazet +Signed-off-by: Cong Wang +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/dccp/ipv6.c | 6 ++++++ + net/ipv6/tcp_ipv6.c | 2 ++ + 2 files changed, 8 insertions(+) + +diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c +index d9b6a4e..b6bbb71 100644 +--- a/net/dccp/ipv6.c ++++ b/net/dccp/ipv6.c +@@ -426,6 +426,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, + newsk->sk_backlog_rcv = dccp_v4_do_rcv; + newnp->pktoptions = NULL; + newnp->opt = NULL; ++ newnp->ipv6_mc_list = NULL; ++ newnp->ipv6_ac_list = NULL; ++ newnp->ipv6_fl_list = NULL; + newnp->mcast_oif = inet6_iif(skb); + newnp->mcast_hops = ipv6_hdr(skb)->hop_limit; + +@@ -490,6 +493,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, + /* Clone RX bits */ + newnp->rxopt.all = np->rxopt.all; + ++ newnp->ipv6_mc_list = NULL; ++ newnp->ipv6_ac_list = NULL; ++ newnp->ipv6_fl_list = NULL; + newnp->pktoptions = NULL; + newnp->opt = NULL; + newnp->mcast_oif = inet6_iif(skb); +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index aeb9497..df5a9ff 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1062,6 +1062,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * + newtp->af_specific = &tcp_sock_ipv6_mapped_specific; + #endif + ++ newnp->ipv6_mc_list = NULL; + newnp->ipv6_ac_list = NULL; + newnp->ipv6_fl_list = NULL; + newnp->pktoptions = NULL; +@@ -1131,6 +1132,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * + First: no IPv4 options. + */ + newinet->inet_opt = NULL; ++ newnp->ipv6_mc_list = NULL; + newnp->ipv6_ac_list = NULL; + newnp->ipv6_fl_list = NULL; + +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9150/0.patch b/Patches/Linux_CVEs/CVE-2017-9150/0.patch new file mode 100644 index 00000000..7894fb62 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9150/0.patch @@ -0,0 +1,75 @@ +From 0d0e57697f162da4aa218b5feafe614fb666db07 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Mon, 8 May 2017 00:04:09 +0200 +Subject: [PATCH] bpf: don't let ldimm64 leak map addresses on unprivileged + +The patch fixes two things at once: + +1) It checks the env->allow_ptr_leaks and only prints the map address to + the log if we have the privileges to do so, otherwise it just dumps 0 + as we would when kptr_restrict is enabled on %pK. Given the latter is + off by default and not every distro sets it, I don't want to rely on + this, hence the 0 by default for unprivileged. + +2) Printing of ldimm64 in the verifier log is currently broken in that + we don't print the full immediate, but only the 32 bit part of the + first insn part for ldimm64. Thus, fix this up as well; it's okay to + access, since we verified all ldimm64 earlier already (including just + constants) through replace_map_fd_with_map_ptr(). + +Fixes: 1be7f75d1668 ("bpf: enable non-root eBPF programs") +Fixes: cbd357008604 ("bpf: verifier (add ability to receive verification log)") +Reported-by: Jann Horn +Signed-off-by: Daniel Borkmann +Acked-by: Alexei Starovoitov +Signed-off-by: David S. Miller +--- + kernel/bpf/verifier.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index c2ff608c1984e..c5b56c92f8e25 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -298,7 +298,8 @@ static const char *const bpf_jmp_string[16] = { + [BPF_EXIT >> 4] = "exit", + }; + +-static void print_bpf_insn(struct bpf_insn *insn) ++static void print_bpf_insn(const struct bpf_verifier_env *env, ++ const struct bpf_insn *insn) + { + u8 class = BPF_CLASS(insn->code); + +@@ -362,9 +363,19 @@ static void print_bpf_insn(struct bpf_insn *insn) + insn->code, + bpf_ldst_string[BPF_SIZE(insn->code) >> 3], + insn->src_reg, insn->imm); +- } else if (BPF_MODE(insn->code) == BPF_IMM) { +- verbose("(%02x) r%d = 0x%x\n", +- insn->code, insn->dst_reg, insn->imm); ++ } else if (BPF_MODE(insn->code) == BPF_IMM && ++ BPF_SIZE(insn->code) == BPF_DW) { ++ /* At this point, we already made sure that the second ++ * part of the ldimm64 insn is accessible. ++ */ ++ u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm; ++ bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD; ++ ++ if (map_ptr && !env->allow_ptr_leaks) ++ imm = 0; ++ ++ verbose("(%02x) r%d = 0x%llx\n", insn->code, ++ insn->dst_reg, (unsigned long long)imm); + } else { + verbose("BUG_ld_%02x\n", insn->code); + return; +@@ -2853,7 +2864,7 @@ static int do_check(struct bpf_verifier_env *env) + + if (log_level) { + verbose("%d: ", insn_idx); +- print_bpf_insn(insn); ++ print_bpf_insn(env, insn); + } + + err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx); diff --git a/Patches/Linux_CVEs/CVE-2017-9242/0.patch b/Patches/Linux_CVEs/CVE-2017-9242/0.patch new file mode 100644 index 00000000..247b5b64 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9242/0.patch @@ -0,0 +1,63 @@ +From 232cd35d0804cc241eb887bb8d4d9b3b9881c64a Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 19 May 2017 14:17:48 -0700 +Subject: [PATCH] ipv6: fix out of bound writes in __ip6_append_data() + +Andrey Konovalov and idaifish@gmail.com reported crashes caused by +one skb shared_info being overwritten from __ip6_append_data() + +Andrey program lead to following state : + +copy -4200 datalen 2000 fraglen 2040 +maxfraglen 2040 alloclen 2048 transhdrlen 0 offset 0 fraggap 6200 + +The skb_copy_and_csum_bits(skb_prev, maxfraglen, data + transhdrlen, +fraggap, 0); is overwriting skb->head and skb_shared_info + +Since we apparently detect this rare condition too late, move the +code earlier to even avoid allocating skb and risking crashes. + +Once again, many thanks to Andrey and syzkaller team. + +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Reported-by: +Signed-off-by: David S. Miller +--- + net/ipv6/ip6_output.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index d4a31becbd25d..bf8a58a1c32d8 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1466,6 +1466,11 @@ static int __ip6_append_data(struct sock *sk, + */ + alloclen += sizeof(struct frag_hdr); + ++ copy = datalen - transhdrlen - fraggap; ++ if (copy < 0) { ++ err = -EINVAL; ++ goto error; ++ } + if (transhdrlen) { + skb = sock_alloc_send_skb(sk, + alloclen + hh_len, +@@ -1515,13 +1520,9 @@ static int __ip6_append_data(struct sock *sk, + data += fraggap; + pskb_trim_unique(skb_prev, maxfraglen); + } +- copy = datalen - transhdrlen - fraggap; +- +- if (copy < 0) { +- err = -EINVAL; +- kfree_skb(skb); +- goto error; +- } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { ++ if (copy > 0 && ++ getfrag(from, data + transhdrlen, offset, ++ copy, fraggap, skb) < 0) { + err = -EFAULT; + kfree_skb(skb); + goto error; diff --git a/Patches/Linux_CVEs/CVE-2017-9676/0.patch b/Patches/Linux_CVEs/CVE-2017-9676/0.patch new file mode 100644 index 00000000..a63b017b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9676/0.patch @@ -0,0 +1,347 @@ +From c1f749639030305a3b02185c180240a8195fb715 Mon Sep 17 00:00:00 2001 +From: Maria Yu +Date: Fri, 21 Apr 2017 16:06:14 +0800 +Subject: soc: qcom: msm_bus: add mutex lock for cllist data + +Cldata needed to be protected by lock since crash +happened when synchronous update and free. + +CRs-Fixed: 2034222 +Change-Id: Ied86461b784d69d9758dc3fc793a8a0de86e7f9c +Signed-off-by: Maria Yu +--- + drivers/platform/msm/msm_bus/msm_bus_dbg.c | 102 +++++++++++++++++++++-------- + 1 file changed, 76 insertions(+), 26 deletions(-) + +diff --git a/drivers/platform/msm/msm_bus/msm_bus_dbg.c b/drivers/platform/msm/msm_bus/msm_bus_dbg.c +index 88ba186..8db3a62 100644 +--- a/drivers/platform/msm/msm_bus/msm_bus_dbg.c ++++ b/drivers/platform/msm/msm_bus/msm_bus_dbg.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2012, 2014-2015, The Linux Foundation. All rights ++/* Copyright (c) 2010-2012, 2014-2015, 2017 The Linux Foundation. All rights + * reserved. + * + * This program is free software; you can redistribute it and/or modify +@@ -38,6 +38,7 @@ + static struct dentry *clients; + static struct dentry *dir; + static DEFINE_MUTEX(msm_bus_dbg_fablist_lock); ++static DEFINE_RT_MUTEX(msm_bus_dbg_cllist_lock); + struct msm_bus_dbg_state { + uint32_t cl; + uint8_t enable; +@@ -289,7 +290,9 @@ static ssize_t client_data_read(struct file *file, char __user *buf, + struct msm_bus_cldata *cldata = NULL; + const struct msm_bus_client_handle *handle = file->private_data; + int found = 0; ++ ssize_t ret; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if ((cldata->clid == cl) || + (cldata->handle && (cldata->handle == handle))) { +@@ -298,12 +301,17 @@ static ssize_t client_data_read(struct file *file, char __user *buf, + } + } + +- if (!found) ++ if (!found) { ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return 0; ++ } + + bsize = cldata->size; +- return simple_read_from_buffer(buf, count, ppos, ++ ret = simple_read_from_buffer(buf, count, ppos, + cldata->buffer, bsize); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); ++ ++ return ret; + } + + static int client_data_open(struct inode *inode, struct file *file) +@@ -339,7 +347,9 @@ int msm_bus_dbg_add_client(const struct msm_bus_client_handle *pdata) + return -ENOMEM; + } + cldata->handle = pdata; ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_add_tail(&cldata->list, &cl_list); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return 0; + } + +@@ -352,6 +362,7 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, + bool found = false; + char *buf = NULL; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->handle == pdata) { + found = true; +@@ -359,12 +370,15 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, + } + } + +- if (!found) ++ if (!found) { ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return -ENOENT; ++ } + + if (cldata->file == NULL) { + if (pdata->name == NULL) { + MSM_BUS_DBG("Client doesn't have a name\n"); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return -EINVAL; + } + cldata->file = debugfs_create_file(pdata->name, S_IRUGO, +@@ -393,6 +407,7 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, + i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%llu ", ib); + i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n"); + cldata->size = i; ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + + trace_bus_update_request((int)ts.tv_sec, (int)ts.tv_nsec, + pdata->name, pdata->mas, pdata->slv, ab, ib); +@@ -404,6 +419,7 @@ void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata) + { + struct msm_bus_cldata *cldata = NULL; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->handle == pdata) { + debugfs_remove(cldata->file); +@@ -412,6 +428,7 @@ void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata) + break; + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + } + + static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, +@@ -429,7 +446,9 @@ static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, + cldata->clid = clid; + cldata->file = file; + cldata->size = 0; ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_add_tail(&cldata->list, &cl_list); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return 0; + } + +@@ -437,6 +456,7 @@ static void msm_bus_dbg_free_client(uint32_t clid) + { + struct msm_bus_cldata *cldata = NULL; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->clid == clid) { + debugfs_remove(cldata->file); +@@ -445,6 +465,7 @@ static void msm_bus_dbg_free_client(uint32_t clid) + break; + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + } + + static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, +@@ -456,6 +477,7 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, + struct timespec ts; + int found = 0; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->clid == clid) { + found = 1; +@@ -463,11 +485,14 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, + } + } + +- if (!found) ++ if (!found) { ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return -ENOENT; ++ } + + if (cldata->file == NULL) { + if (pdata->name == NULL) { ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + MSM_BUS_DBG("Client doesn't have a name\n"); + return -EINVAL; + } +@@ -515,19 +540,9 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, + + cldata->index = index; + cldata->size = i; +- return i; +-} +- +-static int msm_bus_dbg_update_request(struct msm_bus_cldata *cldata, int index) +-{ +- int ret = 0; ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + +- if ((index < 0) || (index > cldata->pdata->num_usecases)) { +- MSM_BUS_DBG("Invalid index!\n"); +- return -EINVAL; +- } +- ret = msm_bus_scale_client_update_request(cldata->clid, index); +- return ret; ++ return i; + } + + static ssize_t msm_bus_dbg_update_request_write(struct file *file, +@@ -539,19 +554,26 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file, + char *chid; + char *buf = kmalloc((sizeof(char) * (cnt + 1)), GFP_KERNEL); + int found = 0; ++ uint32_t clid; ++ ssize_t res = cnt; + + if (!buf || IS_ERR(buf)) { + MSM_BUS_ERR("Memory allocation for buffer failed\n"); + return -ENOMEM; + } +- if (cnt == 0) +- return 0; +- if (copy_from_user(buf, ubuf, cnt)) +- return -EFAULT; ++ if (cnt == 0) { ++ res = 0; ++ goto out; ++ } ++ if (copy_from_user(buf, ubuf, cnt)) { ++ res = -EFAULT; ++ goto out; ++ } + buf[cnt] = '\0'; + chid = buf; + MSM_BUS_DBG("buffer: %s\n size: %zu\n", buf, sizeof(ubuf)); + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (strnstr(chid, cldata->pdata->name, cnt)) { + found = 1; +@@ -562,21 +584,35 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file, + if (ret) { + MSM_BUS_DBG("Index conversion" + " failed\n"); +- return -EFAULT; ++ rt_mutex_unlock( ++ &msm_bus_dbg_cllist_lock); ++ res = -EFAULT; ++ goto out; + } + } else { + MSM_BUS_DBG("Error parsing input. Index not" + " found\n"); + found = 0; + } ++ if ((index < 0) || ++ (index > cldata->pdata->num_usecases)) { ++ MSM_BUS_DBG("Invalid index!\n"); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); ++ res = -EINVAL; ++ goto out; ++ } ++ clid = cldata->clid; + break; + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + + if (found) +- msm_bus_dbg_update_request(cldata, index); ++ msm_bus_scale_client_update_request(clid, index); ++ ++out: + kfree(buf); +- return cnt; ++ return res; + } + + /** +@@ -599,8 +635,10 @@ static ssize_t fabric_data_read(struct file *file, char __user *buf, + break; + } + } +- if (!found) ++ if (!found) { ++ mutex_unlock(&msm_bus_dbg_fablist_lock); + return -ENOENT; ++ } + bsize = fablist->size; + ret = simple_read_from_buffer(buf, count, ppos, + fablist->buffer, bsize); +@@ -689,8 +727,10 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname, + break; + } + } +- if (!found) ++ if (!found) { ++ mutex_unlock(&msm_bus_dbg_fablist_lock); + return -ENOENT; ++ } + + if (fablist->file == NULL) { + MSM_BUS_DBG("Fabric dbg entry does not exist\n"); +@@ -741,6 +781,8 @@ static ssize_t msm_bus_dbg_dump_clients_read(struct file *file, + "\nDumping curent client votes to trace log\n"); + if (*ppos) + goto exit_dump_clients_read; ++ ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (IS_ERR_OR_NULL(cldata->pdata)) + continue; +@@ -756,6 +798,7 @@ static ssize_t msm_bus_dbg_dump_clients_read(struct file *file, + cldata->pdata->active_only); + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + exit_dump_clients_read: + return simple_read_from_buffer(buf, count, ppos, msg, cnt); + } +@@ -880,6 +923,7 @@ static int __init msm_bus_debugfs_init(void) + goto err; + } + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->pdata) { + if (cldata->pdata->name == NULL) { +@@ -899,6 +943,7 @@ static int __init msm_bus_debugfs_init(void) + &client_data_fops); + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + + if (debugfs_create_file("dump_clients", S_IRUGO | S_IWUSR, + clients, NULL, &msm_bus_dbg_dump_clients_fops) == NULL) +@@ -911,6 +956,7 @@ static int __init msm_bus_debugfs_init(void) + if (fablist->file == NULL) { + MSM_BUS_DBG("Cannot create files for commit data\n"); + kfree(rules_buf); ++ mutex_unlock(&msm_bus_dbg_fablist_lock); + goto err; + } + } +@@ -930,10 +976,14 @@ static void __exit msm_bus_dbg_teardown(void) + struct msm_bus_cldata *cldata = NULL, *cldata_temp; + + debugfs_remove_recursive(dir); ++ ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry_safe(cldata, cldata_temp, &cl_list, list) { + list_del(&cldata->list); + kfree(cldata); + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); ++ + mutex_lock(&msm_bus_dbg_fablist_lock); + list_for_each_entry_safe(fablist, fablist_temp, &fabdata_list, list) { + list_del(&fablist->list); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9676/1.patch b/Patches/Linux_CVEs/CVE-2017-9676/1.patch new file mode 100644 index 00000000..44facbac --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9676/1.patch @@ -0,0 +1,272 @@ +From d109d8d7e2998a635406215a559e298fa7ef4bb8 Mon Sep 17 00:00:00 2001 +From: "lianwei.wang" +Date: Fri, 30 Mar 2012 12:05:50 +0800 +Subject: [PATCH] IKHSS7-18791 msm:fix the list usage in msm_bus_dbg + +The list usage in msm_bus_dbg driver are not correct which will cause +kernel panic. + . The list operation should be protected by a lock, e.g. mutex_lock. + . The list entry should only be operated on a valid entry. + +Change-Id: I19efeb346d1bacf129ccfd7a6511bc795c029afc +Signed-off-by: Lianwei Wang +Reviewed-on: http://gerrit.pcs.mot.com/384275 +Reviewed-by: Guo-Jian Chen +Reviewed-by: Ke Lv +Tested-by: Jira Key +Reviewed-by: Jeffrey Carlyle +Reviewed-by: Check Patch +Reviewed-by: Klocwork kwcheck +Reviewed-by: Tao Hu +--- + arch/arm/mach-msm/msm_bus/msm_bus_dbg.c | 74 ++++++++++++++++++++++++++------- + 1 file changed, 58 insertions(+), 16 deletions(-) + +diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c +index abd986bca68..76173529d35 100644 +--- a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c ++++ b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c +@@ -28,6 +28,7 @@ + static struct dentry *clients; + static struct dentry *dir; + static DEFINE_MUTEX(msm_bus_dbg_fablist_lock); ++static DEFINE_MUTEX(msm_bus_dbg_cllist_lock); + struct msm_bus_dbg_state { + uint32_t cl; + uint8_t enable; +@@ -271,16 +272,21 @@ static ssize_t client_data_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) + { + int bsize = 0; ++ ssize_t read_count = 0; + uint32_t cl = (uint32_t)file->private_data; + struct msm_bus_cldata *cldata = NULL; + ++ mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { +- if (cldata->clid == cl) ++ if (cldata->clid == cl) { ++ bsize = cldata->size; ++ read_count = simple_read_from_buffer(buf, count, ppos, ++ cldata->buffer, bsize); + break; ++ } + } +- bsize = cldata->size; +- return simple_read_from_buffer(buf, count, ppos, +- cldata->buffer, bsize); ++ mutex_unlock(&msm_bus_dbg_cllist_lock); ++ return read_count; + } + + static int client_data_open(struct inode *inode, struct file *file) +@@ -310,9 +316,11 @@ static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, + { + struct msm_bus_cldata *cldata; + ++ mutex_lock(&msm_bus_dbg_cllist_lock); + cldata = kmalloc(sizeof(struct msm_bus_cldata), GFP_KERNEL); + if (!cldata) { + MSM_BUS_DBG("Failed to allocate memory for client data\n"); ++ mutex_unlock(&msm_bus_dbg_cllist_lock); + return -ENOMEM; + } + cldata->pdata = pdata; +@@ -321,6 +329,7 @@ static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, + cldata->file = file; + cldata->size = 0; + list_add_tail(&cldata->list, &cl_list); ++ mutex_unlock(&msm_bus_dbg_cllist_lock); + return 0; + } + +@@ -328,6 +337,7 @@ static void msm_bus_dbg_free_client(uint32_t clid) + { + struct msm_bus_cldata *cldata = NULL; + ++ mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->clid == clid) { + debugfs_remove(cldata->file); +@@ -336,23 +346,34 @@ static void msm_bus_dbg_free_client(uint32_t clid) + break; + } + } ++ mutex_unlock(&msm_bus_dbg_cllist_lock); + } + + static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, + int index, uint32_t clid) + { +- int i = 0, j; ++ int i = 0, j, found = 0; + char *buf = NULL; + struct msm_bus_cldata *cldata = NULL; + struct timespec ts; + ++ mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { +- if (cldata->clid == clid) ++ if (cldata->clid == clid) { ++ found = 1; + break; ++ } ++ } ++ ++ if (!found) { ++ MSM_BUS_DBG("Client(clid=%d) doesn't exist\n", clid); ++ mutex_unlock(&msm_bus_dbg_cllist_lock); ++ return -EINVAL; + } + if (cldata->file == NULL) { + if (pdata->name == NULL) { + MSM_BUS_DBG("Client doesn't have a name\n"); ++ mutex_unlock(&msm_bus_dbg_cllist_lock); + return -EINVAL; + } + cldata->file = msm_bus_dbg_create(pdata->name, S_IRUGO, +@@ -390,6 +411,9 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, + i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n"); + + cldata->size = i; ++ ++ mutex_unlock(&msm_bus_dbg_cllist_lock); ++ + return i; + } + +@@ -426,6 +450,7 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file, + chid = buf; + MSM_BUS_DBG("buffer: %s\n size: %d\n", buf, sizeof(ubuf)); + ++ mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (strstr(chid, cldata->pdata->name)) { + cldata = cldata; +@@ -435,16 +460,19 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file, + if (ret) { + MSM_BUS_DBG("Index conversion" + " failed\n"); ++ mutex_unlock(&msm_bus_dbg_cllist_lock); + return -EFAULT; + } + } else + MSM_BUS_DBG("Error parsing input. Index not" + " found\n"); ++ msm_bus_dbg_update_request(cldata, index); + break; + } + } + +- msm_bus_dbg_update_request(cldata, index); ++ mutex_unlock(&msm_bus_dbg_cllist_lock); ++ + kfree(buf); + return cnt; + } +@@ -458,17 +486,18 @@ static ssize_t fabric_data_read(struct file *file, char __user *buf, + { + struct msm_bus_fab_list *fablist = NULL; + int bsize = 0; +- ssize_t ret; ++ ssize_t ret = 0; + const char *name = file->private_data; + + mutex_lock(&msm_bus_dbg_fablist_lock); + list_for_each_entry(fablist, &fabdata_list, list) { +- if (strcmp(fablist->name, name) == 0) ++ if (strcmp(fablist->name, name) == 0) { ++ bsize = fablist->size; ++ ret = simple_read_from_buffer(buf, count, ppos, ++ fablist->buffer, bsize); + break; ++ } + } +- bsize = fablist->size; +- ret = simple_read_from_buffer(buf, count, ppos, +- fablist->buffer, bsize); + mutex_unlock(&msm_bus_dbg_fablist_lock); + return ret; + } +@@ -519,16 +548,25 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname, + void *cdata, int nmasters, int nslaves, + int ntslaves) + { +- int i; ++ int i, found = 0; + char *buf = NULL; + struct msm_bus_fab_list *fablist = NULL; + struct timespec ts; + + mutex_lock(&msm_bus_dbg_fablist_lock); + list_for_each_entry(fablist, &fabdata_list, list) { +- if (strcmp(fablist->name, fabname) == 0) ++ if (strcmp(fablist->name, fabname) == 0) { ++ found = 1; + break; ++ } ++ } ++ ++ if (!found) { ++ MSM_BUS_DBG("Fabric dbg entry %s does not exist, fabname\n"); ++ mutex_unlock(&msm_bus_dbg_fablist_lock); ++ return -EINVAL; + } ++ + if (fablist->file == NULL) { + MSM_BUS_DBG("Fabric dbg entry does not exist\n"); + mutex_unlock(&msm_bus_dbg_fablist_lock); +@@ -542,7 +580,6 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname, + fablist->size = 0; + } + buf = fablist->buffer; +- mutex_unlock(&msm_bus_dbg_fablist_lock); + ts = ktime_to_timespec(ktime_get()); + i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n%d.%d\n", + (int)ts.tv_sec, (int)ts.tv_nsec); +@@ -550,7 +587,6 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname, + msm_bus_rpm_fill_cdata_buffer(&i, buf + i, MAX_BUFF_SIZE, cdata, + nmasters, nslaves, ntslaves); + i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n"); +- mutex_lock(&msm_bus_dbg_fablist_lock); + fablist->size = i; + mutex_unlock(&msm_bus_dbg_fablist_lock); + return 0; +@@ -660,6 +696,7 @@ static int __init msm_bus_debugfs_init(void) + clients, NULL, &msm_bus_dbg_update_request_fops) == NULL) + goto err; + ++ mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->pdata->name == NULL) { + MSM_BUS_DBG("Client name not found\n"); +@@ -668,6 +705,7 @@ static int __init msm_bus_debugfs_init(void) + cldata->file = msm_bus_dbg_create(cldata-> + pdata->name, S_IRUGO, clients, cldata->clid); + } ++ mutex_unlock(&msm_bus_dbg_cllist_lock); + + mutex_lock(&msm_bus_dbg_fablist_lock); + list_for_each_entry(fablist, &fabdata_list, list) { +@@ -675,6 +713,7 @@ static int __init msm_bus_debugfs_init(void) + commit, (void *)fablist->name, &fabric_data_fops); + if (fablist->file == NULL) { + MSM_BUS_DBG("Cannot create files for commit data\n"); ++ mutex_unlock(&msm_bus_dbg_fablist_lock); + goto err; + } + } +@@ -694,10 +733,13 @@ static void __exit msm_bus_dbg_teardown(void) + struct msm_bus_cldata *cldata = NULL, *cldata_temp; + + debugfs_remove_recursive(dir); ++ mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry_safe(cldata, cldata_temp, &cl_list, list) { + list_del(&cldata->list); + kfree(cldata); + } ++ mutex_unlock(&msm_bus_dbg_cllist_lock); ++ + mutex_lock(&msm_bus_dbg_fablist_lock); + list_for_each_entry_safe(fablist, fablist_temp, &fabdata_list, list) { + list_del(&fablist->list); diff --git a/Patches/Linux_CVEs/CVE-2017-9677/0.patch b/Patches/Linux_CVEs/CVE-2017-9677/0.patch new file mode 100644 index 00000000..a367d6ff --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9677/0.patch @@ -0,0 +1,1858 @@ +From b62291edb424281ed31a4e15140b16972ce9eef1 Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Thu, 27 Apr 2017 14:44:25 +0800 +Subject: ASoC: msm: remove unused msm-compr-q6-v2 + +msm-compr-q6-v2.c and msm-compr-q6-v2.h are no longer used. + +CRs-Fixed: 2022953 +Bug: 62379475 +Change-Id: I856d90a212a3e123a2c8b80092aff003f7c608c7 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/apq8084-i2s.c | 2 +- + sound/soc/msm/apq8084.c | 2 +- + sound/soc/msm/msm8226.c | 2 +- + sound/soc/msm/msm8974.c | 2 +- + sound/soc/msm/msm8994.c | 2 +- + sound/soc/msm/qdsp6v2/Makefile | 2 +- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c | 1707 ------------------------------- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h | 36 - + 8 files changed, 6 insertions(+), 1749 deletions(-) + delete mode 100644 sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c + delete mode 100644 sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h + +diff --git a/sound/soc/msm/apq8084-i2s.c b/sound/soc/msm/apq8084-i2s.c +index 794aa25..5897e9c 100644 +--- a/sound/soc/msm/apq8084-i2s.c ++++ b/sound/soc/msm/apq8084-i2s.c +@@ -1826,7 +1826,7 @@ static struct snd_soc_dai_link apq8084_dai_links[] = { + .name = "APQ8084 Compr8", + .stream_name = "COMPR8", + .cpu_dai_name = "MultiMedia8", +- .platform_name = "msm-compr-dsp", ++ .platform_name = "msm-compress-dsp", + .dynamic = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, +diff --git a/sound/soc/msm/apq8084.c b/sound/soc/msm/apq8084.c +index aa2e25f..2b02e5d 100644 +--- a/sound/soc/msm/apq8084.c ++++ b/sound/soc/msm/apq8084.c +@@ -3046,7 +3046,7 @@ static struct snd_soc_dai_link apq8084_common_dai_links[] = { + .name = "APQ8084 Compr8", + .stream_name = "COMPR8", + .cpu_dai_name = "MultiMedia8", +- .platform_name = "msm-compr-dsp", ++ .platform_name = "msm-compress-dsp", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE + | ASYNC_DPCM_SND_SOC_HW_PARAMS, +diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c +index 4095c12..113d77b 100644 +--- a/sound/soc/msm/msm8226.c ++++ b/sound/soc/msm/msm8226.c +@@ -1495,7 +1495,7 @@ static struct snd_soc_dai_link msm8226_common_dai[] = { + .name = "MSM8226 Compr8", + .stream_name = "COMPR8", + .cpu_dai_name = "MultiMedia8", +- .platform_name = "msm-compr-dsp", ++ .platform_name = "msm-compress-dsp", + .dynamic = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, +diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c +index fd69611..4cfd7c3 100644 +--- a/sound/soc/msm/msm8974.c ++++ b/sound/soc/msm/msm8974.c +@@ -2164,7 +2164,7 @@ static struct snd_soc_dai_link msm8974_common_dai_links[] = { + .name = "MSM8974 Compr8", + .stream_name = "COMPR8", + .cpu_dai_name = "MultiMedia8", +- .platform_name = "msm-compr-dsp", ++ .platform_name = "msm-compress-dsp", + .dynamic = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, +diff --git a/sound/soc/msm/msm8994.c b/sound/soc/msm/msm8994.c +index 1285c59..8678fb1 100644 +--- a/sound/soc/msm/msm8994.c ++++ b/sound/soc/msm/msm8994.c +@@ -2684,7 +2684,7 @@ static struct snd_soc_dai_link msm8994_common_dai_links[] = { + .name = "MSM8994 Compr8", + .stream_name = "COMPR8", + .cpu_dai_name = "MultiMedia8", +- .platform_name = "msm-compr-dsp", ++ .platform_name = "msm-compress-dsp", + .dynamic = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, +diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile +index 5865eb9..41f3984 100644 +--- a/sound/soc/msm/qdsp6v2/Makefile ++++ b/sound/soc/msm/qdsp6v2/Makefile +@@ -1,5 +1,5 @@ + snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \ +- msm-compress-q6-v2.o msm-compr-q6-v2.o \ ++ msm-compress-q6-v2.o \ + msm-pcm-lpa-v2.o \ + msm-pcm-afe-v2.o msm-pcm-voip-v2.o \ + msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o \ +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +deleted file mode 100644 +index 5fe5f24..0000000 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c ++++ /dev/null +@@ -1,1707 +0,0 @@ +-/* Copyright (c) 2012-2014, 2016 The 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 +- * only version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include "msm-compr-q6-v2.h" +-#include "msm-pcm-routing-v2.h" +-#include "audio_ocmem.h" +-#include +- +-#define COMPRE_CAPTURE_NUM_PERIODS 16 +-/* Allocate the worst case frame size for compressed audio */ +-#define COMPRE_CAPTURE_HEADER_SIZE (sizeof(struct snd_compr_audio_info)) +-/* Changing period size to 4032. 4032 will make sure COMPRE_CAPTURE_PERIOD_SIZE +- * is 4096 with meta data size of 64 and MAX_NUM_FRAMES_PER_BUFFER 1 +- */ +-#define COMPRE_CAPTURE_MAX_FRAME_SIZE (4032) +-#define COMPRE_CAPTURE_PERIOD_SIZE ((COMPRE_CAPTURE_MAX_FRAME_SIZE + \ +- COMPRE_CAPTURE_HEADER_SIZE) * \ +- MAX_NUM_FRAMES_PER_BUFFER) +-#define COMPRE_OUTPUT_METADATA_SIZE (sizeof(struct output_meta_data_st)) +-#define COMPRESSED_LR_VOL_MAX_STEPS 0x20002000 +- +-#define MAX_AC3_PARAM_SIZE (18*2*sizeof(int)) +-#define AMR_WB_BAND_MODE 8 +-#define AMR_WB_DTX_MODE 0 +- +- +-const DECLARE_TLV_DB_LINEAR(compr_rx_vol_gain, 0, +- COMPRESSED_LR_VOL_MAX_STEPS); +-struct snd_msm { +- atomic_t audio_ocmem_req; +-}; +-static struct snd_msm compressed_audio; +- +-static struct audio_locks the_locks; +- +-static struct snd_pcm_hardware msm_compr_hardware_capture = { +- .info = (SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_BLOCK_TRANSFER | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_INTERLEAVED | +- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), +- .formats = SNDRV_PCM_FMTBIT_S16_LE, +- .rates = SNDRV_PCM_RATE_8000_48000, +- .rate_min = 8000, +- .rate_max = 48000, +- .channels_min = 1, +- .channels_max = 8, +- .buffer_bytes_max = +- COMPRE_CAPTURE_PERIOD_SIZE * COMPRE_CAPTURE_NUM_PERIODS , +- .period_bytes_min = COMPRE_CAPTURE_PERIOD_SIZE, +- .period_bytes_max = COMPRE_CAPTURE_PERIOD_SIZE, +- .periods_min = COMPRE_CAPTURE_NUM_PERIODS, +- .periods_max = COMPRE_CAPTURE_NUM_PERIODS, +- .fifo_size = 0, +-}; +- +-static struct snd_pcm_hardware msm_compr_hardware_playback = { +- .info = (SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_BLOCK_TRANSFER | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_INTERLEAVED | +- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), +- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, +- .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT, +- .rate_min = 8000, +- .rate_max = 48000, +- .channels_min = 1, +- .channels_max = 8, +- .buffer_bytes_max = 1024 * 1024, +- .period_bytes_min = 128 * 1024, +- .period_bytes_max = 256 * 1024, +- .periods_min = 4, +- .periods_max = 8, +- .fifo_size = 0, +-}; +- +-/* Conventional and unconventional sample rate supported */ +-static unsigned int supported_sample_rates[] = { +- 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 +-}; +- +-/* Add supported codecs for compress capture path */ +-static uint32_t supported_compr_capture_codecs[] = { +- SND_AUDIOCODEC_AMRWB +-}; +- +-static struct snd_pcm_hw_constraint_list constraints_sample_rates = { +- .count = ARRAY_SIZE(supported_sample_rates), +- .list = supported_sample_rates, +- .mask = 0, +-}; +- +-static bool msm_compr_capture_codecs(uint32_t req_codec) +-{ +- int i; +- pr_debug("%s req_codec:%d\n", __func__, req_codec); +- if (req_codec == 0) +- return false; +- for (i = 0; i < ARRAY_SIZE(supported_compr_capture_codecs); i++) { +- if (req_codec == supported_compr_capture_codecs[i]) +- return true; +- } +- return false; +-} +- +-static void compr_event_handler(uint32_t opcode, +- uint32_t token, uint32_t *payload, void *priv) +-{ +- struct compr_audio *compr = priv; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_pcm_substream *substream = prtd->substream; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct audio_aio_write_param param; +- struct audio_aio_read_param read_param; +- struct audio_buffer *buf = NULL; +- phys_addr_t temp; +- struct output_meta_data_st output_meta_data; +- uint32_t *ptrmem = (uint32_t *)payload; +- int i = 0; +- int time_stamp_flag = 0; +- int buffer_length = 0; +- int stop_playback = 0; +- +- pr_debug("%s opcode =%08x\n", __func__, opcode); +- switch (opcode) { +- case ASM_DATA_EVENT_WRITE_DONE_V2: { +- uint32_t *ptrmem = (uint32_t *)¶m; +- pr_debug("ASM_DATA_EVENT_WRITE_DONE\n"); +- pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem); +- prtd->pcm_irq_pos += prtd->pcm_count; +- if (atomic_read(&prtd->start)) +- snd_pcm_period_elapsed(substream); +- else +- if (substream->timer_running) +- snd_timer_interrupt(substream->timer, 1); +- atomic_inc(&prtd->out_count); +- wake_up(&the_locks.write_wait); +- if (!atomic_read(&prtd->start)) { +- atomic_set(&prtd->pending_buffer, 1); +- break; +- } else +- atomic_set(&prtd->pending_buffer, 0); +- +- /* +- * check for underrun +- */ +- snd_pcm_stream_lock_irq(substream); +- if (runtime->status->hw_ptr >= runtime->control->appl_ptr) { +- runtime->render_flag |= SNDRV_RENDER_STOPPED; +- stop_playback = 1; +- } +- snd_pcm_stream_unlock_irq(substream); +- +- if (stop_playback) { +- pr_err("underrun! render stopped\n"); +- break; +- } +- +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", +- __func__, prtd->pcm_count, prtd->out_head); +- temp = buf[0].phys + (prtd->out_head * prtd->pcm_count); +- pr_debug("%s:writing buffer[%d] from 0x%pa\n", +- __func__, prtd->out_head, &temp); +- +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- if (buffer_length == 0) { +- pr_debug("Recieved a zero length buffer-break out"); +- break; +- } +- param.paddr = temp + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- for (i = 0; i < sizeof(struct audio_aio_write_param)/4; +- i++, ++ptrmem) +- pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem); +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) & (runtime->periods - 1); +- break; +- } +- case ASM_DATA_EVENT_RENDERED_EOS: +- pr_debug("ASM_DATA_CMDRSP_EOS\n"); +- if (atomic_read(&prtd->eos)) { +- pr_debug("ASM_DATA_CMDRSP_EOS wake up\n"); +- prtd->cmd_ack = 1; +- wake_up(&the_locks.eos_wait); +- atomic_set(&prtd->eos, 0); +- } +- break; +- case ASM_DATA_EVENT_READ_DONE_V2: { +- pr_debug("ASM_DATA_EVENT_READ_DONE\n"); +- pr_debug("buf = %pK, data = 0x%X, *data = %pK,\n" +- "prtd->pcm_irq_pos = %d\n", +- prtd->audio_client->port[OUT].buf, +- *(uint32_t *)prtd->audio_client->port[OUT].buf->data, +- prtd->audio_client->port[OUT].buf->data, +- prtd->pcm_irq_pos); +- +- memcpy(prtd->audio_client->port[OUT].buf->data + +- prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE), +- COMPRE_CAPTURE_HEADER_SIZE); +- pr_debug("buf = %pK, updated data = 0x%X, *data = %pK\n", +- prtd->audio_client->port[OUT].buf, +- *(uint32_t *)(prtd->audio_client->port[OUT].buf->data + +- prtd->pcm_irq_pos), +- prtd->audio_client->port[OUT].buf->data); +- if (!atomic_read(&prtd->start)) +- break; +- pr_debug("frame size=%d, buffer = 0x%X\n", +- ptrmem[READDONE_IDX_SIZE], +- ptrmem[READDONE_IDX_BUFADD_LSW]); +- if (ptrmem[READDONE_IDX_SIZE] > COMPRE_CAPTURE_MAX_FRAME_SIZE) { +- pr_err("Frame length exceeded the max length"); +- break; +- } +- buf = prtd->audio_client->port[OUT].buf; +- +- pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%pa\n", +- prtd->pcm_irq_pos, &buf[0].phys); +- read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE; +- read_param.paddr = buf[0].phys + +- prtd->pcm_irq_pos + COMPRE_CAPTURE_HEADER_SIZE; +- prtd->pcm_irq_pos += prtd->pcm_count; +- +- if (atomic_read(&prtd->start)) +- snd_pcm_period_elapsed(substream); +- +- q6asm_async_read(prtd->audio_client, &read_param); +- break; +- } +- case APR_BASIC_RSP_RESULT: { +- switch (payload[0]) { +- case ASM_SESSION_CMD_RUN_V2: { +- if (substream->stream +- != SNDRV_PCM_STREAM_PLAYBACK) { +- atomic_set(&prtd->start, 1); +- break; +- } +- if (!atomic_read(&prtd->pending_buffer)) +- break; +- pr_debug("%s: writing %d bytes of buffer[%d] to dsp\n", +- __func__, prtd->pcm_count, prtd->out_head); +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s: writing buffer[%d] from 0x%pa head %d count %d\n", +- __func__, prtd->out_head, &buf[0].phys, +- prtd->pcm_count, prtd->out_head); +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- param.paddr = buf[prtd->out_head].phys +- + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- param.metadata_len = COMPRE_OUTPUT_METADATA_SIZE; +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) +- & (runtime->periods - 1); +- atomic_set(&prtd->pending_buffer, 0); +- } +- break; +- case ASM_STREAM_CMD_FLUSH: +- pr_debug("ASM_STREAM_CMD_FLUSH\n"); +- prtd->cmd_ack = 1; +- wake_up(&the_locks.flush_wait); +- break; +- default: +- break; +- } +- break; +- } +- default: +- pr_debug("Not Supported Event opcode[0x%x]\n", opcode); +- break; +- } +-} +- +-static int msm_compr_send_ddp_cfg(struct audio_client *ac, +- struct snd_dec_ddp *ddp) +-{ +- int i, rc; +- pr_debug("%s\n", __func__); +- for (i = 0; i < ddp->params_length/2; i++) { +- rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i], +- ddp->params_value[i]); +- if (rc) { +- pr_err("sending params_id: %d failed\n", +- ddp->params_id[i]); +- return rc; +- } +- } +- return 0; +-} +- +-static int msm_compr_playback_prepare(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_pcm_hw_params *params; +- struct asm_aac_cfg aac_cfg; +- uint16_t bits_per_sample = 16; +- int ret; +- +- struct asm_softpause_params softpause = { +- .enable = SOFT_PAUSE_ENABLE, +- .period = SOFT_PAUSE_PERIOD, +- .step = SOFT_PAUSE_STEP, +- .rampingcurve = SOFT_PAUSE_CURVE_LINEAR, +- }; +- struct asm_softvolume_params softvol = { +- .period = SOFT_VOLUME_PERIOD, +- .step = SOFT_VOLUME_STEP, +- .rampingcurve = SOFT_VOLUME_CURVE_LINEAR, +- }; +- +- pr_debug("%s\n", __func__); +- +- params = &soc_prtd->dpcm[substream->stream].hw_params; +- if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) +- bits_per_sample = 24; +- +- ret = q6asm_open_write_v2(prtd->audio_client, +- compr->codec, bits_per_sample); +- if (ret < 0) { +- pr_err("%s: Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- msm_pcm_routing_reg_phy_stream( +- soc_prtd->dai_link->be_id, +- prtd->audio_client->perf_mode, +- prtd->session_id, +- substream->stream); +- /* +- * the number of channels are required to call volume api +- * accoridngly. So, get channels from hw params +- */ +- if ((params_channels(params) > 0) && +- (params_periods(params) <= runtime->hw.channels_max)) +- prtd->channel_mode = params_channels(params); +- +- ret = q6asm_set_softpause(prtd->audio_client, &softpause); +- if (ret < 0) +- pr_err("%s: Send SoftPause Param failed ret=%d\n", +- __func__, ret); +- ret = q6asm_set_softvolume(prtd->audio_client, &softvol); +- if (ret < 0) +- pr_err("%s: Send SoftVolume Param failed ret=%d\n", +- __func__, ret); +- +- ret = q6asm_set_io_mode(prtd->audio_client, +- (COMPRESSED_IO | ASYNC_IO_MODE)); +- if (ret < 0) { +- pr_err("%s: Set IO mode failed\n", __func__); +- return -ENOMEM; +- } +- +- prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream); +- prtd->pcm_count = snd_pcm_lib_period_bytes(substream); +- prtd->pcm_irq_pos = 0; +- /* rate and channels are sent to audio driver */ +- prtd->samp_rate = runtime->rate; +- prtd->channel_mode = runtime->channels; +- prtd->out_head = 0; +- atomic_set(&prtd->out_count, runtime->periods); +- +- if (prtd->enabled) +- return 0; +- +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_MP3: +- /* No media format block for mp3 */ +- break; +- case SND_AUDIOCODEC_AAC: +- pr_debug("%s: SND_AUDIOCODEC_AAC\n", __func__); +- memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg)); +- aac_cfg.aot = AAC_ENC_MODE_EAAC_P; +- aac_cfg.format = 0x03; +- aac_cfg.ch_cfg = runtime->channels; +- aac_cfg.sample_rate = runtime->rate; +- ret = q6asm_media_format_block_aac(prtd->audio_client, +- &aac_cfg); +- if (ret < 0) +- pr_err("%s: CMD Format block failed\n", __func__); +- break; +- case SND_AUDIOCODEC_AC3: { +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- pr_debug("%s: SND_AUDIOCODEC_AC3\n", __func__); +- ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp); +- if (ret < 0) +- pr_err("%s: DDP CMD CFG failed\n", __func__); +- break; +- } +- case SND_AUDIOCODEC_EAC3: { +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- pr_debug("%s: SND_AUDIOCODEC_EAC3\n", __func__); +- ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp); +- if (ret < 0) +- pr_err("%s: DDP CMD CFG failed\n", __func__); +- break; +- } +- default: +- return -EINVAL; +- } +- +- prtd->enabled = 1; +- prtd->cmd_ack = 0; +- prtd->cmd_interrupt = 0; +- +- return 0; +-} +- +-static int msm_compr_capture_prepare(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct audio_buffer *buf = prtd->audio_client->port[OUT].buf; +- struct snd_codec *codec = &compr->info.codec_param.codec; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct audio_aio_read_param read_param; +- uint16_t bits_per_sample = 16; +- int ret = 0; +- int i; +- +- prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream); +- prtd->pcm_count = snd_pcm_lib_period_bytes(substream); +- prtd->pcm_irq_pos = 0; +- +- if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) +- bits_per_sample = 24; +- +- if (!msm_compr_capture_codecs( +- compr->info.codec_param.codec.id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- compr->info.codec_param.codec.id = +- SND_AUDIOCODEC_AMRWB; +- } +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- pr_debug("q6asm_open_read(FORMAT_AMRWB)\n"); +- ret = q6asm_open_read(prtd->audio_client, +- FORMAT_AMRWB); +- if (ret < 0) { +- pr_err("%s: compressed Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- pr_debug("msm_pcm_routing_reg_phy_stream\n"); +- msm_pcm_routing_reg_phy_stream( +- soc_prtd->dai_link->be_id, +- prtd->audio_client->perf_mode, +- prtd->session_id, substream->stream); +- break; +- default: +- pr_debug("q6asm_open_read_compressed(COMPRESSED_META_DATA_MODE)\n"); +- /* +- ret = q6asm_open_read_compressed(prtd->audio_client, +- MAX_NUM_FRAMES_PER_BUFFER, +- COMPRESSED_META_DATA_MODE); +- */ +- ret = -EINVAL; +- break; +- } +- +- if (ret < 0) { +- pr_err("%s: compressed Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- +- ret = q6asm_set_io_mode(prtd->audio_client, +- (COMPRESSED_IO | ASYNC_IO_MODE)); +- if (ret < 0) { +- pr_err("%s: Set IO mode failed\n", __func__); +- return -ENOMEM; +- } +- +- if (!msm_compr_capture_codecs(codec->id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- codec->id = SND_AUDIOCODEC_AMRWB; +- } +- /* rate and channels are sent to audio driver */ +- prtd->samp_rate = runtime->rate; +- prtd->channel_mode = runtime->channels; +- +- if (prtd->enabled) +- return ret; +- read_param.len = prtd->pcm_count; +- +- switch (codec->id) { +- case SND_AUDIOCODEC_AMRWB: +- pr_debug("SND_AUDIOCODEC_AMRWB\n"); +- ret = q6asm_enc_cfg_blk_amrwb(prtd->audio_client, +- MAX_NUM_FRAMES_PER_BUFFER, +- /* +- * use fixed band mode and dtx mode +- * band mode - 23.85 kbps +- */ +- AMR_WB_BAND_MODE, +- /* dtx mode - disable */ +- AMR_WB_DTX_MODE); +- if (ret < 0) +- pr_err("%s: CMD Format block failed: %d\n", +- __func__, ret); +- break; +- default: +- pr_debug("No config for codec %d\n", codec->id); +- } +- pr_debug("%s: Samp_rate = %d, Channel = %d, pcm_size = %d,\n" +- "pcm_count = %d, periods = %d\n", +- __func__, prtd->samp_rate, prtd->channel_mode, +- prtd->pcm_size, prtd->pcm_count, runtime->periods); +- +- for (i = 0; i < runtime->periods; i++) { +- read_param.uid = i; +- switch (codec->id) { +- case SND_AUDIOCODEC_AMRWB: +- read_param.len = prtd->pcm_count +- - COMPRE_CAPTURE_HEADER_SIZE; +- read_param.paddr = buf[i].phys +- + COMPRE_CAPTURE_HEADER_SIZE; +- pr_debug("Push buffer [%d] to DSP, paddr: %pa, vaddr: %pK\n", +- i, &read_param.paddr, +- buf[i].data); +- q6asm_async_read(prtd->audio_client, &read_param); +- break; +- default: +- read_param.paddr = buf[i].phys; +- /*q6asm_async_read_compressed(prtd->audio_client, +- &read_param);*/ +- pr_debug("%s: To add support for read compressed\n", +- __func__); +- ret = -EINVAL; +- break; +- } +- } +- prtd->periods = runtime->periods; +- +- prtd->enabled = 1; +- +- return ret; +-} +- +-static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd) +-{ +- int ret = 0; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- +- pr_debug("%s\n", __func__); +- switch (cmd) { +- case SNDRV_PCM_TRIGGER_START: +- prtd->pcm_irq_pos = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- if (!msm_compr_capture_codecs( +- compr->info.codec_param.codec.id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- compr->info.codec_param.codec.id = +- SND_AUDIOCODEC_AMRWB; +- } +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- break; +- default: +- msm_pcm_routing_reg_psthr_stream( +- soc_prtd->dai_link->be_id, +- prtd->session_id, substream->stream); +- break; +- } +- } +- atomic_set(&prtd->pending_buffer, 1); +- case SNDRV_PCM_TRIGGER_RESUME: +- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +- pr_debug("%s: Trigger start\n", __func__); +- q6asm_run_nowait(prtd->audio_client, 0, 0, 0); +- atomic_set(&prtd->start, 1); +- break; +- case SNDRV_PCM_TRIGGER_STOP: +- pr_debug("SNDRV_PCM_TRIGGER_STOP\n"); +- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- break; +- default: +- msm_pcm_routing_reg_psthr_stream( +- soc_prtd->dai_link->be_id, +- prtd->session_id, substream->stream); +- break; +- } +- } +- atomic_set(&prtd->start, 0); +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- break; +- case SNDRV_PCM_TRIGGER_SUSPEND: +- case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +- pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n"); +- q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); +- atomic_set(&prtd->start, 0); +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- break; +- default: +- ret = -EINVAL; +- break; +- } +- +- return ret; +-} +- +-static void populate_codec_list(struct compr_audio *compr, +- struct snd_pcm_runtime *runtime) +-{ +- pr_debug("%s\n", __func__); +- /* MP3 Block */ +- compr->info.compr_cap.num_codecs = 5; +- compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min; +- compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max; +- compr->info.compr_cap.min_fragments = runtime->hw.periods_min; +- compr->info.compr_cap.max_fragments = runtime->hw.periods_max; +- compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3; +- compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC; +- compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3; +- compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3; +- compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_AMRWB; +- /* Add new codecs here */ +-} +- +-static int msm_compr_open(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr; +- struct msm_audio *prtd; +- int ret = 0; +- +- pr_debug("%s\n", __func__); +- compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL); +- if (compr == NULL) { +- pr_err("Failed to allocate memory for msm_audio\n"); +- return -ENOMEM; +- } +- prtd = &compr->prtd; +- prtd->substream = substream; +- runtime->render_flag = SNDRV_DMA_MODE; +- prtd->audio_client = q6asm_audio_client_alloc( +- (app_cb)compr_event_handler, compr); +- if (!prtd->audio_client) { +- pr_info("%s: Could not allocate memory\n", __func__); +- kfree(prtd); +- return -ENOMEM; +- } +- +- prtd->audio_client->perf_mode = false; +- pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session); +- +- prtd->session_id = prtd->audio_client->session; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- runtime->hw = msm_compr_hardware_playback; +- prtd->cmd_ack = 1; +- } else { +- runtime->hw = msm_compr_hardware_capture; +- } +- +- +- ret = snd_pcm_hw_constraint_list(runtime, 0, +- SNDRV_PCM_HW_PARAM_RATE, +- &constraints_sample_rates); +- if (ret < 0) +- pr_info("snd_pcm_hw_constraint_list failed\n"); +- /* Ensure that buffer size is a multiple of period size */ +- ret = snd_pcm_hw_constraint_integer(runtime, +- SNDRV_PCM_HW_PARAM_PERIODS); +- if (ret < 0) +- pr_info("snd_pcm_hw_constraint_integer failed\n"); +- +- prtd->dsp_cnt = 0; +- atomic_set(&prtd->pending_buffer, 1); +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- compr->codec = FORMAT_MP3; +- populate_codec_list(compr, runtime); +- runtime->private_data = compr; +- atomic_set(&prtd->eos, 0); +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- if (!atomic_cmpxchg(&compressed_audio.audio_ocmem_req, 0, 1)) +- audio_ocmem_process_req(AUDIO, true); +- else +- atomic_inc(&compressed_audio.audio_ocmem_req); +- pr_debug("%s: req: %d\n", __func__, +- atomic_read(&compressed_audio.audio_ocmem_req)); +- } +- return 0; +-} +- +-static int compressed_set_volume(struct msm_audio *prtd, uint32_t volume) +-{ +- int rc = 0; +- int avg_vol = 0; +- int lgain = (volume >> 16) & 0xFFFF; +- int rgain = volume & 0xFFFF; +- if (prtd && prtd->audio_client) { +- pr_debug("%s: channels %d volume 0x%x\n", __func__, +- prtd->channel_mode, volume); +- if ((prtd->channel_mode == 2) && +- (lgain != rgain)) { +- pr_debug("%s: call q6asm_set_lrgain\n", __func__); +- rc = q6asm_set_lrgain(prtd->audio_client, lgain, rgain); +- } else { +- avg_vol = (lgain + rgain)/2; +- pr_debug("%s: call q6asm_set_volume\n", __func__); +- rc = q6asm_set_volume(prtd->audio_client, avg_vol); +- } +- if (rc < 0) { +- pr_err("%s: Send Volume command failed rc=%d\n", +- __func__, rc); +- } +- } +- return rc; +-} +- +-static int msm_compr_playback_close(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- int dir = 0; +- +- pr_debug("%s\n", __func__); +- +- dir = IN; +- atomic_set(&prtd->pending_buffer, 0); +- +- if (atomic_read(&compressed_audio.audio_ocmem_req) > 1) +- atomic_dec(&compressed_audio.audio_ocmem_req); +- else if (atomic_cmpxchg(&compressed_audio.audio_ocmem_req, 1, 0)) +- audio_ocmem_process_req(AUDIO, false); +- +- pr_debug("%s: req: %d\n", __func__, +- atomic_read(&compressed_audio.audio_ocmem_req)); +- prtd->pcm_irq_pos = 0; +- q6asm_cmd(prtd->audio_client, CMD_CLOSE); +- q6asm_audio_client_buf_free_contiguous(dir, +- prtd->audio_client); +- msm_pcm_routing_dereg_phy_stream( +- soc_prtd->dai_link->be_id, +- SNDRV_PCM_STREAM_PLAYBACK); +- q6asm_audio_client_free(prtd->audio_client); +- kfree(prtd); +- return 0; +-} +- +-static int msm_compr_capture_close(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- int dir = OUT; +- +- pr_debug("%s\n", __func__); +- atomic_set(&prtd->pending_buffer, 0); +- q6asm_cmd(prtd->audio_client, CMD_CLOSE); +- q6asm_audio_client_buf_free_contiguous(dir, +- prtd->audio_client); +- msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, +- SNDRV_PCM_STREAM_CAPTURE); +- q6asm_audio_client_free(prtd->audio_client); +- kfree(prtd); +- return 0; +-} +- +-static int msm_compr_close(struct snd_pcm_substream *substream) +-{ +- int ret = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- ret = msm_compr_playback_close(substream); +- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) +- ret = msm_compr_capture_close(substream); +- return ret; +-} +- +-static int msm_compr_prepare(struct snd_pcm_substream *substream) +-{ +- int ret = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- ret = msm_compr_playback_prepare(substream); +- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) +- ret = msm_compr_capture_prepare(substream); +- return ret; +-} +- +-static snd_pcm_uframes_t msm_compr_pointer(struct snd_pcm_substream *substream) +-{ +- +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- +- if (prtd->pcm_irq_pos >= prtd->pcm_size) +- prtd->pcm_irq_pos = 0; +- +- pr_debug("%s: pcm_irq_pos = %d, pcm_size = %d, sample_bits = %d,\n" +- "frame_bits = %d\n", __func__, prtd->pcm_irq_pos, +- prtd->pcm_size, runtime->sample_bits, +- runtime->frame_bits); +- return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); +-} +- +-static int msm_compr_mmap(struct snd_pcm_substream *substream, +- struct vm_area_struct *vma) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct msm_audio *prtd = runtime->private_data; +- struct audio_client *ac = prtd->audio_client; +- struct audio_port_data *apd = ac->port; +- struct audio_buffer *ab; +- int dir = -1; +- +- prtd->mmap_flag = 1; +- runtime->render_flag = SNDRV_NON_DMA_MODE; +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- dir = IN; +- else +- dir = OUT; +- ab = &(apd[dir].buf[0]); +- +- return msm_audio_ion_mmap(ab, vma); +-} +- +-static int msm_compr_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_dma_buffer *dma_buf = &substream->dma_buffer; +- struct audio_buffer *buf; +- int dir, ret; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- dir = IN; +- else +- dir = OUT; +- /* Modifying kernel hardware params based on userspace config */ +- if (params_periods(params) > 0 && +- (params_periods(params) != runtime->hw.periods_max)) { +- runtime->hw.periods_max = params_periods(params); +- } +- if (params_period_bytes(params) > 0 && +- (params_period_bytes(params) != runtime->hw.period_bytes_min)) { +- runtime->hw.period_bytes_min = params_period_bytes(params); +- } +- runtime->hw.buffer_bytes_max = +- runtime->hw.period_bytes_min * runtime->hw.periods_max; +- pr_debug("allocate %zd buffers each of size %d\n", +- runtime->hw.period_bytes_min, +- runtime->hw.periods_max); +- ret = q6asm_audio_client_buf_alloc_contiguous(dir, +- prtd->audio_client, +- runtime->hw.period_bytes_min, +- runtime->hw.periods_max); +- if (ret < 0) { +- pr_err("Audio Start: Buffer Allocation failed rc = %d\n", +- ret); +- return -ENOMEM; +- } +- buf = prtd->audio_client->port[dir].buf; +- +- dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; +- dma_buf->dev.dev = substream->pcm->card->dev; +- dma_buf->private_data = NULL; +- dma_buf->area = buf[0].data; +- dma_buf->addr = buf[0].phys; +- dma_buf->bytes = runtime->hw.buffer_bytes_max; +- +- pr_debug("%s: buf[%pK]dma_buf->area[%pK]dma_buf->addr[%pa]\n" +- "dma_buf->bytes[%zd]\n", __func__, +- (void *)buf, (void *)dma_buf->area, +- &dma_buf->addr, dma_buf->bytes); +- if (!dma_buf->area) +- return -ENOMEM; +- +- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); +- return 0; +-} +- +-static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int rc = 0; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- uint64_t timestamp; +- uint64_t temp; +- +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP: { +- struct snd_compr_tstamp *tstamp; +- pr_debug("SNDRV_COMPRESS_TSTAMP\n"); +- tstamp = arg; +- memset(tstamp, 0x0, sizeof(*tstamp)); +- rc = q6asm_get_session_time(prtd->audio_client, ×tamp); +- if (rc < 0) { +- pr_err("%s: Get Session Time return value =%lld\n", +- __func__, timestamp); +- return -EAGAIN; +- } +- temp = (timestamp * 2 * runtime->channels); +- temp = temp * (runtime->rate/1000); +- temp = div_u64(temp, 1000); +- tstamp->sampling_rate = runtime->rate; +- tstamp->timestamp = timestamp; +- pr_debug("%s: bytes_consumed:,timestamp = %lld,\n", +- __func__, +- tstamp->timestamp); +- return 0; +- } +- case SNDRV_COMPRESS_GET_CAPS: { +- struct snd_compr_caps *caps; +- caps = arg; +- memset(caps, 0, sizeof(*caps)); +- pr_debug("SNDRV_COMPRESS_GET_CAPS\n"); +- memcpy(caps, &compr->info.compr_cap, sizeof(*caps)); +- return 0; +- } +- case SNDRV_COMPRESS_SET_PARAMS: +- pr_debug("SNDRV_COMPRESS_SET_PARAMS:\n"); +- memcpy(&compr->info.codec_param, (void *) arg, +- sizeof(struct snd_compr_params)); +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_MP3: +- /* For MP3 we dont need any other parameter */ +- pr_debug("SND_AUDIOCODEC_MP3\n"); +- compr->codec = FORMAT_MP3; +- break; +- case SND_AUDIOCODEC_AAC: +- pr_debug("SND_AUDIOCODEC_AAC\n"); +- compr->codec = FORMAT_MPEG4_AAC; +- break; +- case SND_AUDIOCODEC_AC3: { +- char params_value[MAX_AC3_PARAM_SIZE]; +- int *params_value_data = (int *)params_value; +- /* 36 is the max param length for ddp */ +- int i; +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- uint32_t params_length = 0; +- memset(params_value, 0, MAX_AC3_PARAM_SIZE); +- /* check integer overflow */ +- if (ddp->params_length > UINT_MAX/sizeof(int)) { +- pr_err("%s: Integer overflow ddp->params_length %d\n", +- __func__, ddp->params_length); +- return -EINVAL; +- } +- params_length = ddp->params_length*sizeof(int); +- if (params_length > MAX_AC3_PARAM_SIZE) { +- /*MAX is 36*sizeof(int) this should not happen*/ +- pr_err("%s: params_length(%d) is greater than %zd\n", +- __func__, params_length, MAX_AC3_PARAM_SIZE); +- return -EINVAL; +- } +- pr_debug("SND_AUDIOCODEC_AC3\n"); +- compr->codec = FORMAT_AC3; +- pr_debug("params_length: %d\n", ddp->params_length); +- for (i = 0; i < params_length/sizeof(int); i++) +- pr_debug("params_value[%d]: %x\n", i, +- params_value_data[i]); +- for (i = 0; i < ddp->params_length/2; i++) { +- ddp->params_id[i] = params_value_data[2*i]; +- ddp->params_value[i] = params_value_data[2*i+1]; +- } +- if (atomic_read(&prtd->start)) { +- rc = msm_compr_send_ddp_cfg(prtd->audio_client, +- ddp); +- if (rc < 0) +- pr_err("%s: DDP CMD CFG failed\n", +- __func__); +- } +- break; +- } +- case SND_AUDIOCODEC_EAC3: { +- char params_value[MAX_AC3_PARAM_SIZE]; +- int *params_value_data = (int *)params_value; +- /* 36 is the max param length for ddp */ +- int i; +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- uint32_t params_length = 0; +- memset(params_value, 0, MAX_AC3_PARAM_SIZE); +- /* check integer overflow */ +- if (ddp->params_length > UINT_MAX/sizeof(int)) { +- pr_err("%s: Integer overflow ddp->params_length %d\n", +- __func__, ddp->params_length); +- return -EINVAL; +- } +- params_length = ddp->params_length*sizeof(int); +- if (params_length > MAX_AC3_PARAM_SIZE) { +- /*MAX is 36*sizeof(int) this should not happen*/ +- pr_err("%s: params_length(%d) is greater than %zd\n", +- __func__, params_length, MAX_AC3_PARAM_SIZE); +- return -EINVAL; +- } +- pr_debug("SND_AUDIOCODEC_EAC3\n"); +- compr->codec = FORMAT_EAC3; +- pr_debug("params_length: %d\n", ddp->params_length); +- for (i = 0; i < ddp->params_length; i++) +- pr_debug("params_value[%d]: %x\n", i, +- params_value_data[i]); +- for (i = 0; i < ddp->params_length/2; i++) { +- ddp->params_id[i] = params_value_data[2*i]; +- ddp->params_value[i] = params_value_data[2*i+1]; +- } +- if (atomic_read(&prtd->start)) { +- rc = msm_compr_send_ddp_cfg(prtd->audio_client, +- ddp); +- if (rc < 0) +- pr_err("%s: DDP CMD CFG failed\n", +- __func__); +- } +- break; +- } +- default: +- pr_debug("FORMAT_LINEAR_PCM\n"); +- compr->codec = FORMAT_LINEAR_PCM; +- break; +- } +- return 0; +- case SNDRV_PCM_IOCTL1_RESET: +- pr_debug("SNDRV_PCM_IOCTL1_RESET\n"); +- /* Flush only when session is started during CAPTURE, +- while PLAYBACK has no such restriction. */ +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || +- (substream->stream == SNDRV_PCM_STREAM_CAPTURE && +- atomic_read(&prtd->start))) { +- if (atomic_read(&prtd->eos)) { +- prtd->cmd_interrupt = 1; +- wake_up(&the_locks.eos_wait); +- atomic_set(&prtd->eos, 0); +- } +- +- /* A unlikely race condition possible with FLUSH +- DRAIN if ack is set by flush and reset by drain */ +- prtd->cmd_ack = 0; +- rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH); +- if (rc < 0) { +- pr_err("%s: flush cmd failed rc=%d\n", +- __func__, rc); +- return rc; +- } +- rc = wait_event_timeout(the_locks.flush_wait, +- prtd->cmd_ack, 5 * HZ); +- if (!rc) +- pr_err("Flush cmd timeout\n"); +- prtd->pcm_irq_pos = 0; +- } +- break; +- case SNDRV_COMPRESS_DRAIN: +- pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__); +- if (atomic_read(&prtd->pending_buffer)) { +- pr_debug("%s: no pending writes, drain would block\n", +- __func__); +- return -EWOULDBLOCK; +- } +- +- atomic_set(&prtd->eos, 1); +- atomic_set(&prtd->pending_buffer, 0); +- prtd->cmd_ack = 0; +- q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); +- /* Wait indefinitely for DRAIN. Flush can also signal this*/ +- rc = wait_event_interruptible(the_locks.eos_wait, +- (prtd->cmd_ack || prtd->cmd_interrupt)); +- +- if (rc < 0) +- pr_err("EOS cmd interrupted\n"); +- pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait\n", __func__); +- +- if (prtd->cmd_interrupt) +- rc = -EINTR; +- +- prtd->cmd_interrupt = 0; +- return rc; +- default: +- break; +- } +- return snd_pcm_lib_ioctl(substream, cmd, arg); +-} +-#ifdef CONFIG_COMPAT +-struct snd_enc_wma32 { +- u32 super_block_align; /* WMA Type-specific data */ +- u32 encodeopt1; +- u32 encodeopt2; +-}; +- +-struct snd_enc_vorbis32 { +- s32 quality; +- u32 managed; +- u32 max_bit_rate; +- u32 min_bit_rate; +- u32 downmix; +-}; +- +-struct snd_enc_real32 { +- u32 quant_bits; +- u32 start_region; +- u32 num_regions; +-}; +- +-struct snd_enc_flac32 { +- u32 num; +- u32 gain; +-}; +- +-struct snd_enc_generic32 { +- u32 bw; /* encoder bandwidth */ +- s32 reserved[15]; +-}; +-struct snd_dec_ddp32 { +- u32 params_length; +- u32 params_id[18]; +- u32 params_value[18]; +-}; +- +-union snd_codec_options32 { +- struct snd_enc_wma32 wma; +- struct snd_enc_vorbis32 vorbis; +- struct snd_enc_real32 real; +- struct snd_enc_flac32 flac; +- struct snd_enc_generic32 generic; +- struct snd_dec_ddp32 ddp; +-}; +- +-struct snd_codec32 { +- u32 id; +- u32 ch_in; +- u32 ch_out; +- u32 sample_rate; +- u32 bit_rate; +- u32 rate_control; +- u32 profile; +- u32 level; +- u32 ch_mode; +- u32 format; +- u32 align; +- union snd_codec_options32 options; +- u32 reserved[3]; +-}; +- +-struct snd_compressed_buffer32 { +- u32 fragment_size; +- u32 fragments; +-}; +- +-struct snd_compr_params32 { +- struct snd_compressed_buffer32 buffer; +- struct snd_codec32 codec; +- u8 no_wake_mode; +-}; +- +-struct snd_compr_caps32 { +- u32 num_codecs; +- u32 direction; +- u32 min_fragment_size; +- u32 max_fragment_size; +- u32 min_fragments; +- u32 max_fragments; +- u32 codecs[MAX_NUM_CODECS]; +- u32 reserved[11]; +-}; +-struct snd_compr_tstamp32 { +- u32 byte_offset; +- u32 copied_total; +- compat_ulong_t pcm_frames; +- compat_ulong_t pcm_io_frames; +- u32 sampling_rate; +- compat_u64 timestamp; +-}; +-enum { +- SNDRV_COMPRESS_TSTAMP32 = _IOR('C', 0x20, struct snd_compr_tstamp32), +- SNDRV_COMPRESS_GET_CAPS32 = _IOWR('C', 0x10, struct snd_compr_caps32), +- SNDRV_COMPRESS_SET_PARAMS32 = +- _IOW('C', 0x12, struct snd_compr_params32), +-}; +-static int msm_compr_compat_ioctl(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int err = 0; +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP32: { +- struct snd_compr_tstamp tstamp; +- struct snd_compr_tstamp32 tstamp32; +- memset(&tstamp, 0, sizeof(tstamp)); +- memset(&tstamp32, 0, sizeof(tstamp32)); +- cmd = SNDRV_COMPRESS_TSTAMP; +- err = msm_compr_ioctl_shared(substream, cmd, &tstamp); +- if (err) { +- pr_err("%s: COMPRESS_TSTAMP failed rc %d\n", +- __func__, err); +- goto bail_out; +- } +- tstamp32.byte_offset = tstamp.byte_offset; +- tstamp32.copied_total = tstamp.copied_total; +- tstamp32.pcm_frames = tstamp.pcm_frames; +- tstamp32.pcm_io_frames = tstamp.pcm_io_frames; +- tstamp32.sampling_rate = tstamp.sampling_rate; +- tstamp32.timestamp = tstamp.timestamp; +- if (copy_to_user(arg, &tstamp32, sizeof(tstamp32))) { +- pr_err("%s: copytouser failed COMPRESS_TSTAMP32\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_GET_CAPS32: { +- struct snd_compr_caps caps; +- struct snd_compr_caps32 caps32; +- u32 i; +- memset(&caps, 0, sizeof(caps)); +- memset(&caps32, 0, sizeof(caps32)); +- cmd = SNDRV_COMPRESS_GET_CAPS; +- err = msm_compr_ioctl_shared(substream, cmd, &caps); +- if (err) { +- pr_err("%s: GET_CAPS failed rc %d\n", +- __func__, err); +- goto bail_out; +- } +- pr_debug("SNDRV_COMPRESS_GET_CAPS_32\n"); +- if (!err && caps.num_codecs >= MAX_NUM_CODECS) { +- pr_err("%s: Invalid number of codecs\n", __func__); +- err = -EINVAL; +- goto bail_out; +- } +- caps32.direction = caps.direction; +- caps32.max_fragment_size = caps.max_fragment_size; +- caps32.max_fragments = caps.max_fragments; +- caps32.min_fragment_size = caps.min_fragment_size; +- caps32.num_codecs = caps.num_codecs; +- for (i = 0; i < caps.num_codecs; i++) +- caps32.codecs[i] = caps.codecs[i]; +- if (copy_to_user(arg, &caps32, sizeof(caps32))) { +- pr_err("%s: copytouser failed COMPRESS_GETCAPS32\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_SET_PARAMS32: { +- struct snd_compr_params32 params32; +- struct snd_compr_params params; +- memset(¶ms32, 0 , sizeof(params32)); +- memset(¶ms, 0 , sizeof(params)); +- cmd = SNDRV_COMPRESS_SET_PARAMS; +- if (copy_from_user(¶ms32, arg, sizeof(params32))) { +- pr_err("%s: copyfromuser failed SET_PARAMS32\n", +- __func__); +- err = -EFAULT; +- goto bail_out; +- } +- params.no_wake_mode = params32.no_wake_mode; +- params.codec.id = params32.codec.id; +- params.codec.ch_in = params32.codec.ch_in; +- params.codec.ch_out = params32.codec.ch_out; +- params.codec.sample_rate = params32.codec.sample_rate; +- params.codec.bit_rate = params32.codec.bit_rate; +- params.codec.rate_control = params32.codec.rate_control; +- params.codec.profile = params32.codec.profile; +- params.codec.level = params32.codec.level; +- params.codec.ch_mode = params32.codec.ch_mode; +- params.codec.format = params32.codec.format; +- params.codec.align = params32.codec.align; +- +- switch (params.codec.id) { +- case SND_AUDIOCODEC_WMA: +- case SND_AUDIOCODEC_WMA_PRO: +- params.codec.options.wma.encodeopt1 = +- params32.codec.options.wma.encodeopt1; +- params.codec.options.wma.encodeopt2 = +- params32.codec.options.wma.encodeopt2; +- params.codec.options.wma.super_block_align = +- params32.codec.options.wma.super_block_align; +- break; +- case SND_AUDIOCODEC_VORBIS: +- params.codec.options.vorbis.downmix = +- params32.codec.options.vorbis.downmix; +- params.codec.options.vorbis.managed = +- params32.codec.options.vorbis.managed; +- params.codec.options.vorbis.max_bit_rate = +- params32.codec.options.vorbis.max_bit_rate; +- params.codec.options.vorbis.min_bit_rate = +- params32.codec.options.vorbis.min_bit_rate; +- params.codec.options.vorbis.quality = +- params32.codec.options.vorbis.quality; +- break; +- case SND_AUDIOCODEC_REAL: +- params.codec.options.real.num_regions = +- params32.codec.options.real.num_regions; +- params.codec.options.real.quant_bits = +- params32.codec.options.real.quant_bits; +- params.codec.options.real.start_region = +- params32.codec.options.real.start_region; +- break; +- case SND_AUDIOCODEC_FLAC: +- params.codec.options.flac.gain = +- params32.codec.options.flac.gain; +- params.codec.options.flac.num = +- params32.codec.options.flac.num; +- break; +- case SND_AUDIOCODEC_DTS: +- case SND_AUDIOCODEC_DTS_PASS_THROUGH: +- case SND_AUDIOCODEC_DTS_LBR: +- case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH: +- case SND_AUDIOCODEC_DTS_TRANSCODE_LOOPBACK: +- break; +- case SND_AUDIOCODEC_AC3: +- case SND_AUDIOCODEC_EAC3: +- params.codec.options.ddp.params_length = +- params32.codec.options.ddp.params_length; +- memcpy(params.codec.options.ddp.params_value, +- params32.codec.options.ddp.params_value, +- sizeof(params32.codec.options.ddp.params_value)); +- memcpy(params.codec.options.ddp.params_id, +- params32.codec.options.ddp.params_id, +- sizeof(params32.codec.options.ddp.params_id)); +- break; +- default: +- params.codec.options.generic.bw = +- params32.codec.options.generic.bw; +- break; +- } +- if (!err) +- err = msm_compr_ioctl_shared(substream, cmd, ¶ms); +- break; +- } +- default: +- err = msm_compr_ioctl_shared(substream, cmd, arg); +- } +-bail_out: +- return err; +- +-} +-#endif +-static int msm_compr_ioctl(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int err = 0; +- if (!substream) { +- pr_err("%s: Invalid params\n", __func__); +- return -EINVAL; +- } +- pr_debug("%s called with cmd = %d\n", __func__, cmd); +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP: { +- struct snd_compr_tstamp tstamp; +- if (!arg) { +- pr_err("%s: Invalid params Tstamp\n", __func__); +- return -EINVAL; +- } +- err = msm_compr_ioctl_shared(substream, cmd, &tstamp); +- if (err) +- pr_err("%s: COMPRESS_TSTAMP failed rc %d\n", +- __func__, err); +- if (!err && copy_to_user(arg, &tstamp, sizeof(tstamp))) { +- pr_err("%s: copytouser failed COMPRESS_TSTAMP\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_GET_CAPS: { +- struct snd_compr_caps cap; +- if (!arg) { +- pr_err("%s: Invalid params getcaps\n", __func__); +- return -EINVAL; +- } +- pr_debug("SNDRV_COMPRESS_GET_CAPS\n"); +- err = msm_compr_ioctl_shared(substream, cmd, &cap); +- if (err) +- pr_err("%s: GET_CAPS failed rc %d\n", +- __func__, err); +- if (!err && copy_to_user(arg, &cap, sizeof(cap))) { +- pr_err("%s: copytouser failed GET_CAPS\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_SET_PARAMS: { +- struct snd_compr_params params; +- if (!arg) { +- pr_err("%s: Invalid params setparam\n", __func__); +- return -EINVAL; +- } +- if (copy_from_user(¶ms, arg, +- sizeof(struct snd_compr_params))) { +- pr_err("%s: SET_PARAMS\n", __func__); +- return -EFAULT; +- } +- err = msm_compr_ioctl_shared(substream, cmd, ¶ms); +- if (err) +- pr_err("%s: SET_PARAMS failed rc %d\n", +- __func__, err); +- break; +- } +- default: +- err = msm_compr_ioctl_shared(substream, cmd, arg); +- } +- return err; +-} +- +-static int msm_compr_restart(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct audio_aio_write_param param; +- struct audio_buffer *buf = NULL; +- struct output_meta_data_st output_meta_data; +- int time_stamp_flag = 0; +- int buffer_length = 0; +- +- pr_debug("%s, trigger restart\n", __func__); +- +- if (runtime->render_flag & SNDRV_RENDER_STOPPED) { +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", +- __func__, prtd->pcm_count, prtd->out_head); +- pr_debug("%s:writing buffer[%d] from 0x%08x\n", +- __func__, prtd->out_head, +- ((unsigned int)buf[0].phys +- + (prtd->out_head * prtd->pcm_count))); +- +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- +- param.paddr = (unsigned long)buf[0].phys +- + (prtd->out_head * prtd->pcm_count) +- + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) & (runtime->periods - 1); +- +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- return 0; +- } +- return 0; +-} +- +-static int msm_compr_volume_ctl_put(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- int rc = 0; +- struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); +- struct snd_pcm_substream *substream = +- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; +- struct msm_audio *prtd; +- int volume = ucontrol->value.integer.value[0]; +- +- pr_debug("%s: volume : %x\n", __func__, volume); +- if (!substream) +- return -ENODEV; +- if (!substream->runtime) +- return 0; +- prtd = substream->runtime->private_data; +- if (prtd) +- rc = compressed_set_volume(prtd, volume); +- +- return rc; +-} +- +-static int msm_compr_volume_ctl_get(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); +- struct snd_pcm_substream *substream = +- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; +- struct msm_audio *prtd; +- +- pr_debug("%s\n", __func__); +- if (!substream) +- return -ENODEV; +- if (!substream->runtime) +- return 0; +- prtd = substream->runtime->private_data; +- if (prtd) +- ucontrol->value.integer.value[0] = prtd->volume; +- return 0; +-} +- +-static int msm_compr_add_controls(struct snd_soc_pcm_runtime *rtd) +-{ +- int ret = 0; +- struct snd_pcm *pcm = rtd->pcm; +- struct snd_pcm_volume *volume_info; +- struct snd_kcontrol *kctl; +- +- dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__); +- ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, +- NULL, 1, rtd->dai_link->be_id, +- &volume_info); +- if (ret < 0) +- return ret; +- kctl = volume_info->kctl; +- kctl->put = msm_compr_volume_ctl_put; +- kctl->get = msm_compr_volume_ctl_get; +- kctl->tlv.p = compr_rx_vol_gain; +- return 0; +-} +- +-static struct snd_pcm_ops msm_compr_ops = { +- .open = msm_compr_open, +- .hw_params = msm_compr_hw_params, +- .close = msm_compr_close, +- .ioctl = msm_compr_ioctl, +- .prepare = msm_compr_prepare, +- .trigger = msm_compr_trigger, +- .pointer = msm_compr_pointer, +- .mmap = msm_compr_mmap, +- .restart = msm_compr_restart, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = msm_compr_compat_ioctl, +-#endif +-}; +- +-static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) +-{ +- struct snd_card *card = rtd->card->snd_card; +- int ret = 0; +- +- if (!card->dev->coherent_dma_mask) +- card->dev->coherent_dma_mask = DMA_BIT_MASK(32); +- +- ret = msm_compr_add_controls(rtd); +- if (ret) +- pr_err("%s, kctl add failed\n", __func__); +- return ret; +-} +- +-static struct snd_soc_platform_driver msm_soc_platform = { +- .ops = &msm_compr_ops, +- .pcm_new = msm_asoc_pcm_new, +-}; +- +-static int msm_compr_probe(struct platform_device *pdev) +-{ +- +- dev_info(&pdev->dev, "%s: dev name %s\n", +- __func__, dev_name(&pdev->dev)); +- +- atomic_set(&compressed_audio.audio_ocmem_req, 0); +- return snd_soc_register_platform(&pdev->dev, +- &msm_soc_platform); +-} +- +-static int msm_compr_remove(struct platform_device *pdev) +-{ +- snd_soc_unregister_platform(&pdev->dev); +- return 0; +-} +- +-static const struct of_device_id msm_compr_dt_match[] = { +- {.compatible = "qcom,msm-compr-dsp"}, +- {} +-}; +-MODULE_DEVICE_TABLE(of, msm_compr_dt_match); +- +-static struct platform_driver msm_compr_driver = { +- .driver = { +- .name = "msm-compr-dsp", +- .owner = THIS_MODULE, +- .of_match_table = msm_compr_dt_match, +- }, +- .probe = msm_compr_probe, +- .remove = msm_compr_remove, +-}; +- +-static int __init msm_soc_platform_init(void) +-{ +- init_waitqueue_head(&the_locks.enable_wait); +- init_waitqueue_head(&the_locks.eos_wait); +- init_waitqueue_head(&the_locks.write_wait); +- init_waitqueue_head(&the_locks.read_wait); +- init_waitqueue_head(&the_locks.flush_wait); +- +- return platform_driver_register(&msm_compr_driver); +-} +-module_init(msm_soc_platform_init); +- +-static void __exit msm_soc_platform_exit(void) +-{ +- platform_driver_unregister(&msm_compr_driver); +-} +-module_exit(msm_soc_platform_exit); +- +-MODULE_DESCRIPTION("PCM module platform driver"); +-MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h +deleted file mode 100644 +index d6e3ec6..0000000 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h ++++ /dev/null +@@ -1,36 +0,0 @@ +-/* +- * Copyright (c) 2012, The 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 +- * only version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _MSM_COMPR_H +-#define _MSM_COMPR_H +-#include +-#include +-#include +-#include +-#include +- +-#include "msm-pcm-q6-v2.h" +- +-struct compr_info { +- struct snd_compr_caps compr_cap; +- struct snd_compr_codec_caps codec_caps; +- struct snd_compr_params codec_param; +-}; +- +-struct compr_audio { +- struct msm_audio prtd; +- struct compr_info info; +- uint32_t codec; +-}; +- +-#endif /*_MSM_COMPR_H*/ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9677/1.patch b/Patches/Linux_CVEs/CVE-2017-9677/1.patch new file mode 100644 index 00000000..33e0cd6b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9677/1.patch @@ -0,0 +1,1774 @@ +From dc333eb1c31b5bdd2b6375d7cb890086d8f27d8b Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Thu, 27 Apr 2017 14:44:25 +0800 +Subject: ASoC: msm: remove unused msm-compr-q6-v2 + +msm-compr-q6-v2.c and msm-compr-q6-v2.h are no longer used. + +CRs-Fixed: 2022953 +Change-Id: I856d90a212a3e123a2c8b80092aff003f7c608c7 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/qdsp6v2/Makefile | 2 +- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c | 1694 ------------------------------- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h | 36 - + 3 files changed, 1 insertion(+), 1731 deletions(-) + delete mode 100644 sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c + delete mode 100644 sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h + +diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile +index 8e1aa30..7abaaad 100644 +--- a/sound/soc/msm/qdsp6v2/Makefile ++++ b/sound/soc/msm/qdsp6v2/Makefile +@@ -1,5 +1,5 @@ + snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \ +- msm-compress-q6-v2.o msm-compr-q6-v2.o \ ++ msm-compress-q6-v2.o \ + msm-pcm-lpa-v2.o \ + msm-pcm-afe-v2.o msm-pcm-voip-v2.o \ + msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o \ +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +deleted file mode 100644 +index 58a4de5..0000000 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c ++++ /dev/null +@@ -1,1694 +0,0 @@ +-/* Copyright (c) 2012-2016, The 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 +- * only version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include "msm-compr-q6-v2.h" +-#include "msm-pcm-routing-v2.h" +-#include +- +-#define COMPRE_CAPTURE_NUM_PERIODS 16 +-/* Allocate the worst case frame size for compressed audio */ +-#define COMPRE_CAPTURE_HEADER_SIZE (sizeof(struct snd_compr_audio_info)) +-/* Changing period size to 4032. 4032 will make sure COMPRE_CAPTURE_PERIOD_SIZE +- * is 4096 with meta data size of 64 and MAX_NUM_FRAMES_PER_BUFFER 1 +- */ +-#define COMPRE_CAPTURE_MAX_FRAME_SIZE (4032) +-#define COMPRE_CAPTURE_PERIOD_SIZE ((COMPRE_CAPTURE_MAX_FRAME_SIZE + \ +- COMPRE_CAPTURE_HEADER_SIZE) * \ +- MAX_NUM_FRAMES_PER_BUFFER) +-#define COMPRE_OUTPUT_METADATA_SIZE (sizeof(struct output_meta_data_st)) +-#define COMPRESSED_LR_VOL_MAX_STEPS 0x20002000 +- +-#define MAX_AC3_PARAM_SIZE (18*2*sizeof(int)) +-#define AMR_WB_BAND_MODE 8 +-#define AMR_WB_DTX_MODE 0 +- +- +-const DECLARE_TLV_DB_LINEAR(compr_rx_vol_gain, 0, +- COMPRESSED_LR_VOL_MAX_STEPS); +- +-static struct audio_locks the_locks; +- +-static struct snd_pcm_hardware msm_compr_hardware_capture = { +- .info = (SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_BLOCK_TRANSFER | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_INTERLEAVED | +- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), +- .formats = SNDRV_PCM_FMTBIT_S16_LE, +- .rates = SNDRV_PCM_RATE_8000_48000, +- .rate_min = 8000, +- .rate_max = 48000, +- .channels_min = 1, +- .channels_max = 8, +- .buffer_bytes_max = +- COMPRE_CAPTURE_PERIOD_SIZE * COMPRE_CAPTURE_NUM_PERIODS , +- .period_bytes_min = COMPRE_CAPTURE_PERIOD_SIZE, +- .period_bytes_max = COMPRE_CAPTURE_PERIOD_SIZE, +- .periods_min = COMPRE_CAPTURE_NUM_PERIODS, +- .periods_max = COMPRE_CAPTURE_NUM_PERIODS, +- .fifo_size = 0, +-}; +- +-static struct snd_pcm_hardware msm_compr_hardware_playback = { +- .info = (SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_BLOCK_TRANSFER | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_INTERLEAVED | +- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), +- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, +- .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT, +- .rate_min = 8000, +- .rate_max = 48000, +- .channels_min = 1, +- .channels_max = 8, +- .buffer_bytes_max = 1024 * 1024, +- .period_bytes_min = 128 * 1024, +- .period_bytes_max = 256 * 1024, +- .periods_min = 4, +- .periods_max = 8, +- .fifo_size = 0, +-}; +- +-/* Conventional and unconventional sample rate supported */ +-static unsigned int supported_sample_rates[] = { +- 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 +-}; +- +-/* Add supported codecs for compress capture path */ +-static uint32_t supported_compr_capture_codecs[] = { +- SND_AUDIOCODEC_AMRWB +-}; +- +-static struct snd_pcm_hw_constraint_list constraints_sample_rates = { +- .count = ARRAY_SIZE(supported_sample_rates), +- .list = supported_sample_rates, +- .mask = 0, +-}; +- +-static bool msm_compr_capture_codecs(uint32_t req_codec) +-{ +- int i; +- pr_debug("%s req_codec:%d\n", __func__, req_codec); +- if (req_codec == 0) +- return false; +- for (i = 0; i < ARRAY_SIZE(supported_compr_capture_codecs); i++) { +- if (req_codec == supported_compr_capture_codecs[i]) +- return true; +- } +- return false; +-} +- +-static void compr_event_handler(uint32_t opcode, +- uint32_t token, uint32_t *payload, void *priv) +-{ +- struct compr_audio *compr = priv; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_pcm_substream *substream = prtd->substream; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct audio_aio_write_param param; +- struct audio_aio_read_param read_param; +- struct audio_buffer *buf = NULL; +- phys_addr_t temp; +- struct output_meta_data_st output_meta_data; +- uint32_t *ptrmem = (uint32_t *)payload; +- int i = 0; +- int time_stamp_flag = 0; +- int buffer_length = 0; +- int stop_playback = 0; +- +- pr_debug("%s opcode =%08x\n", __func__, opcode); +- switch (opcode) { +- case ASM_DATA_EVENT_WRITE_DONE_V2: { +- uint32_t *ptrmem = (uint32_t *)¶m; +- pr_debug("ASM_DATA_EVENT_WRITE_DONE\n"); +- pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem); +- prtd->pcm_irq_pos += prtd->pcm_count; +- if (atomic_read(&prtd->start)) +- snd_pcm_period_elapsed(substream); +- else +- if (substream->timer_running) +- snd_timer_interrupt(substream->timer, 1); +- atomic_inc(&prtd->out_count); +- wake_up(&the_locks.write_wait); +- if (!atomic_read(&prtd->start)) { +- atomic_set(&prtd->pending_buffer, 1); +- break; +- } else +- atomic_set(&prtd->pending_buffer, 0); +- +- /* +- * check for underrun +- */ +- snd_pcm_stream_lock_irq(substream); +- if (runtime->status->hw_ptr >= runtime->control->appl_ptr) { +- runtime->render_flag |= SNDRV_RENDER_STOPPED; +- stop_playback = 1; +- } +- snd_pcm_stream_unlock_irq(substream); +- +- if (stop_playback) { +- pr_err("underrun! render stopped\n"); +- break; +- } +- +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", +- __func__, prtd->pcm_count, prtd->out_head); +- temp = buf[0].phys + (prtd->out_head * prtd->pcm_count); +- pr_debug("%s:writing buffer[%d] from 0x%pK\n", +- __func__, prtd->out_head, &temp); +- +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- if (buffer_length == 0) { +- pr_debug("Recieved a zero length buffer-break out"); +- break; +- } +- param.paddr = temp + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- for (i = 0; i < sizeof(struct audio_aio_write_param)/4; +- i++, ++ptrmem) +- pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem); +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) & (runtime->periods - 1); +- break; +- } +- case ASM_DATA_EVENT_RENDERED_EOS: +- pr_debug("ASM_DATA_CMDRSP_EOS\n"); +- if (atomic_read(&prtd->eos)) { +- pr_debug("ASM_DATA_CMDRSP_EOS wake up\n"); +- prtd->cmd_ack = 1; +- wake_up(&the_locks.eos_wait); +- atomic_set(&prtd->eos, 0); +- } +- break; +- case ASM_DATA_EVENT_READ_DONE_V2: { +- pr_debug("ASM_DATA_EVENT_READ_DONE\n"); +- pr_debug("buf = %pK, data = 0x%X, *data = %pK,\n" +- "prtd->pcm_irq_pos = %d\n", +- prtd->audio_client->port[OUT].buf, +- *(uint32_t *)prtd->audio_client->port[OUT].buf->data, +- prtd->audio_client->port[OUT].buf->data, +- prtd->pcm_irq_pos); +- +- memcpy(prtd->audio_client->port[OUT].buf->data + +- prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE), +- COMPRE_CAPTURE_HEADER_SIZE); +- pr_debug("buf = %pK, updated data = 0x%X, *data = %pK\n", +- prtd->audio_client->port[OUT].buf, +- *(uint32_t *)(prtd->audio_client->port[OUT].buf->data + +- prtd->pcm_irq_pos), +- prtd->audio_client->port[OUT].buf->data); +- if (!atomic_read(&prtd->start)) +- break; +- pr_debug("frame size=%d, buffer = 0x%X\n", +- ptrmem[READDONE_IDX_SIZE], +- ptrmem[READDONE_IDX_BUFADD_LSW]); +- if (ptrmem[READDONE_IDX_SIZE] > COMPRE_CAPTURE_MAX_FRAME_SIZE) { +- pr_err("Frame length exceeded the max length"); +- break; +- } +- buf = prtd->audio_client->port[OUT].buf; +- +- pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%pK\n", +- prtd->pcm_irq_pos, &buf[0].phys); +- read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE; +- read_param.paddr = buf[0].phys + +- prtd->pcm_irq_pos + COMPRE_CAPTURE_HEADER_SIZE; +- prtd->pcm_irq_pos += prtd->pcm_count; +- +- if (atomic_read(&prtd->start)) +- snd_pcm_period_elapsed(substream); +- +- q6asm_async_read(prtd->audio_client, &read_param); +- break; +- } +- case APR_BASIC_RSP_RESULT: { +- switch (payload[0]) { +- case ASM_SESSION_CMD_RUN_V2: { +- if (substream->stream +- != SNDRV_PCM_STREAM_PLAYBACK) { +- atomic_set(&prtd->start, 1); +- break; +- } +- if (!atomic_read(&prtd->pending_buffer)) +- break; +- pr_debug("%s: writing %d bytes of buffer[%d] to dsp\n", +- __func__, prtd->pcm_count, prtd->out_head); +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s: writing buffer[%d] from 0x%pK head %d count %d\n", +- __func__, prtd->out_head, &buf[0].phys, +- prtd->pcm_count, prtd->out_head); +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- param.paddr = buf[prtd->out_head].phys +- + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- param.metadata_len = COMPRE_OUTPUT_METADATA_SIZE; +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) +- & (runtime->periods - 1); +- atomic_set(&prtd->pending_buffer, 0); +- } +- break; +- case ASM_STREAM_CMD_FLUSH: +- pr_debug("ASM_STREAM_CMD_FLUSH\n"); +- prtd->cmd_ack = 1; +- wake_up(&the_locks.flush_wait); +- break; +- default: +- break; +- } +- break; +- } +- default: +- pr_debug("Not Supported Event opcode[0x%x]\n", opcode); +- break; +- } +-} +- +-static int msm_compr_send_ddp_cfg(struct audio_client *ac, +- struct snd_dec_ddp *ddp) +-{ +- int i, rc; +- pr_debug("%s\n", __func__); +- +- if (ddp->params_length / 2 > SND_DEC_DDP_MAX_PARAMS) { +- pr_err("%s: Invalid number of params %u, max allowed %u\n", +- __func__, ddp->params_length / 2, +- SND_DEC_DDP_MAX_PARAMS); +- return -EINVAL; +- } +- +- for (i = 0; i < ddp->params_length/2; i++) { +- rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i], +- ddp->params_value[i]); +- if (rc) { +- pr_err("sending params_id: %d failed\n", +- ddp->params_id[i]); +- return rc; +- } +- } +- return 0; +-} +- +-static int msm_compr_playback_prepare(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_pcm_hw_params *params; +- struct asm_aac_cfg aac_cfg; +- uint16_t bits_per_sample = 16; +- int ret; +- +- struct asm_softpause_params softpause = { +- .enable = SOFT_PAUSE_ENABLE, +- .period = SOFT_PAUSE_PERIOD, +- .step = SOFT_PAUSE_STEP, +- .rampingcurve = SOFT_PAUSE_CURVE_LINEAR, +- }; +- struct asm_softvolume_params softvol = { +- .period = SOFT_VOLUME_PERIOD, +- .step = SOFT_VOLUME_STEP, +- .rampingcurve = SOFT_VOLUME_CURVE_LINEAR, +- }; +- +- pr_debug("%s\n", __func__); +- +- params = &soc_prtd->dpcm[substream->stream].hw_params; +- if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) +- bits_per_sample = 24; +- +- ret = q6asm_open_write_v2(prtd->audio_client, +- compr->codec, bits_per_sample); +- if (ret < 0) { +- pr_err("%s: Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- msm_pcm_routing_reg_phy_stream( +- soc_prtd->dai_link->be_id, +- prtd->audio_client->perf_mode, +- prtd->session_id, +- substream->stream); +- /* +- * the number of channels are required to call volume api +- * accoridngly. So, get channels from hw params +- */ +- if ((params_channels(params) > 0) && +- (params_periods(params) <= runtime->hw.channels_max)) +- prtd->channel_mode = params_channels(params); +- +- ret = q6asm_set_softpause(prtd->audio_client, &softpause); +- if (ret < 0) +- pr_err("%s: Send SoftPause Param failed ret=%d\n", +- __func__, ret); +- ret = q6asm_set_softvolume(prtd->audio_client, &softvol); +- if (ret < 0) +- pr_err("%s: Send SoftVolume Param failed ret=%d\n", +- __func__, ret); +- +- ret = q6asm_set_io_mode(prtd->audio_client, +- (COMPRESSED_IO | ASYNC_IO_MODE)); +- if (ret < 0) { +- pr_err("%s: Set IO mode failed\n", __func__); +- return -ENOMEM; +- } +- +- prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream); +- prtd->pcm_count = snd_pcm_lib_period_bytes(substream); +- prtd->pcm_irq_pos = 0; +- /* rate and channels are sent to audio driver */ +- prtd->samp_rate = runtime->rate; +- prtd->channel_mode = runtime->channels; +- prtd->out_head = 0; +- atomic_set(&prtd->out_count, runtime->periods); +- +- if (prtd->enabled) +- return 0; +- +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_MP3: +- /* No media format block for mp3 */ +- break; +- case SND_AUDIOCODEC_AAC: +- pr_debug("%s: SND_AUDIOCODEC_AAC\n", __func__); +- memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg)); +- aac_cfg.aot = AAC_ENC_MODE_EAAC_P; +- aac_cfg.format = 0x03; +- aac_cfg.ch_cfg = runtime->channels; +- aac_cfg.sample_rate = runtime->rate; +- ret = q6asm_media_format_block_aac(prtd->audio_client, +- &aac_cfg); +- if (ret < 0) +- pr_err("%s: CMD Format block failed\n", __func__); +- break; +- case SND_AUDIOCODEC_AC3: { +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- pr_debug("%s: SND_AUDIOCODEC_AC3\n", __func__); +- ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp); +- if (ret < 0) +- pr_err("%s: DDP CMD CFG failed\n", __func__); +- break; +- } +- case SND_AUDIOCODEC_EAC3: { +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- pr_debug("%s: SND_AUDIOCODEC_EAC3\n", __func__); +- ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp); +- if (ret < 0) +- pr_err("%s: DDP CMD CFG failed\n", __func__); +- break; +- } +- default: +- return -EINVAL; +- } +- +- prtd->enabled = 1; +- prtd->cmd_ack = 0; +- prtd->cmd_interrupt = 0; +- +- return 0; +-} +- +-static int msm_compr_capture_prepare(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct audio_buffer *buf = prtd->audio_client->port[OUT].buf; +- struct snd_codec *codec = &compr->info.codec_param.codec; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct audio_aio_read_param read_param; +- uint16_t bits_per_sample = 16; +- int ret = 0; +- int i; +- +- prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream); +- prtd->pcm_count = snd_pcm_lib_period_bytes(substream); +- prtd->pcm_irq_pos = 0; +- +- if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) +- bits_per_sample = 24; +- +- if (!msm_compr_capture_codecs( +- compr->info.codec_param.codec.id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- compr->info.codec_param.codec.id = +- SND_AUDIOCODEC_AMRWB; +- } +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- pr_debug("q6asm_open_read(FORMAT_AMRWB)\n"); +- ret = q6asm_open_read(prtd->audio_client, +- FORMAT_AMRWB); +- if (ret < 0) { +- pr_err("%s: compressed Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- pr_debug("msm_pcm_routing_reg_phy_stream\n"); +- msm_pcm_routing_reg_phy_stream( +- soc_prtd->dai_link->be_id, +- prtd->audio_client->perf_mode, +- prtd->session_id, substream->stream); +- break; +- default: +- pr_debug("q6asm_open_read_compressed(COMPRESSED_META_DATA_MODE)\n"); +- /* +- ret = q6asm_open_read_compressed(prtd->audio_client, +- MAX_NUM_FRAMES_PER_BUFFER, +- COMPRESSED_META_DATA_MODE); +- */ +- ret = -EINVAL; +- break; +- } +- +- if (ret < 0) { +- pr_err("%s: compressed Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- +- ret = q6asm_set_io_mode(prtd->audio_client, +- (COMPRESSED_IO | ASYNC_IO_MODE)); +- if (ret < 0) { +- pr_err("%s: Set IO mode failed\n", __func__); +- return -ENOMEM; +- } +- +- if (!msm_compr_capture_codecs(codec->id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- codec->id = SND_AUDIOCODEC_AMRWB; +- } +- /* rate and channels are sent to audio driver */ +- prtd->samp_rate = runtime->rate; +- prtd->channel_mode = runtime->channels; +- +- if (prtd->enabled) +- return ret; +- read_param.len = prtd->pcm_count; +- +- switch (codec->id) { +- case SND_AUDIOCODEC_AMRWB: +- pr_debug("SND_AUDIOCODEC_AMRWB\n"); +- ret = q6asm_enc_cfg_blk_amrwb(prtd->audio_client, +- MAX_NUM_FRAMES_PER_BUFFER, +- /* +- * use fixed band mode and dtx mode +- * band mode - 23.85 kbps +- */ +- AMR_WB_BAND_MODE, +- /* dtx mode - disable */ +- AMR_WB_DTX_MODE); +- if (ret < 0) +- pr_err("%s: CMD Format block failed: %d\n", +- __func__, ret); +- break; +- default: +- pr_debug("No config for codec %d\n", codec->id); +- } +- pr_debug("%s: Samp_rate = %d, Channel = %d, pcm_size = %d,\n" +- "pcm_count = %d, periods = %d\n", +- __func__, prtd->samp_rate, prtd->channel_mode, +- prtd->pcm_size, prtd->pcm_count, runtime->periods); +- +- for (i = 0; i < runtime->periods; i++) { +- read_param.uid = i; +- switch (codec->id) { +- case SND_AUDIOCODEC_AMRWB: +- read_param.len = prtd->pcm_count +- - COMPRE_CAPTURE_HEADER_SIZE; +- read_param.paddr = buf[i].phys +- + COMPRE_CAPTURE_HEADER_SIZE; +- pr_debug("Push buffer [%d] to DSP, paddr: %pK, vaddr: %pK\n", +- i, &read_param.paddr, +- buf[i].data); +- q6asm_async_read(prtd->audio_client, &read_param); +- break; +- default: +- read_param.paddr = buf[i].phys; +- /*q6asm_async_read_compressed(prtd->audio_client, +- &read_param);*/ +- pr_debug("%s: To add support for read compressed\n", +- __func__); +- ret = -EINVAL; +- break; +- } +- } +- prtd->periods = runtime->periods; +- +- prtd->enabled = 1; +- +- return ret; +-} +- +-static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd) +-{ +- int ret = 0; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- +- pr_debug("%s\n", __func__); +- switch (cmd) { +- case SNDRV_PCM_TRIGGER_START: +- prtd->pcm_irq_pos = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- if (!msm_compr_capture_codecs( +- compr->info.codec_param.codec.id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- compr->info.codec_param.codec.id = +- SND_AUDIOCODEC_AMRWB; +- } +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- break; +- default: +- msm_pcm_routing_reg_psthr_stream( +- soc_prtd->dai_link->be_id, +- prtd->session_id, substream->stream); +- break; +- } +- } +- atomic_set(&prtd->pending_buffer, 1); +- case SNDRV_PCM_TRIGGER_RESUME: +- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +- pr_debug("%s: Trigger start\n", __func__); +- q6asm_run_nowait(prtd->audio_client, 0, 0, 0); +- atomic_set(&prtd->start, 1); +- break; +- case SNDRV_PCM_TRIGGER_STOP: +- pr_debug("SNDRV_PCM_TRIGGER_STOP\n"); +- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- break; +- default: +- msm_pcm_routing_reg_psthr_stream( +- soc_prtd->dai_link->be_id, +- prtd->session_id, substream->stream); +- break; +- } +- } +- atomic_set(&prtd->start, 0); +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- break; +- case SNDRV_PCM_TRIGGER_SUSPEND: +- case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +- pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n"); +- q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); +- atomic_set(&prtd->start, 0); +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- break; +- default: +- ret = -EINVAL; +- break; +- } +- +- return ret; +-} +- +-static void populate_codec_list(struct compr_audio *compr, +- struct snd_pcm_runtime *runtime) +-{ +- pr_debug("%s\n", __func__); +- /* MP3 Block */ +- compr->info.compr_cap.num_codecs = 5; +- compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min; +- compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max; +- compr->info.compr_cap.min_fragments = runtime->hw.periods_min; +- compr->info.compr_cap.max_fragments = runtime->hw.periods_max; +- compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3; +- compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC; +- compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3; +- compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3; +- compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_AMRWB; +- /* Add new codecs here */ +-} +- +-static int msm_compr_open(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr; +- struct msm_audio *prtd; +- int ret = 0; +- +- pr_debug("%s\n", __func__); +- compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL); +- if (compr == NULL) { +- pr_err("Failed to allocate memory for msm_audio\n"); +- return -ENOMEM; +- } +- prtd = &compr->prtd; +- prtd->substream = substream; +- runtime->render_flag = SNDRV_DMA_MODE; +- prtd->audio_client = q6asm_audio_client_alloc( +- (app_cb)compr_event_handler, compr); +- if (!prtd->audio_client) { +- pr_info("%s: Could not allocate memory\n", __func__); +- kfree(prtd); +- return -ENOMEM; +- } +- +- prtd->audio_client->perf_mode = false; +- pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session); +- +- prtd->session_id = prtd->audio_client->session; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- runtime->hw = msm_compr_hardware_playback; +- prtd->cmd_ack = 1; +- } else { +- runtime->hw = msm_compr_hardware_capture; +- } +- +- +- ret = snd_pcm_hw_constraint_list(runtime, 0, +- SNDRV_PCM_HW_PARAM_RATE, +- &constraints_sample_rates); +- if (ret < 0) +- pr_info("snd_pcm_hw_constraint_list failed\n"); +- /* Ensure that buffer size is a multiple of period size */ +- ret = snd_pcm_hw_constraint_integer(runtime, +- SNDRV_PCM_HW_PARAM_PERIODS); +- if (ret < 0) +- pr_info("snd_pcm_hw_constraint_integer failed\n"); +- +- prtd->dsp_cnt = 0; +- atomic_set(&prtd->pending_buffer, 1); +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- compr->codec = FORMAT_MP3; +- populate_codec_list(compr, runtime); +- runtime->private_data = compr; +- atomic_set(&prtd->eos, 0); +- return 0; +-} +- +-static int compressed_set_volume(struct msm_audio *prtd, uint32_t volume) +-{ +- int rc = 0; +- int avg_vol = 0; +- int lgain = (volume >> 16) & 0xFFFF; +- int rgain = volume & 0xFFFF; +- if (prtd && prtd->audio_client) { +- pr_debug("%s: channels %d volume 0x%x\n", __func__, +- prtd->channel_mode, volume); +- if ((prtd->channel_mode == 2) && +- (lgain != rgain)) { +- pr_debug("%s: call q6asm_set_lrgain\n", __func__); +- rc = q6asm_set_lrgain(prtd->audio_client, lgain, rgain); +- } else { +- avg_vol = (lgain + rgain)/2; +- pr_debug("%s: call q6asm_set_volume\n", __func__); +- rc = q6asm_set_volume(prtd->audio_client, avg_vol); +- } +- if (rc < 0) { +- pr_err("%s: Send Volume command failed rc=%d\n", +- __func__, rc); +- } +- } +- return rc; +-} +- +-static int msm_compr_playback_close(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- int dir = 0; +- +- pr_debug("%s\n", __func__); +- +- dir = IN; +- atomic_set(&prtd->pending_buffer, 0); +- +- prtd->pcm_irq_pos = 0; +- q6asm_cmd(prtd->audio_client, CMD_CLOSE); +- q6asm_audio_client_buf_free_contiguous(dir, +- prtd->audio_client); +- msm_pcm_routing_dereg_phy_stream( +- soc_prtd->dai_link->be_id, +- SNDRV_PCM_STREAM_PLAYBACK); +- q6asm_audio_client_free(prtd->audio_client); +- kfree(prtd); +- return 0; +-} +- +-static int msm_compr_capture_close(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- int dir = OUT; +- +- pr_debug("%s\n", __func__); +- atomic_set(&prtd->pending_buffer, 0); +- q6asm_cmd(prtd->audio_client, CMD_CLOSE); +- q6asm_audio_client_buf_free_contiguous(dir, +- prtd->audio_client); +- msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, +- SNDRV_PCM_STREAM_CAPTURE); +- q6asm_audio_client_free(prtd->audio_client); +- kfree(prtd); +- return 0; +-} +- +-static int msm_compr_close(struct snd_pcm_substream *substream) +-{ +- int ret = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- ret = msm_compr_playback_close(substream); +- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) +- ret = msm_compr_capture_close(substream); +- return ret; +-} +- +-static int msm_compr_prepare(struct snd_pcm_substream *substream) +-{ +- int ret = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- ret = msm_compr_playback_prepare(substream); +- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) +- ret = msm_compr_capture_prepare(substream); +- return ret; +-} +- +-static snd_pcm_uframes_t msm_compr_pointer(struct snd_pcm_substream *substream) +-{ +- +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- +- if (prtd->pcm_irq_pos >= prtd->pcm_size) +- prtd->pcm_irq_pos = 0; +- +- pr_debug("%s: pcm_irq_pos = %d, pcm_size = %d, sample_bits = %d,\n" +- "frame_bits = %d\n", __func__, prtd->pcm_irq_pos, +- prtd->pcm_size, runtime->sample_bits, +- runtime->frame_bits); +- return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); +-} +- +-static int msm_compr_mmap(struct snd_pcm_substream *substream, +- struct vm_area_struct *vma) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct msm_audio *prtd = runtime->private_data; +- struct audio_client *ac = prtd->audio_client; +- struct audio_port_data *apd = ac->port; +- struct audio_buffer *ab; +- int dir = -1; +- +- prtd->mmap_flag = 1; +- runtime->render_flag = SNDRV_NON_DMA_MODE; +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- dir = IN; +- else +- dir = OUT; +- ab = &(apd[dir].buf[0]); +- +- return msm_audio_ion_mmap(ab, vma); +-} +- +-static int msm_compr_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_dma_buffer *dma_buf = &substream->dma_buffer; +- struct audio_buffer *buf; +- int dir, ret; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- dir = IN; +- else +- dir = OUT; +- /* Modifying kernel hardware params based on userspace config */ +- if (params_periods(params) > 0 && +- (params_periods(params) != runtime->hw.periods_max)) { +- runtime->hw.periods_max = params_periods(params); +- } +- if (params_period_bytes(params) > 0 && +- (params_period_bytes(params) != runtime->hw.period_bytes_min)) { +- runtime->hw.period_bytes_min = params_period_bytes(params); +- } +- runtime->hw.buffer_bytes_max = +- runtime->hw.period_bytes_min * runtime->hw.periods_max; +- pr_debug("allocate %zd buffers each of size %d\n", +- runtime->hw.period_bytes_min, +- runtime->hw.periods_max); +- ret = q6asm_audio_client_buf_alloc_contiguous(dir, +- prtd->audio_client, +- runtime->hw.period_bytes_min, +- runtime->hw.periods_max); +- if (ret < 0) { +- pr_err("Audio Start: Buffer Allocation failed rc = %d\n", +- ret); +- return -ENOMEM; +- } +- buf = prtd->audio_client->port[dir].buf; +- +- dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; +- dma_buf->dev.dev = substream->pcm->card->dev; +- dma_buf->private_data = NULL; +- dma_buf->area = buf[0].data; +- dma_buf->addr = buf[0].phys; +- dma_buf->bytes = runtime->hw.buffer_bytes_max; +- +- pr_debug("%s: buf[%pK]dma_buf->area[%pK]dma_buf->addr[%pK]\n" +- "dma_buf->bytes[%zd]\n", __func__, +- (void *)buf, (void *)dma_buf->area, +- &dma_buf->addr, dma_buf->bytes); +- if (!dma_buf->area) +- return -ENOMEM; +- +- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); +- return 0; +-} +- +-static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int rc = 0; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- uint64_t timestamp; +- uint64_t temp; +- +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP: { +- struct snd_compr_tstamp *tstamp; +- pr_debug("SNDRV_COMPRESS_TSTAMP\n"); +- tstamp = arg; +- memset(tstamp, 0x0, sizeof(*tstamp)); +- rc = q6asm_get_session_time(prtd->audio_client, ×tamp); +- if (rc < 0) { +- pr_err("%s: Get Session Time return value =%lld\n", +- __func__, timestamp); +- return -EAGAIN; +- } +- temp = (timestamp * 2 * runtime->channels); +- temp = temp * (runtime->rate/1000); +- temp = div_u64(temp, 1000); +- tstamp->sampling_rate = runtime->rate; +- tstamp->timestamp = timestamp; +- pr_debug("%s: bytes_consumed:,timestamp = %lld,\n", +- __func__, +- tstamp->timestamp); +- return 0; +- } +- case SNDRV_COMPRESS_GET_CAPS: { +- struct snd_compr_caps *caps; +- caps = arg; +- memset(caps, 0, sizeof(*caps)); +- pr_debug("SNDRV_COMPRESS_GET_CAPS\n"); +- memcpy(caps, &compr->info.compr_cap, sizeof(*caps)); +- return 0; +- } +- case SNDRV_COMPRESS_SET_PARAMS: +- pr_debug("SNDRV_COMPRESS_SET_PARAMS:\n"); +- memcpy(&compr->info.codec_param, (void *) arg, +- sizeof(struct snd_compr_params)); +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_MP3: +- /* For MP3 we dont need any other parameter */ +- pr_debug("SND_AUDIOCODEC_MP3\n"); +- compr->codec = FORMAT_MP3; +- break; +- case SND_AUDIOCODEC_AAC: +- pr_debug("SND_AUDIOCODEC_AAC\n"); +- compr->codec = FORMAT_MPEG4_AAC; +- break; +- case SND_AUDIOCODEC_AC3: { +- char params_value[MAX_AC3_PARAM_SIZE]; +- int *params_value_data = (int *)params_value; +- /* 36 is the max param length for ddp */ +- int i; +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- uint32_t params_length = 0; +- memset(params_value, 0, MAX_AC3_PARAM_SIZE); +- /* check integer overflow */ +- if (ddp->params_length > UINT_MAX/sizeof(int)) { +- pr_err("%s: Integer overflow ddp->params_length %d\n", +- __func__, ddp->params_length); +- return -EINVAL; +- } +- params_length = ddp->params_length*sizeof(int); +- if (params_length > MAX_AC3_PARAM_SIZE) { +- /*MAX is 36*sizeof(int) this should not happen*/ +- pr_err("%s: params_length(%d) is greater than %zd\n", +- __func__, params_length, MAX_AC3_PARAM_SIZE); +- return -EINVAL; +- } +- pr_debug("SND_AUDIOCODEC_AC3\n"); +- compr->codec = FORMAT_AC3; +- pr_debug("params_length: %d\n", ddp->params_length); +- for (i = 0; i < params_length/sizeof(int); i++) +- pr_debug("params_value[%d]: %x\n", i, +- params_value_data[i]); +- for (i = 0; i < ddp->params_length/2; i++) { +- ddp->params_id[i] = params_value_data[2*i]; +- ddp->params_value[i] = params_value_data[2*i+1]; +- } +- if (atomic_read(&prtd->start)) { +- rc = msm_compr_send_ddp_cfg(prtd->audio_client, +- ddp); +- if (rc < 0) +- pr_err("%s: DDP CMD CFG failed\n", +- __func__); +- } +- break; +- } +- case SND_AUDIOCODEC_EAC3: { +- char params_value[MAX_AC3_PARAM_SIZE]; +- int *params_value_data = (int *)params_value; +- /* 36 is the max param length for ddp */ +- int i; +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- uint32_t params_length = 0; +- memset(params_value, 0, MAX_AC3_PARAM_SIZE); +- /* check integer overflow */ +- if (ddp->params_length > UINT_MAX/sizeof(int)) { +- pr_err("%s: Integer overflow ddp->params_length %d\n", +- __func__, ddp->params_length); +- return -EINVAL; +- } +- params_length = ddp->params_length*sizeof(int); +- if (params_length > MAX_AC3_PARAM_SIZE) { +- /*MAX is 36*sizeof(int) this should not happen*/ +- pr_err("%s: params_length(%d) is greater than %zd\n", +- __func__, params_length, MAX_AC3_PARAM_SIZE); +- return -EINVAL; +- } +- pr_debug("SND_AUDIOCODEC_EAC3\n"); +- compr->codec = FORMAT_EAC3; +- pr_debug("params_length: %d\n", ddp->params_length); +- for (i = 0; i < ddp->params_length; i++) +- pr_debug("params_value[%d]: %x\n", i, +- params_value_data[i]); +- for (i = 0; i < ddp->params_length/2; i++) { +- ddp->params_id[i] = params_value_data[2*i]; +- ddp->params_value[i] = params_value_data[2*i+1]; +- } +- if (atomic_read(&prtd->start)) { +- rc = msm_compr_send_ddp_cfg(prtd->audio_client, +- ddp); +- if (rc < 0) +- pr_err("%s: DDP CMD CFG failed\n", +- __func__); +- } +- break; +- } +- default: +- pr_debug("FORMAT_LINEAR_PCM\n"); +- compr->codec = FORMAT_LINEAR_PCM; +- break; +- } +- return 0; +- case SNDRV_PCM_IOCTL1_RESET: +- pr_debug("SNDRV_PCM_IOCTL1_RESET\n"); +- /* Flush only when session is started during CAPTURE, +- while PLAYBACK has no such restriction. */ +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || +- (substream->stream == SNDRV_PCM_STREAM_CAPTURE && +- atomic_read(&prtd->start))) { +- if (atomic_read(&prtd->eos)) { +- prtd->cmd_interrupt = 1; +- wake_up(&the_locks.eos_wait); +- atomic_set(&prtd->eos, 0); +- } +- +- /* A unlikely race condition possible with FLUSH +- DRAIN if ack is set by flush and reset by drain */ +- prtd->cmd_ack = 0; +- rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH); +- if (rc < 0) { +- pr_err("%s: flush cmd failed rc=%d\n", +- __func__, rc); +- return rc; +- } +- rc = wait_event_timeout(the_locks.flush_wait, +- prtd->cmd_ack, 5 * HZ); +- if (!rc) +- pr_err("Flush cmd timeout\n"); +- prtd->pcm_irq_pos = 0; +- } +- break; +- case SNDRV_COMPRESS_DRAIN: +- pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__); +- if (atomic_read(&prtd->pending_buffer)) { +- pr_debug("%s: no pending writes, drain would block\n", +- __func__); +- return -EWOULDBLOCK; +- } +- +- atomic_set(&prtd->eos, 1); +- atomic_set(&prtd->pending_buffer, 0); +- prtd->cmd_ack = 0; +- q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); +- /* Wait indefinitely for DRAIN. Flush can also signal this*/ +- rc = wait_event_interruptible(the_locks.eos_wait, +- (prtd->cmd_ack || prtd->cmd_interrupt)); +- +- if (rc < 0) +- pr_err("EOS cmd interrupted\n"); +- pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait\n", __func__); +- +- if (prtd->cmd_interrupt) +- rc = -EINTR; +- +- prtd->cmd_interrupt = 0; +- return rc; +- default: +- break; +- } +- return snd_pcm_lib_ioctl(substream, cmd, arg); +-} +-#ifdef CONFIG_COMPAT +-struct snd_enc_wma32 { +- u32 super_block_align; /* WMA Type-specific data */ +- u32 encodeopt1; +- u32 encodeopt2; +-}; +- +-struct snd_enc_vorbis32 { +- s32 quality; +- u32 managed; +- u32 max_bit_rate; +- u32 min_bit_rate; +- u32 downmix; +-}; +- +-struct snd_enc_real32 { +- u32 quant_bits; +- u32 start_region; +- u32 num_regions; +-}; +- +-struct snd_enc_flac32 { +- u32 num; +- u32 gain; +-}; +- +-struct snd_enc_generic32 { +- u32 bw; /* encoder bandwidth */ +- s32 reserved[15]; +-}; +-struct snd_dec_ddp32 { +- u32 params_length; +- u32 params_id[18]; +- u32 params_value[18]; +-}; +- +-union snd_codec_options32 { +- struct snd_enc_wma32 wma; +- struct snd_enc_vorbis32 vorbis; +- struct snd_enc_real32 real; +- struct snd_enc_flac32 flac; +- struct snd_enc_generic32 generic; +- struct snd_dec_ddp32 ddp; +-}; +- +-struct snd_codec32 { +- u32 id; +- u32 ch_in; +- u32 ch_out; +- u32 sample_rate; +- u32 bit_rate; +- u32 rate_control; +- u32 profile; +- u32 level; +- u32 ch_mode; +- u32 format; +- u32 align; +- union snd_codec_options32 options; +- u32 reserved[3]; +-}; +- +-struct snd_compressed_buffer32 { +- u32 fragment_size; +- u32 fragments; +-}; +- +-struct snd_compr_params32 { +- struct snd_compressed_buffer32 buffer; +- struct snd_codec32 codec; +- u8 no_wake_mode; +-}; +- +-struct snd_compr_caps32 { +- u32 num_codecs; +- u32 direction; +- u32 min_fragment_size; +- u32 max_fragment_size; +- u32 min_fragments; +- u32 max_fragments; +- u32 codecs[MAX_NUM_CODECS]; +- u32 reserved[11]; +-}; +-struct snd_compr_tstamp32 { +- u32 byte_offset; +- u32 copied_total; +- compat_ulong_t pcm_frames; +- compat_ulong_t pcm_io_frames; +- u32 sampling_rate; +- compat_u64 timestamp; +-}; +-enum { +- SNDRV_COMPRESS_TSTAMP32 = _IOR('C', 0x20, struct snd_compr_tstamp32), +- SNDRV_COMPRESS_GET_CAPS32 = _IOWR('C', 0x10, struct snd_compr_caps32), +- SNDRV_COMPRESS_SET_PARAMS32 = +- _IOW('C', 0x12, struct snd_compr_params32), +-}; +-static int msm_compr_compat_ioctl(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int err = 0; +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP32: { +- struct snd_compr_tstamp tstamp; +- struct snd_compr_tstamp32 tstamp32; +- memset(&tstamp, 0, sizeof(tstamp)); +- memset(&tstamp32, 0, sizeof(tstamp32)); +- cmd = SNDRV_COMPRESS_TSTAMP; +- err = msm_compr_ioctl_shared(substream, cmd, &tstamp); +- if (err) { +- pr_err("%s: COMPRESS_TSTAMP failed rc %d\n", +- __func__, err); +- goto bail_out; +- } +- tstamp32.byte_offset = tstamp.byte_offset; +- tstamp32.copied_total = tstamp.copied_total; +- tstamp32.pcm_frames = tstamp.pcm_frames; +- tstamp32.pcm_io_frames = tstamp.pcm_io_frames; +- tstamp32.sampling_rate = tstamp.sampling_rate; +- tstamp32.timestamp = tstamp.timestamp; +- if (copy_to_user(arg, &tstamp32, sizeof(tstamp32))) { +- pr_err("%s: copytouser failed COMPRESS_TSTAMP32\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_GET_CAPS32: { +- struct snd_compr_caps caps; +- struct snd_compr_caps32 caps32; +- u32 i; +- memset(&caps, 0, sizeof(caps)); +- memset(&caps32, 0, sizeof(caps32)); +- cmd = SNDRV_COMPRESS_GET_CAPS; +- err = msm_compr_ioctl_shared(substream, cmd, &caps); +- if (err) { +- pr_err("%s: GET_CAPS failed rc %d\n", +- __func__, err); +- goto bail_out; +- } +- pr_debug("SNDRV_COMPRESS_GET_CAPS_32\n"); +- if (!err && caps.num_codecs >= MAX_NUM_CODECS) { +- pr_err("%s: Invalid number of codecs\n", __func__); +- err = -EINVAL; +- goto bail_out; +- } +- caps32.direction = caps.direction; +- caps32.max_fragment_size = caps.max_fragment_size; +- caps32.max_fragments = caps.max_fragments; +- caps32.min_fragment_size = caps.min_fragment_size; +- caps32.num_codecs = caps.num_codecs; +- for (i = 0; i < caps.num_codecs; i++) +- caps32.codecs[i] = caps.codecs[i]; +- if (copy_to_user(arg, &caps32, sizeof(caps32))) { +- pr_err("%s: copytouser failed COMPRESS_GETCAPS32\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_SET_PARAMS32: { +- struct snd_compr_params32 params32; +- struct snd_compr_params params; +- memset(¶ms32, 0 , sizeof(params32)); +- memset(¶ms, 0 , sizeof(params)); +- cmd = SNDRV_COMPRESS_SET_PARAMS; +- if (copy_from_user(¶ms32, arg, sizeof(params32))) { +- pr_err("%s: copyfromuser failed SET_PARAMS32\n", +- __func__); +- err = -EFAULT; +- goto bail_out; +- } +- params.no_wake_mode = params32.no_wake_mode; +- params.codec.id = params32.codec.id; +- params.codec.ch_in = params32.codec.ch_in; +- params.codec.ch_out = params32.codec.ch_out; +- params.codec.sample_rate = params32.codec.sample_rate; +- params.codec.bit_rate = params32.codec.bit_rate; +- params.codec.rate_control = params32.codec.rate_control; +- params.codec.profile = params32.codec.profile; +- params.codec.level = params32.codec.level; +- params.codec.ch_mode = params32.codec.ch_mode; +- params.codec.format = params32.codec.format; +- params.codec.align = params32.codec.align; +- +- switch (params.codec.id) { +- case SND_AUDIOCODEC_WMA: +- case SND_AUDIOCODEC_WMA_PRO: +- params.codec.options.wma.encodeopt1 = +- params32.codec.options.wma.encodeopt1; +- params.codec.options.wma.encodeopt2 = +- params32.codec.options.wma.encodeopt2; +- params.codec.options.wma.super_block_align = +- params32.codec.options.wma.super_block_align; +- break; +- case SND_AUDIOCODEC_VORBIS: +- params.codec.options.vorbis.downmix = +- params32.codec.options.vorbis.downmix; +- params.codec.options.vorbis.managed = +- params32.codec.options.vorbis.managed; +- params.codec.options.vorbis.max_bit_rate = +- params32.codec.options.vorbis.max_bit_rate; +- params.codec.options.vorbis.min_bit_rate = +- params32.codec.options.vorbis.min_bit_rate; +- params.codec.options.vorbis.quality = +- params32.codec.options.vorbis.quality; +- break; +- case SND_AUDIOCODEC_REAL: +- params.codec.options.real.num_regions = +- params32.codec.options.real.num_regions; +- params.codec.options.real.quant_bits = +- params32.codec.options.real.quant_bits; +- params.codec.options.real.start_region = +- params32.codec.options.real.start_region; +- break; +- case SND_AUDIOCODEC_FLAC: +- params.codec.options.flac.gain = +- params32.codec.options.flac.gain; +- params.codec.options.flac.num = +- params32.codec.options.flac.num; +- break; +- case SND_AUDIOCODEC_DTS: +- case SND_AUDIOCODEC_DTS_PASS_THROUGH: +- case SND_AUDIOCODEC_DTS_LBR: +- case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH: +- case SND_AUDIOCODEC_DTS_TRANSCODE_LOOPBACK: +- break; +- case SND_AUDIOCODEC_AC3: +- case SND_AUDIOCODEC_EAC3: +- params.codec.options.ddp.params_length = +- params32.codec.options.ddp.params_length; +- memcpy(params.codec.options.ddp.params_value, +- params32.codec.options.ddp.params_value, +- sizeof(params32.codec.options.ddp.params_value)); +- memcpy(params.codec.options.ddp.params_id, +- params32.codec.options.ddp.params_id, +- sizeof(params32.codec.options.ddp.params_id)); +- break; +- default: +- params.codec.options.generic.bw = +- params32.codec.options.generic.bw; +- break; +- } +- if (!err) +- err = msm_compr_ioctl_shared(substream, cmd, ¶ms); +- break; +- } +- default: +- err = msm_compr_ioctl_shared(substream, cmd, arg); +- } +-bail_out: +- return err; +- +-} +-#endif +-static int msm_compr_ioctl(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int err = 0; +- if (!substream) { +- pr_err("%s: Invalid params\n", __func__); +- return -EINVAL; +- } +- pr_debug("%s called with cmd = %d\n", __func__, cmd); +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP: { +- struct snd_compr_tstamp tstamp; +- if (!arg) { +- pr_err("%s: Invalid params Tstamp\n", __func__); +- return -EINVAL; +- } +- err = msm_compr_ioctl_shared(substream, cmd, &tstamp); +- if (err) +- pr_err("%s: COMPRESS_TSTAMP failed rc %d\n", +- __func__, err); +- if (!err && copy_to_user(arg, &tstamp, sizeof(tstamp))) { +- pr_err("%s: copytouser failed COMPRESS_TSTAMP\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_GET_CAPS: { +- struct snd_compr_caps cap; +- if (!arg) { +- pr_err("%s: Invalid params getcaps\n", __func__); +- return -EINVAL; +- } +- pr_debug("SNDRV_COMPRESS_GET_CAPS\n"); +- err = msm_compr_ioctl_shared(substream, cmd, &cap); +- if (err) +- pr_err("%s: GET_CAPS failed rc %d\n", +- __func__, err); +- if (!err && copy_to_user(arg, &cap, sizeof(cap))) { +- pr_err("%s: copytouser failed GET_CAPS\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_SET_PARAMS: { +- struct snd_compr_params params; +- if (!arg) { +- pr_err("%s: Invalid params setparam\n", __func__); +- return -EINVAL; +- } +- if (copy_from_user(¶ms, arg, +- sizeof(struct snd_compr_params))) { +- pr_err("%s: SET_PARAMS\n", __func__); +- return -EFAULT; +- } +- err = msm_compr_ioctl_shared(substream, cmd, ¶ms); +- if (err) +- pr_err("%s: SET_PARAMS failed rc %d\n", +- __func__, err); +- break; +- } +- default: +- err = msm_compr_ioctl_shared(substream, cmd, arg); +- } +- return err; +-} +- +-static int msm_compr_restart(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct audio_aio_write_param param; +- struct audio_buffer *buf = NULL; +- struct output_meta_data_st output_meta_data; +- int time_stamp_flag = 0; +- int buffer_length = 0; +- +- pr_debug("%s, trigger restart\n", __func__); +- +- if (runtime->render_flag & SNDRV_RENDER_STOPPED) { +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", +- __func__, prtd->pcm_count, prtd->out_head); +- pr_debug("%s:writing buffer[%d] from 0x%08x\n", +- __func__, prtd->out_head, +- ((unsigned int)buf[0].phys +- + (prtd->out_head * prtd->pcm_count))); +- +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- +- param.paddr = (unsigned long)buf[0].phys +- + (prtd->out_head * prtd->pcm_count) +- + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) & (runtime->periods - 1); +- +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- return 0; +- } +- return 0; +-} +- +-static int msm_compr_volume_ctl_put(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- int rc = 0; +- struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); +- struct snd_pcm_substream *substream = +- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; +- struct msm_audio *prtd; +- int volume = ucontrol->value.integer.value[0]; +- +- pr_debug("%s: volume : %x\n", __func__, volume); +- if (!substream) +- return -ENODEV; +- if (!substream->runtime) +- return 0; +- prtd = substream->runtime->private_data; +- if (prtd) +- rc = compressed_set_volume(prtd, volume); +- +- return rc; +-} +- +-static int msm_compr_volume_ctl_get(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); +- struct snd_pcm_substream *substream = +- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; +- struct msm_audio *prtd; +- +- pr_debug("%s\n", __func__); +- if (!substream) +- return -ENODEV; +- if (!substream->runtime) +- return 0; +- prtd = substream->runtime->private_data; +- if (prtd) +- ucontrol->value.integer.value[0] = prtd->volume; +- return 0; +-} +- +-static int msm_compr_add_controls(struct snd_soc_pcm_runtime *rtd) +-{ +- int ret = 0; +- struct snd_pcm *pcm = rtd->pcm; +- struct snd_pcm_volume *volume_info; +- struct snd_kcontrol *kctl; +- +- dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__); +- ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, +- NULL, 1, rtd->dai_link->be_id, +- &volume_info); +- if (ret < 0) +- return ret; +- kctl = volume_info->kctl; +- kctl->put = msm_compr_volume_ctl_put; +- kctl->get = msm_compr_volume_ctl_get; +- kctl->tlv.p = compr_rx_vol_gain; +- return 0; +-} +- +-static struct snd_pcm_ops msm_compr_ops = { +- .open = msm_compr_open, +- .hw_params = msm_compr_hw_params, +- .close = msm_compr_close, +- .ioctl = msm_compr_ioctl, +- .prepare = msm_compr_prepare, +- .trigger = msm_compr_trigger, +- .pointer = msm_compr_pointer, +- .mmap = msm_compr_mmap, +- .restart = msm_compr_restart, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = msm_compr_compat_ioctl, +-#endif +-}; +- +-static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) +-{ +- struct snd_card *card = rtd->card->snd_card; +- int ret = 0; +- +- if (!card->dev->coherent_dma_mask) +- card->dev->coherent_dma_mask = DMA_BIT_MASK(32); +- +- ret = msm_compr_add_controls(rtd); +- if (ret) +- pr_err("%s, kctl add failed\n", __func__); +- return ret; +-} +- +-static struct snd_soc_platform_driver msm_soc_platform = { +- .ops = &msm_compr_ops, +- .pcm_new = msm_asoc_pcm_new, +-}; +- +-static int msm_compr_probe(struct platform_device *pdev) +-{ +- +- dev_info(&pdev->dev, "%s: dev name %s\n", +- __func__, dev_name(&pdev->dev)); +- +- return snd_soc_register_platform(&pdev->dev, +- &msm_soc_platform); +-} +- +-static int msm_compr_remove(struct platform_device *pdev) +-{ +- snd_soc_unregister_platform(&pdev->dev); +- return 0; +-} +- +-static const struct of_device_id msm_compr_dt_match[] = { +- {.compatible = "qcom,msm-compr-dsp"}, +- {} +-}; +-MODULE_DEVICE_TABLE(of, msm_compr_dt_match); +- +-static struct platform_driver msm_compr_driver = { +- .driver = { +- .name = "msm-compr-dsp", +- .owner = THIS_MODULE, +- .of_match_table = msm_compr_dt_match, +- }, +- .probe = msm_compr_probe, +- .remove = msm_compr_remove, +-}; +- +-static int __init msm_soc_platform_init(void) +-{ +- init_waitqueue_head(&the_locks.enable_wait); +- init_waitqueue_head(&the_locks.eos_wait); +- init_waitqueue_head(&the_locks.write_wait); +- init_waitqueue_head(&the_locks.read_wait); +- init_waitqueue_head(&the_locks.flush_wait); +- +- return platform_driver_register(&msm_compr_driver); +-} +-module_init(msm_soc_platform_init); +- +-static void __exit msm_soc_platform_exit(void) +-{ +- platform_driver_unregister(&msm_compr_driver); +-} +-module_exit(msm_soc_platform_exit); +- +-MODULE_DESCRIPTION("PCM module platform driver"); +-MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h +deleted file mode 100644 +index d6e3ec6..0000000 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h ++++ /dev/null +@@ -1,36 +0,0 @@ +-/* +- * Copyright (c) 2012, The 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 +- * only version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _MSM_COMPR_H +-#define _MSM_COMPR_H +-#include +-#include +-#include +-#include +-#include +- +-#include "msm-pcm-q6-v2.h" +- +-struct compr_info { +- struct snd_compr_caps compr_cap; +- struct snd_compr_codec_caps codec_caps; +- struct snd_compr_params codec_param; +-}; +- +-struct compr_audio { +- struct msm_audio prtd; +- struct compr_info info; +- uint32_t codec; +-}; +- +-#endif /*_MSM_COMPR_H*/ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9678/0.patch b/Patches/Linux_CVEs/CVE-2017-9678/0.patch new file mode 100644 index 00000000..959bc8ff --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9678/0.patch @@ -0,0 +1,42 @@ +From 420d0dc1b4563880f962002e8cb21e733bf074eb Mon Sep 17 00:00:00 2001 +From: Harsh Sahu +Date: Fri, 21 Apr 2017 16:12:22 -0700 +Subject: [PATCH] msm: mdss: fix memcpy source and dest memory buffer size + mismatch + +Currently memcpy is copying from a bigger memory size to a smaller +memory size, which may lead to buffer overflow. This change corrects +this issue by performing the memcopy restricted to the smaller of the +src or dest memory buffer. + +Bug: 35258962 +Change-Id: Ibbe5665083799a4262d3cfbb06f94f3e35e03748 +Signed-off-by: Harsh Sahu +--- + drivers/video/msm/mdss/mdss_compat_utils.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c +index 7159d91148645..ec08626ba7765 100644 +--- a/drivers/video/msm/mdss/mdss_compat_utils.c ++++ b/drivers/video/msm/mdss/mdss_compat_utils.c +@@ -119,14 +119,18 @@ static unsigned int __do_compat_ioctl_nr(unsigned int cmd32) + static void __copy_atomic_commit_struct(struct mdp_layer_commit *commit, + struct mdp_layer_commit32 *commit32) + { ++ unsigned int destSize = sizeof(commit->commit_v1.reserved); ++ unsigned int srcSize = sizeof(commit32->commit_v1.reserved); ++ unsigned int count = (destSize <= srcSize ? destSize : srcSize); + commit->version = commit32->version; + commit->commit_v1.flags = commit32->commit_v1.flags; + commit->commit_v1.input_layer_cnt = + commit32->commit_v1.input_layer_cnt; + commit->commit_v1.left_roi = commit32->commit_v1.left_roi; + commit->commit_v1.right_roi = commit32->commit_v1.right_roi; ++ + memcpy(&commit->commit_v1.reserved, &commit32->commit_v1.reserved, +- sizeof(commit32->commit_v1.reserved)); ++ count); + } + + static struct mdp_input_layer32 *__create_layer_list32( diff --git a/Patches/Linux_CVEs/CVE-2017-9679/0.patch b/Patches/Linux_CVEs/CVE-2017-9679/0.patch new file mode 100644 index 00000000..0aa2e795 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9679/0.patch @@ -0,0 +1,45 @@ +From 31f54e33d88c676bedb64127b5ae0c60d06f9518 Mon Sep 17 00:00:00 2001 +From: Abir Ghosh +Date: Tue, 11 Apr 2017 10:01:15 +0530 +Subject: [PATCH] qbt1000: Terminate fingerprint TA name with null + +Terminate the string, coming from userspace and containing the name +of fingerprint trusted app, with null character, to make sure kernel +memory does not leak into logs + +Bug: 35644510 +Change-Id: I1668a64fcb6747ce3ef3b1ee6321fa5fa4a1798a +CRs-Fixed: 2029409 +Signed-off-by: Abir Ghosh +--- + drivers/soc/qcom/qbt1000.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c +index bd6f0e6005f31..6b3d34bc8c970 100755 +--- a/drivers/soc/qcom/qbt1000.c ++++ b/drivers/soc/qcom/qbt1000.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2017, The 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 +@@ -803,13 +803,15 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + } + } + ++ app.name[MAX_NAME_SIZE - 1] = '\0'; ++ + /* start the TZ app */ + rc = qseecom_start_app(&drvdata->app_handle, app.name, app.size); + if (rc == 0) { + g_app_buf_size = app.size; + } else { +- dev_err(drvdata->dev, "%s: App %s failed to load\n", +- __func__, app.name); ++ dev_err(drvdata->dev, "%s: Fingerprint Trusted App failed to load\n", ++ __func__); + goto end; + } + diff --git a/Patches/Linux_CVEs/CVE-2017-9680/0.patch b/Patches/Linux_CVEs/CVE-2017-9680/0.patch new file mode 100644 index 00000000..37486924 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9680/0.patch @@ -0,0 +1,36 @@ +From b256cd87d50eede2dae6185fbe8828d7223db0d6 Mon Sep 17 00:00:00 2001 +From: Abir Ghosh +Date: Tue, 11 Apr 2017 10:10:23 +0530 +Subject: [PATCH] qbt1000: Initialize drvdata structure before usage + +Fix uninitialized local variable error which might have lead to +crash + +Bug: 35764241 +Change-Id: I3fd95cb343c3175e4190c8ebfe209399db0602a6 +CRs-Fixed: 2030137 +Signed-off-by: Abir Ghosh +--- + drivers/soc/qcom/qbt1000.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c +index f76cf0f45ecaa..bd6f0e6005f31 100755 +--- a/drivers/soc/qcom/qbt1000.c ++++ b/drivers/soc/qcom/qbt1000.c +@@ -752,13 +752,14 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + void __user *priv_arg = (void __user *)arg; + struct qbt1000_drvdata *drvdata; + ++ drvdata = file->private_data; ++ + if (IS_ERR(priv_arg)) { + dev_err(drvdata->dev, "%s: invalid user space pointer %lu\n", + __func__, arg); + return -EINVAL; + } + +- drvdata = file->private_data; + pm_runtime_get_sync(drvdata->dev); + mutex_lock(&drvdata->mutex); + if (((drvdata->sensor_conn_type == SPI) && (!drvdata->clock_state)) || diff --git a/Patches/Linux_CVEs/CVE-2017-9682/0.patch b/Patches/Linux_CVEs/CVE-2017-9682/0.patch new file mode 100644 index 00000000..8d40372f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9682/0.patch @@ -0,0 +1,31 @@ +From cd821a40b76919b0815a9a7c09d0f6cf1f15a7ee Mon Sep 17 00:00:00 2001 +From: Sunil Khatri +Date: Mon, 5 Jun 2017 11:16:57 -0700 +Subject: [PATCH] msm: kgsl: Fix the race between context create and destroy + +Hold the context lock before updating the context id in +param->drawctxt_id to avoid race condition between context +creation and context destroy. + +Bug: 36491445 +Change-Id: Ic26d3e5b68078c02d15c38080b1a262ea4b1f7fe +Signed-off-by: Sunil Khatri +--- + drivers/gpu/msm/kgsl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index 7186ccf6b0cb3..5fce561ae971e 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -1668,9 +1668,9 @@ long kgsl_ioctl_drawctxt_create(struct kgsl_device_private *dev_priv, + /* Commit the pointer to the context in context_idr */ + write_lock(&device->context_lock); + idr_replace(&device->context_idr, context, context->id); ++ param->drawctxt_id = context->id; + write_unlock(&device->context_lock); + +- param->drawctxt_id = context->id; + done: + return result; + } diff --git a/Patches/Linux_CVEs/CVE-2017-9684/0.patch b/Patches/Linux_CVEs/CVE-2017-9684/0.patch new file mode 100644 index 00000000..e18033bb --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9684/0.patch @@ -0,0 +1,38 @@ +From d3d636627c8bb57a64bfadcc5d282c35d152f563 Mon Sep 17 00:00:00 2001 +From: Mayank Rana +Date: Thu, 28 Aug 2014 15:11:44 -0700 +Subject: [PATCH] f_qc_rndis: Check config or cdev is NULL in before accessing + +RNDIS control path completion handlers are getting called during +disconnect as part of composition switch and this is leading to a +crash. Avoid this crash, by checking, if cdev is not NULL before +accessing. + +CRs-Fixed: 717035 +Bug: 35136547 +Change-Id: Id8748f963298129a403ffd6e4413476013315061 +Signed-off-by: Mayank Rana +--- + drivers/usb/gadget/f_qc_rndis.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c +index 3bccfe8fc5a76..dfa3dd6ed18dd 100644 +--- a/drivers/usb/gadget/f_qc_rndis.c ++++ b/drivers/usb/gadget/f_qc_rndis.c +@@ -552,7 +552,14 @@ static void rndis_qc_response_complete(struct usb_ep *ep, + { + struct f_rndis_qc *rndis = req->context; + int status = req->status; +- struct usb_composite_dev *cdev = rndis->port.func.config->cdev; ++ struct usb_composite_dev *cdev; ++ ++ if (!rndis->port.func.config || !rndis->port.func.config->cdev) { ++ pr_err("%s(): cdev or config is NULL.\n", __func__); ++ return; ++ } else { ++ cdev = rndis->port.func.config->cdev; ++ } + + /* after TX: + * - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control) diff --git a/Patches/Linux_CVEs/CVE-2017-9684/1.patch b/Patches/Linux_CVEs/CVE-2017-9684/1.patch new file mode 100644 index 00000000..fdaba97c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9684/1.patch @@ -0,0 +1,60 @@ +From 83cf9f50cda5ab3f99055242bebbcb26d96319ad Mon Sep 17 00:00:00 2001 +From: Jack Pham +Date: Wed, 6 Aug 2014 19:52:49 -0700 +Subject: [PATCH] usb: gadget: qc_rndis: Properly handle rndis_ipa_init failure + +Currently if rndis_ipa_init() fails port->func doesn't get +removed from the configuration list, and will lead to a +use-after-free when the calling function later tries to remove +the function. Fix this to handle the failure gracefully and only +call usb_add_function() if it succeeded. + +Bug: 35136547 +Change-Id: I2ad0dfeaea6b5b6ba1e47aad564ac052348677e6 +Signed-off-by: Jack Pham +--- + drivers/usb/gadget/f_qc_rndis.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c +index dfa3dd6ed18dd..819bde5072a39 100644 +--- a/drivers/usb/gadget/f_qc_rndis.c ++++ b/drivers/usb/gadget/f_qc_rndis.c +@@ -1206,25 +1206,27 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + + _rndis_qc = rndis; + ++ if (rndis->xport == USB_GADGET_XPORT_BAM2BAM_IPA) { ++ status = rndis_ipa_init(&rndis_ipa_params); ++ if (status) { ++ pr_err("%s: failed to init rndis_ipa\n", __func__); ++ goto fail; ++ } ++ } ++ + status = usb_add_function(c, &rndis->port.func); + if (status) { +- kfree(rndis); ++ if (rndis->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ++ rndis_ipa_cleanup(rndis_ipa_params.private); + goto fail; + } + + if (rndis->xport != USB_GADGET_XPORT_BAM2BAM_IPA) + return status; + +- status = rndis_ipa_init(&rndis_ipa_params); +- if (status) { +- pr_err("%s: failed to initialize rndis_ipa\n", __func__); +- kfree(rndis); +- goto fail; +- } else { +- pr_debug("%s: rndis_ipa successful created\n", __func__); +- return status; +- } + fail: ++ kfree(rndis); ++ _rndis_qc = NULL; + rndis_exit(); + return status; + } diff --git a/Patches/Linux_CVEs/CVE-2017-9684/2.patch b/Patches/Linux_CVEs/CVE-2017-9684/2.patch new file mode 100644 index 00000000..8a596b5f --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9684/2.patch @@ -0,0 +1,259 @@ +From b2fa897c8e86362946ec524ed47300164a33453d Mon Sep 17 00:00:00 2001 +From: Lena Salman +Date: Wed, 14 May 2014 10:59:58 +0300 +Subject: [PATCH] USB: f_qc_rndis: Prevent use-after-free for _rndis_qc + +Assume that there are two threads, thread1 is setting +value of _rndis_qc variable in rndis_qc_bind_config_vendor +function. Thread2 jumps in and get the value of _rndis_qc +in rndis_qc_open_dev function before it is freed in +rndis_qc_bind_config_vendor function, since rndis_ipa_init +or usb_add_function failed. Use-after-free will happen as +Thread2 is referencing freed objects. To prevent this +spinlock is used where ever it is needed to protect +_rndis_qc variable. + +Bug: 35136547 +Change-Id: Ib45ae14281821eeaf79419e8d177cb5d51b94df8 +--- + drivers/usb/gadget/f_qc_rndis.c | 105 +++++++++++++++++++++++++++++----------- + 1 file changed, 76 insertions(+), 29 deletions(-) + +diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c +index 819bde5072a39..b7f37df6921d8 100644 +--- a/drivers/usb/gadget/f_qc_rndis.c ++++ b/drivers/usb/gadget/f_qc_rndis.c +@@ -81,7 +81,7 @@ + */ + + struct f_rndis_qc { +- struct qc_gether port; ++ struct qc_gether port; + u8 ctrl_id, data_id; + u8 ethaddr[ETH_ALEN]; + u32 vendorID; +@@ -90,8 +90,8 @@ struct f_rndis_qc { + u32 max_pkt_size; + const char *manufacturer; + int config; +- atomic_t ioctl_excl; +- atomic_t open_excl; ++ atomic_t ioctl_excl; ++ atomic_t open_excl; + + struct usb_ep *notify; + struct usb_request *notify_req; +@@ -101,6 +101,7 @@ struct f_rndis_qc { + }; + + static struct ipa_usb_init_params rndis_ipa_params; ++static spinlock_t rndis_lock; + static bool rndis_ipa_supported; + static void rndis_qc_open(struct qc_gether *geth); + +@@ -548,7 +549,7 @@ static void rndis_qc_response_available(void *_rndis) + } + + static void rndis_qc_response_complete(struct usb_ep *ep, +- struct usb_request *req) ++ struct usb_request *req) + { + struct f_rndis_qc *rndis = req->context; + int status = req->status; +@@ -693,7 +694,7 @@ rndis_qc_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) + + static int rndis_qc_set_alt(struct usb_function *f, unsigned intf, unsigned alt) + { +- struct f_rndis_qc *rndis = func_to_rndis_qc(f); ++ struct f_rndis_qc *rndis = func_to_rndis_qc(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt == 0 */ +@@ -1033,6 +1034,7 @@ static void + rndis_qc_unbind(struct usb_configuration *c, struct usb_function *f) + { + struct f_rndis_qc *rndis = func_to_rndis_qc(f); ++ unsigned long flags; + + pr_debug("rndis_qc_unbind: free"); + bam_data_destroy(0); +@@ -1051,7 +1053,10 @@ rndis_qc_unbind(struct usb_configuration *c, struct usb_function *f) + rndis_ipa_supported = false; + } + ++ spin_lock_irqsave(&rndis_lock, flags); + kfree(rndis); ++ _rndis_qc = NULL; ++ spin_unlock_irqrestore(&rndis_lock, flags); + } + + bool is_rndis_ipa_supported(void) +@@ -1204,8 +1209,6 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + rndis->port.func.suspend = rndis_qc_suspend; + rndis->port.func.resume = rndis_qc_resume; + +- _rndis_qc = rndis; +- + if (rndis->xport == USB_GADGET_XPORT_BAM2BAM_IPA) { + status = rndis_ipa_init(&rndis_ipa_params); + if (status) { +@@ -1221,86 +1224,128 @@ rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + goto fail; + } + +- if (rndis->xport != USB_GADGET_XPORT_BAM2BAM_IPA) +- return status; ++ _rndis_qc = rndis; ++ ++ return status; + + fail: +- kfree(rndis); +- _rndis_qc = NULL; ++ kfree(rndis); ++ _rndis_qc = NULL; + rndis_exit(); + return status; + } + + static int rndis_qc_open_dev(struct inode *ip, struct file *fp) + { ++ int ret = 0; ++ unsigned long flags; + pr_info("Open rndis QC driver\n"); + ++ spin_lock_irqsave(&rndis_lock, flags); + if (!_rndis_qc) { + pr_err("rndis_qc_dev not created yet\n"); +- return -ENODEV; ++ ret = -ENODEV; ++ goto fail; + } + + if (rndis_qc_lock(&_rndis_qc->open_excl)) { + pr_err("Already opened\n"); +- return -EBUSY; ++ ret = -EBUSY; ++ goto fail; + } + + fp->private_data = _rndis_qc; +- pr_info("rndis QC file opened\n"); ++fail: ++ spin_unlock_irqrestore(&rndis_lock, flags); + +- return 0; ++ if (!ret) ++ pr_info("rndis QC file opened\n"); ++ ++ return ret; + } + + static int rndis_qc_release_dev(struct inode *ip, struct file *fp) + { +- struct f_rndis_qc *rndis = fp->private_data; +- ++ unsigned long flags; + pr_info("Close rndis QC file"); +- rndis_qc_unlock(&rndis->open_excl); + ++ spin_lock_irqsave(&rndis_lock, flags); ++ ++ if (!_rndis_qc) { ++ pr_err("rndis_qc_dev not present\n"); ++ spin_unlock_irqrestore(&rndis_lock, flags); ++ return -ENODEV; ++ } ++ rndis_qc_unlock(&_rndis_qc->open_excl); ++ spin_unlock_irqrestore(&rndis_lock, flags); + return 0; + } + + static long rndis_qc_ioctl(struct file *fp, unsigned cmd, unsigned long arg) + { +- struct f_rndis_qc *rndis = fp->private_data; ++ u8 qc_max_pkt_per_xfer = 0; ++ u32 qc_max_pkt_size = 0; + int ret = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&rndis_lock, flags); ++ if (!_rndis_qc) { ++ pr_err("rndis_qc_dev not present\n"); ++ ret = -ENODEV; ++ goto fail; ++ } + +- pr_info("Received command %d", cmd); ++ qc_max_pkt_per_xfer = _rndis_qc->max_pkt_per_xfer; ++ qc_max_pkt_size = _rndis_qc->max_pkt_size; + +- if (rndis_qc_lock(&rndis->ioctl_excl)) +- return -EBUSY; ++ if (rndis_qc_lock(&_rndis_qc->ioctl_excl)) { ++ ret = -EBUSY; ++ goto fail; ++ } ++ ++ spin_unlock_irqrestore(&rndis_lock, flags); ++ ++ pr_info("Received command %d\n", cmd); + + switch (cmd) { + case RNDIS_QC_GET_MAX_PKT_PER_XFER: + ret = copy_to_user((void __user *)arg, +- &rndis->max_pkt_per_xfer, +- sizeof(rndis->max_pkt_per_xfer)); ++ &qc_max_pkt_per_xfer, ++ sizeof(qc_max_pkt_per_xfer)); + if (ret) { + pr_err("copying to user space failed"); + ret = -EFAULT; + } + pr_info("Sent max packets per xfer %d", +- rndis->max_pkt_per_xfer); ++ qc_max_pkt_per_xfer); + break; + case RNDIS_QC_GET_MAX_PKT_SIZE: + ret = copy_to_user((void __user *)arg, +- &rndis->max_pkt_size, +- sizeof(rndis->max_pkt_size)); ++ &qc_max_pkt_size, ++ sizeof(qc_max_pkt_size)); + if (ret) { + pr_err("copying to user space failed"); + ret = -EFAULT; + } + pr_debug("Sent max packet size %d", +- rndis->max_pkt_size); ++ qc_max_pkt_size); + break; + default: + pr_err("Unsupported IOCTL"); + ret = -EINVAL; + } + +- rndis_qc_unlock(&rndis->ioctl_excl); ++ spin_lock_irqsave(&rndis_lock, flags); ++ ++ if (!_rndis_qc) { ++ pr_err("rndis_qc_dev not present\n"); ++ ret = -ENODEV; ++ goto fail; ++ } ++ rndis_qc_unlock(&_rndis_qc->ioctl_excl); + ++fail: ++ spin_unlock_irqrestore(&rndis_lock, flags); + return ret; + } + +@@ -1323,6 +1368,8 @@ static int rndis_qc_init(void) + + pr_info("initialize rndis QC instance\n"); + ++ spin_lock_init(&rndis_lock); ++ + ret = misc_register(&rndis_qc_device); + if (ret) + pr_err("rndis QC driver failed to register"); diff --git a/Patches/Linux_CVEs/CVE-2017-9686/0.patch b/Patches/Linux_CVEs/CVE-2017-9686/0.patch new file mode 100644 index 00000000..1b784b0b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9686/0.patch @@ -0,0 +1,193 @@ +From de875dd095d3ec0906c77518d28f793e6c69a9da Mon Sep 17 00:00:00 2001 +From: Siva Kumar Akkireddi +Date: Thu, 11 May 2017 15:29:47 +0530 +Subject: msm: sps: Fix race condition in SPS debugfs APIs + +SPS debugfs APIs can be called concurrently which can result +in dangling pointer access. This change synchronizes access +to the SPS debugfs buffer. + +Change-Id: I409b3f0618f760cb67eba47b43c81d166cdae4aa +Signed-off-by: Siva Kumar Akkireddi +--- + drivers/platform/msm/sps/sps.c | 15 ++++++++++++++- + drivers/platform/msm/sps/spsi.h | 17 ----------------- + 2 files changed, 14 insertions(+), 18 deletions(-) + +diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c +index b812960..e2abeaf 100644 +--- a/drivers/platform/msm/sps/sps.c ++++ b/drivers/platform/msm/sps/sps.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016 , The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2017, The 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 +@@ -67,6 +67,7 @@ static char *debugfs_buf; + static u32 debugfs_buf_size; + static u32 debugfs_buf_used; + static int wraparound; ++static struct mutex sps_debugfs_lock; + + struct dentry *dent; + struct dentry *dfile_info; +@@ -85,6 +86,7 @@ static struct sps_bam *phy2bam(phys_addr_t phys_addr); + /* record debug info for debugfs */ + void sps_debugfs_record(const char *msg) + { ++ mutex_lock(&sps_debugfs_lock); + if (debugfs_record_enabled) { + if (debugfs_buf_used + MAX_MSG_LEN >= debugfs_buf_size) { + debugfs_buf_used = 0; +@@ -98,6 +100,7 @@ void sps_debugfs_record(const char *msg) + debugfs_buf_size - debugfs_buf_used, + "\n**** end line of sps log ****\n\n"); + } ++ mutex_unlock(&sps_debugfs_lock); + } + + /* read the recorded debug info to userspace */ +@@ -107,6 +110,7 @@ static ssize_t sps_read_info(struct file *file, char __user *ubuf, + int ret = 0; + int size; + ++ mutex_lock(&sps_debugfs_lock); + if (debugfs_record_enabled) { + if (wraparound) + size = debugfs_buf_size - MAX_MSG_LEN; +@@ -116,6 +120,7 @@ static ssize_t sps_read_info(struct file *file, char __user *ubuf, + ret = simple_read_from_buffer(ubuf, count, ppos, + debugfs_buf, size); + } ++ mutex_unlock(&sps_debugfs_lock); + + return ret; + } +@@ -161,11 +166,13 @@ static ssize_t sps_set_info(struct file *file, const char __user *buf, + + new_buf_size = buf_size_kb * SZ_1K; + ++ mutex_lock(&sps_debugfs_lock); + if (debugfs_record_enabled) { + if (debugfs_buf_size == new_buf_size) { + /* need do nothing */ + pr_info("sps:debugfs: input buffer size " + "is the same as before.\n"); ++ mutex_unlock(&sps_debugfs_lock); + return count; + } else { + /* release the current buffer */ +@@ -185,12 +192,14 @@ static ssize_t sps_set_info(struct file *file, const char __user *buf, + if (!debugfs_buf) { + debugfs_buf_size = 0; + pr_err("sps:fail to allocate memory for debug_fs.\n"); ++ mutex_unlock(&sps_debugfs_lock); + return -ENOMEM; + } + + debugfs_buf_used = 0; + wraparound = false; + debugfs_record_enabled = true; ++ mutex_unlock(&sps_debugfs_lock); + + return count; + } +@@ -239,6 +248,7 @@ static ssize_t sps_set_logging_option(struct file *file, const char __user *buf, + return count; + } + ++ mutex_lock(&sps_debugfs_lock); + if (((option == 0) || (option == 2)) && + ((logging_option == 1) || (logging_option == 3))) { + debugfs_record_enabled = false; +@@ -250,6 +260,7 @@ static ssize_t sps_set_logging_option(struct file *file, const char __user *buf, + } + + logging_option = option; ++ mutex_unlock(&sps_debugfs_lock); + + return count; + } +@@ -587,6 +598,8 @@ static void sps_debugfs_init(void) + goto bam_log_level_err; + } + ++ mutex_init(&sps_debugfs_lock); ++ + return; + + bam_log_level_err: +diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h +index ccf761e..abf4b04 100644 +--- a/drivers/platform/msm/sps/spsi.h ++++ b/drivers/platform/msm/sps/spsi.h +@@ -145,11 +145,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } \ + } while (0) +-#define SPS_DEBUGFS(msg, args...) do { \ +- char buf[MAX_MSG_LEN]; \ +- snprintf(buf, MAX_MSG_LEN, msg"\n", ##args); \ +- sps_debugfs_record(buf); \ +- } while (0) + #define SPS_ERR(dev, msg, args...) do { \ + if (logging_option != 1) { \ + if (unlikely(print_limit_option > 2)) \ +@@ -157,8 +152,6 @@ extern u8 print_limit_option; + else \ + pr_err(msg, ##args); \ + } \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + SPS_IPC(3, dev, msg, args); \ + } while (0) + #define SPS_INFO(dev, msg, args...) do { \ +@@ -168,8 +161,6 @@ extern u8 print_limit_option; + else \ + pr_info(msg, ##args); \ + } \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + SPS_IPC(3, dev, msg, args); \ + } while (0) + #define SPS_DBG(dev, msg, args...) do { \ +@@ -181,8 +172,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } else \ + pr_debug(msg, ##args); \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + if (dev) { \ + if ((dev)->ipc_loglevel <= 0) \ + SPS_IPC(0, dev, msg, args); \ +@@ -197,8 +186,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } else \ + pr_debug(msg, ##args); \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + if (dev) { \ + if ((dev)->ipc_loglevel <= 1) \ + SPS_IPC(1, dev, msg, args); \ +@@ -213,8 +200,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } else \ + pr_debug(msg, ##args); \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + if (dev) { \ + if ((dev)->ipc_loglevel <= 2) \ + SPS_IPC(2, dev, msg, args); \ +@@ -229,8 +214,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } else \ + pr_debug(msg, ##args); \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + if (dev) { \ + if ((dev)->ipc_loglevel <= 3) \ + SPS_IPC(3, dev, msg, args); \ +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9687/0.patch b/Patches/Linux_CVEs/CVE-2017-9687/0.patch new file mode 100644 index 00000000..8ad40b53 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9687/0.patch @@ -0,0 +1,58 @@ +From 34cff2eb2adc663de32ca682b57551c50c9253c6 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Fri, 21 Apr 2017 10:42:57 -0700 +Subject: [PATCH] msm: ipa: fix IPC low priority logging + +Allocate IPC low priority on first usage only. + +Bug: 62827190 +Change-Id: Icea7f0fad9ed34c93641296f68736bbaf2e6eaa9 +CRs-Fixed: 2016076 +Acked-by: Ady Abraham +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +index 12127a2304bbc..66482e2dc0634 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +@@ -105,6 +105,7 @@ static char dbg_buff[IPA_MAX_MSG_LEN]; + static char *active_clients_buf; + + static s8 ep_reg_idx; ++static void *ipa_ipc_low_buff; + + + static ssize_t ipa3_read_gen_reg(struct file *file, char __user *ubuf, +@@ -1610,22 +1611,20 @@ static ssize_t ipa3_enable_ipc_low(struct file *file, + if (kstrtos8(dbg_buff, 0, &option)) + return -EFAULT; + ++ mutex_lock(&ipa3_ctx->lock); + if (option) { +- if (!ipa3_ctx->logbuf_low) { +- ipa3_ctx->logbuf_low = ++ if (!ipa_ipc_low_buff) { ++ ipa_ipc_low_buff = + ipc_log_context_create(IPA_IPC_LOG_PAGES, + "ipa_low", 0); + } +- +- if (ipa3_ctx->logbuf_low == NULL) { +- IPAERR("failed to get logbuf_low\n"); +- return -EFAULT; +- } ++ if (ipa_ipc_low_buff == NULL) ++ IPAERR("failed to get logbuf_low\n"); ++ ipa3_ctx->logbuf_low = ipa_ipc_low_buff; + } else { +- if (ipa3_ctx->logbuf_low) +- ipc_log_context_destroy(ipa3_ctx->logbuf_low); + ipa3_ctx->logbuf_low = NULL; + } ++ mutex_unlock(&ipa3_ctx->lock); + + return count; + } diff --git a/Patches/Linux_CVEs/CVE-2017-9691/0.patch b/Patches/Linux_CVEs/CVE-2017-9691/0.patch new file mode 100644 index 00000000..90eb2966 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9691/0.patch @@ -0,0 +1,42 @@ +From 869bd2cd3d6c17826b6f162e0d721174224b867a Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Wed, 31 May 2017 15:11:05 -0700 +Subject: [PATCH] defconfig: gud: Remove gud driver + +Disable and remove gud mobicore driver. + +Bug: 33842910 +CRs-Fixed: 1116560 +Change-Id: Ia16bc3e1331f86724a391fd367587b56ccc14546 +Acked-by: Tony Hamilton +Signed-off-by: Trudy Shearer +Signed-off-by: Dennis Cagle +--- + arch/arm64/configs/msm-auto_defconfig | 1 - + arch/arm64/configs/msm_defconfig | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig +index 9a1856e70ceeb..2839526226bac 100644 +--- a/arch/arm64/configs/msm-auto_defconfig ++++ b/arch/arm64/configs/msm-auto_defconfig +@@ -596,7 +596,6 @@ CONFIG_CORESIGHT_REMOTE_ETM=y + CONFIG_CORESIGHT_QPDI=y + CONFIG_SENSORS_SSC=y + CONFIG_MSM_TZ_LOG=y +-CONFIG_MOBICORE_DRIVER=m + CONFIG_EXT2_FS=y + CONFIG_EXT2_FS_XATTR=y + CONFIG_EXT3_FS=y +diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig +index ba053b5abfdfc..1fbbbbe876ad4 100644 +--- a/arch/arm64/configs/msm_defconfig ++++ b/arch/arm64/configs/msm_defconfig +@@ -594,7 +594,6 @@ CONFIG_CORESIGHT_REMOTE_ETM=y + CONFIG_CORESIGHT_QPDI=y + CONFIG_SENSORS_SSC=y + CONFIG_MSM_TZ_LOG=y +-CONFIG_MOBICORE_DRIVER=m + CONFIG_EXT2_FS=y + CONFIG_EXT2_FS_XATTR=y + CONFIG_EXT3_FS=y diff --git a/Patches/Linux_CVEs/CVE-2017-9691/1.patch b/Patches/Linux_CVEs/CVE-2017-9691/1.patch new file mode 100644 index 00000000..345a38c8 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9691/1.patch @@ -0,0 +1,9751 @@ +From 04468bc1d72f15e6b8f19014e8c6203038dd6b23 Mon Sep 17 00:00:00 2001 +From: Maggie White +Date: Fri, 2 Jun 2017 18:10:06 -0700 +Subject: [PATCH] msm: gud: Remove gud driver + +Complete removal of gud mobicore driver. +The driver author delivers an updated version of the driver to +interested parties directly rendering this version obsolete. + +Bug: 33842910 +CRs-Fixed: 1116560 +Change-Id: I40498d3203b1d6ca04f2b5a2e65461851d84d2d4 +Acked-by: Tony Hamilton +Signed-off-by: Trudy Shearer +Signed-off-by: Dennis Cagle +Signed-off-by: Maggie White +--- + drivers/Kconfig | 2 - + drivers/Makefile | 3 - + drivers/gud/Kconfig | 35 - + drivers/gud/Makefile | 6 - + drivers/gud/MobiCoreDriver/Makefile | 33 - + drivers/gud/MobiCoreDriver/admin.c | 1011 ------------------- + drivers/gud/MobiCoreDriver/admin.h | 32 - + drivers/gud/MobiCoreDriver/api.c | 419 -------- + drivers/gud/MobiCoreDriver/api.h | 46 - + drivers/gud/MobiCoreDriver/arm.h | 88 -- + drivers/gud/MobiCoreDriver/build_tag.h | 15 - + drivers/gud/MobiCoreDriver/client.c | 572 ----------- + drivers/gud/MobiCoreDriver/client.h | 99 -- + drivers/gud/MobiCoreDriver/clientlib.c | 433 -------- + drivers/gud/MobiCoreDriver/clock.c | 161 --- + drivers/gud/MobiCoreDriver/clock.h | 53 - + drivers/gud/MobiCoreDriver/debug.h | 63 -- + drivers/gud/MobiCoreDriver/fastcall.c | 512 ---------- + drivers/gud/MobiCoreDriver/fastcall.h | 38 - + drivers/gud/MobiCoreDriver/logging.c | 251 ----- + drivers/gud/MobiCoreDriver/logging.h | 51 - + drivers/gud/MobiCoreDriver/main.c | 750 -------------- + drivers/gud/MobiCoreDriver/main.h | 60 -- + drivers/gud/MobiCoreDriver/mci/mcifc.h | 144 --- + drivers/gud/MobiCoreDriver/mci/mcimcp.h | 508 ---------- + drivers/gud/MobiCoreDriver/mci/mcinq.h | 86 -- + drivers/gud/MobiCoreDriver/mci/mcloadformat.h | 134 --- + drivers/gud/MobiCoreDriver/mcp.c | 1067 -------------------- + drivers/gud/MobiCoreDriver/mcp.h | 121 --- + drivers/gud/MobiCoreDriver/mmu.c | 450 --------- + drivers/gud/MobiCoreDriver/mmu.h | 44 - + drivers/gud/MobiCoreDriver/platform.h | 150 --- + drivers/gud/MobiCoreDriver/pm.c | 62 -- + drivers/gud/MobiCoreDriver/pm.h | 36 - + drivers/gud/MobiCoreDriver/public/mc_admin.h | 80 -- + drivers/gud/MobiCoreDriver/public/mc_linux.h | 170 ---- + drivers/gud/MobiCoreDriver/public/mc_linux_api.h | 28 - + .../MobiCoreDriver/public/mobicore_driver_api.h | 450 --------- + drivers/gud/MobiCoreDriver/scheduler.c | 231 ----- + drivers/gud/MobiCoreDriver/scheduler.h | 25 - + drivers/gud/MobiCoreDriver/session.c | 779 -------------- + drivers/gud/MobiCoreDriver/session.h | 63 -- + drivers/gud/setupDrivers.sh | 19 - + 43 files changed, 9380 deletions(-) + delete mode 100644 drivers/gud/Kconfig + delete mode 100644 drivers/gud/Makefile + delete mode 100644 drivers/gud/MobiCoreDriver/Makefile + delete mode 100644 drivers/gud/MobiCoreDriver/admin.c + delete mode 100644 drivers/gud/MobiCoreDriver/admin.h + delete mode 100644 drivers/gud/MobiCoreDriver/api.c + delete mode 100644 drivers/gud/MobiCoreDriver/api.h + delete mode 100644 drivers/gud/MobiCoreDriver/arm.h + delete mode 100644 drivers/gud/MobiCoreDriver/build_tag.h + delete mode 100644 drivers/gud/MobiCoreDriver/client.c + delete mode 100644 drivers/gud/MobiCoreDriver/client.h + delete mode 100644 drivers/gud/MobiCoreDriver/clientlib.c + delete mode 100644 drivers/gud/MobiCoreDriver/clock.c + delete mode 100644 drivers/gud/MobiCoreDriver/clock.h + delete mode 100644 drivers/gud/MobiCoreDriver/debug.h + delete mode 100644 drivers/gud/MobiCoreDriver/fastcall.c + delete mode 100644 drivers/gud/MobiCoreDriver/fastcall.h + delete mode 100644 drivers/gud/MobiCoreDriver/logging.c + delete mode 100644 drivers/gud/MobiCoreDriver/logging.h + delete mode 100644 drivers/gud/MobiCoreDriver/main.c + delete mode 100644 drivers/gud/MobiCoreDriver/main.h + delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcifc.h + delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcimcp.h + delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcinq.h + delete mode 100644 drivers/gud/MobiCoreDriver/mci/mcloadformat.h + delete mode 100644 drivers/gud/MobiCoreDriver/mcp.c + delete mode 100644 drivers/gud/MobiCoreDriver/mcp.h + delete mode 100644 drivers/gud/MobiCoreDriver/mmu.c + delete mode 100644 drivers/gud/MobiCoreDriver/mmu.h + delete mode 100644 drivers/gud/MobiCoreDriver/platform.h + delete mode 100644 drivers/gud/MobiCoreDriver/pm.c + delete mode 100644 drivers/gud/MobiCoreDriver/pm.h + delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_admin.h + delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_linux.h + delete mode 100644 drivers/gud/MobiCoreDriver/public/mc_linux_api.h + delete mode 100644 drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h + delete mode 100644 drivers/gud/MobiCoreDriver/scheduler.c + delete mode 100644 drivers/gud/MobiCoreDriver/scheduler.h + delete mode 100644 drivers/gud/MobiCoreDriver/session.c + delete mode 100644 drivers/gud/MobiCoreDriver/session.h + delete mode 100644 drivers/gud/setupDrivers.sh + +diff --git a/drivers/Kconfig b/drivers/Kconfig +index 0e7c68c62542a..8b796ec00009e 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -200,8 +200,6 @@ source "drivers/firmware/Kconfig" + + source "drivers/bif/Kconfig" + +-source "drivers/gud/Kconfig" +- + source "drivers/htc_mnemosyne/Kconfig" + + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index fb0cd18143ad5..13236262a1857 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -171,9 +171,6 @@ obj-$(CONFIG_BIF) += bif/ + + obj-$(CONFIG_SENSORS_SSC) += sensors/ + +-# +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +-#include "public/mc_admin.h" +- +-#include "mci/mcloadformat.h" +- +-#include "main.h" +-#include "debug.h" +-#include "mmu.h" /* For load_check and load_token */ +-#include "mcp.h" +-#include "client.h" +-#include "api.h" +-#include "admin.h" +- +-/* We need 2 devices for admin and user interface*/ +-#define MC_DEV_MAX 2 +- +-static struct admin_ctx { +- struct device *dev; +- atomic_t daemon_counter; +- /* Define a MobiCore device structure for use with dev_debug() etc */ +- struct device_driver mc_dev_name; +- dev_t mc_dev_admin; +- struct cdev mc_admin_cdev; +- int (*tee_start_cb)(void); +-} g_admin_ctx; +- +-static struct mc_admin_driver_request { +- /* Global */ +- struct mutex mutex; /* Protects access to this struct */ +- struct mutex states_mutex; /* Protect access to the states */ +- enum client_state { +- IDLE, +- REQUEST_SENT, +- BUFFERS_READY, +- } client_state; +- enum server_state { +- NOT_CONNECTED, /* Device not open */ +- READY, /* Waiting for requests */ +- REQUEST_RECEIVED, /* Got a request, is working */ +- RESPONSE_SENT, /* Has sent a response header */ +- DATA_SENT, /* Blocked until data is consumed */ +- } server_state; +- /* Request */ +- uint32_t request_id; +- struct mc_admin_request request; +- struct completion client_complete; +- /* Response */ +- struct mc_admin_response response; +- struct completion server_complete; +- void *buffer; /* Reception buffer (pre-allocated) */ +- size_t size; /* Size of the reception buffer */ +-} g_request; +- +-static struct tbase_object *tbase_object_alloc(bool is_sp_trustlet, +- size_t length) +-{ +- struct tbase_object *obj; +- size_t size = sizeof(*obj) + length; +- size_t header_length = 0; +- +- /* Determine required size */ +- if (is_sp_trustlet) { +- /* Need space for lengths info and containers */ +- header_length = sizeof(struct mc_blob_len_info); +- size += header_length + 3 * MAX_SO_CONT_SIZE; +- } +- +- /* Allocate memory */ +- obj = vzalloc(size); +- if (!obj) +- return NULL; +- +- /* A non-zero header_length indicates that we have a SP trustlet */ +- obj->header_length = header_length; +- obj->length = length; +- return obj; +-} +- +-void tbase_object_free(struct tbase_object *robj) +-{ +- vfree(robj); +-} +- +-static inline void client_state_change(enum client_state state) +-{ +- mutex_lock(&g_request.states_mutex); +- g_request.client_state = state; +- mutex_unlock(&g_request.states_mutex); +-} +- +-static inline bool client_state_is(enum client_state state) +-{ +- bool is; +- +- mutex_lock(&g_request.states_mutex); +- is = g_request.client_state == state; +- mutex_unlock(&g_request.states_mutex); +- return is; +-} +- +-static inline void server_state_change(enum server_state state) +-{ +- mutex_lock(&g_request.states_mutex); +- g_request.server_state = state; +- mutex_unlock(&g_request.states_mutex); +-} +- +-static inline bool server_state_is(enum server_state state) +-{ +- bool is; +- +- mutex_lock(&g_request.states_mutex); +- is = g_request.server_state == state; +- mutex_unlock(&g_request.states_mutex); +- return is; +-} +- +-static void request_cancel(void); +- +-static int request_send(uint32_t command, const struct mc_uuid_t *uuid, +- uint32_t is_gp, uint32_t spid) +-{ +- struct device *dev = g_admin_ctx.dev; +- int counter = 10; +- int ret; +- +- /* Prepare request */ +- mutex_lock(&g_request.states_mutex); +- /* Wait a little for daemon to connect */ +- while ((g_request.server_state == NOT_CONNECTED) && counter--) { +- mutex_unlock(&g_request.states_mutex); +- ssleep(1); +- mutex_lock(&g_request.states_mutex); +- } +- +- BUG_ON(g_request.client_state != IDLE); +- if (g_request.server_state != READY) { +- mutex_unlock(&g_request.states_mutex); +- if (g_request.server_state != NOT_CONNECTED) { +- /* TODO: can we recover? */ +- dev_err(dev, "%s: invalid daemon state %d\n", __func__, +- g_request.server_state); +- ret = -EPROTO; +- goto end; +- } else { +- dev_err(dev, "%s: daemon not connected\n", __func__); +- ret = -ENOTCONN; +- goto end; +- } +- } +- +- memset(&g_request.request, 0, sizeof(g_request.request)); +- memset(&g_request.response, 0, sizeof(g_request.response)); +- g_request.request.request_id = g_request.request_id++; +- g_request.request.command = command; +- if (uuid) +- memcpy(&g_request.request.uuid, uuid, sizeof(*uuid)); +- else +- memset(&g_request.request.uuid, 0, sizeof(*uuid)); +- +- g_request.request.is_gp = is_gp; +- g_request.request.spid = spid; +- g_request.client_state = REQUEST_SENT; +- mutex_unlock(&g_request.states_mutex); +- +- /* Send request */ +- complete(&g_request.client_complete); +- +- /* Wait for header (could be interruptible, but then needs more work) */ +- wait_for_completion(&g_request.server_complete); +- +- /* Server should be waiting with some data for us */ +- mutex_lock(&g_request.states_mutex); +- switch (g_request.server_state) { +- case NOT_CONNECTED: +- /* Daemon gone */ +- ret = -EPIPE; +- break; +- case READY: +- /* No data to come, likely an error */ +- ret = -g_request.response.error_no; +- break; +- case RESPONSE_SENT: +- case DATA_SENT: +- /* Normal case, data to come */ +- ret = 0; +- break; +- default: +- /* Should not happen as complete means the state changed */ +- dev_err(dev, "%s: daemon is in a bad state: %d\n", __func__, +- g_request.server_state); +- ret = -EPIPE; +- break; +- } +- +- mutex_unlock(&g_request.states_mutex); +- +-end: +- if (ret) +- request_cancel(); +- +- return ret; +-} +- +-static int request_receive(void *address, uint32_t size) +-{ +- /* +- * At this point we have received the header and prepared some buffers +- * to receive data that we know are coming from the server. +- */ +- +- /* Check server state */ +- bool server_ok; +- +- mutex_lock(&g_request.states_mutex); +- server_ok = (g_request.server_state == RESPONSE_SENT) || +- (g_request.server_state == DATA_SENT); +- mutex_unlock(&g_request.states_mutex); +- if (!server_ok) { +- /* TODO: can we recover? */ +- request_cancel(); +- return -EPIPE; +- } +- +- /* Setup reception buffer */ +- g_request.buffer = address; +- g_request.size = size; +- client_state_change(BUFFERS_READY); +- +- /* Unlock write of data */ +- complete(&g_request.client_complete); +- +- /* Wait for data (far too late to be interruptible) */ +- wait_for_completion(&g_request.server_complete); +- +- /* Reset reception buffer */ +- g_request.buffer = NULL; +- g_request.size = 0; +- +- /* Return to idle state */ +- client_state_change(IDLE); +- return 0; +-} +- +-/* Must be called instead of request_receive() to cancel a pending request */ +-static void request_cancel(void) +-{ +- /* Unlock write of data */ +- mutex_lock(&g_request.states_mutex); +- if (g_request.server_state == DATA_SENT) +- complete(&g_request.client_complete); +- +- /* Return to idle state */ +- g_request.client_state = IDLE; +- mutex_unlock(&g_request.states_mutex); +-} +- +-static int admin_get_root_container(void *address) +-{ +- struct device *dev = g_admin_ctx.dev; +- int ret = 0; +- +- /* Lock communication channel */ +- mutex_lock(&g_request.mutex); +- +- /* Send request and wait for header */ +- ret = request_send(MC_DRV_GET_ROOT_CONTAINER, 0, 0, 0); +- if (ret) +- goto end; +- +- /* Check length against max */ +- if (g_request.response.length >= MAX_SO_CONT_SIZE) { +- request_cancel(); +- dev_err(dev, "%s: response length exceeds maximum\n", __func__); +- ret = EREMOTEIO; +- goto end; +- } +- +- /* Get data */ +- ret = request_receive(address, g_request.response.length); +- if (!ret) +- ret = g_request.response.length; +- +-end: +- mutex_unlock(&g_request.mutex); +- return ret; +-} +- +-static int admin_get_sp_container(void *address, uint32_t spid) +-{ +- struct device *dev = g_admin_ctx.dev; +- int ret = 0; +- +- /* Lock communication channel */ +- mutex_lock(&g_request.mutex); +- +- /* Send request and wait for header */ +- ret = request_send(MC_DRV_GET_SP_CONTAINER, 0, 0, spid); +- if (ret) +- goto end; +- +- /* Check length against max */ +- if (g_request.response.length >= MAX_SO_CONT_SIZE) { +- request_cancel(); +- dev_err(dev, "%s: response length exceeds maximum\n", __func__); +- ret = EREMOTEIO; +- goto end; +- } +- +- /* Get data */ +- ret = request_receive(address, g_request.response.length); +- if (!ret) +- ret = g_request.response.length; +- +-end: +- mutex_unlock(&g_request.mutex); +- return ret; +-} +- +-static int admin_get_trustlet_container(void *address, +- const struct mc_uuid_t *uuid, +- uint32_t spid) +-{ +- struct device *dev = g_admin_ctx.dev; +- int ret = 0; +- +- /* Lock communication channel */ +- mutex_lock(&g_request.mutex); +- +- /* Send request and wait for header */ +- ret = request_send(MC_DRV_GET_TRUSTLET_CONTAINER, uuid, 0, spid); +- if (ret) +- goto end; +- +- /* Check length against max */ +- if (g_request.response.length >= MAX_SO_CONT_SIZE) { +- request_cancel(); +- dev_err(dev, "%s: response length exceeds maximum\n", __func__); +- ret = EREMOTEIO; +- goto end; +- } +- +- /* Get data */ +- ret = request_receive(address, g_request.response.length); +- if (!ret) +- ret = g_request.response.length; +- +-end: +- mutex_unlock(&g_request.mutex); +- return ret; +-} +- +-static struct tbase_object *admin_get_trustlet(const struct mc_uuid_t *uuid, +- uint32_t is_gp, uint32_t *spid) +-{ +- struct tbase_object *obj = NULL; +- bool is_sp_tl; +- int ret = 0; +- +- /* Lock communication channel */ +- mutex_lock(&g_request.mutex); +- +- /* Send request and wait for header */ +- ret = request_send(MC_DRV_GET_TRUSTLET, uuid, is_gp, 0); +- if (ret) +- goto end; +- +- /* Allocate memory */ +- is_sp_tl = g_request.response.service_type == SERVICE_TYPE_SP_TRUSTLET; +- obj = tbase_object_alloc(is_sp_tl, g_request.response.length); +- if (!obj) { +- request_cancel(); +- ret = -ENOMEM; +- goto end; +- } +- +- /* Get data */ +- ret = request_receive(&obj->data[obj->header_length], obj->length); +- *spid = g_request.response.spid; +- +-end: +- mutex_unlock(&g_request.mutex); +- if (ret) +- return ERR_PTR(ret); +- +- return obj; +-} +- +-static void mc_admin_sendcrashdump(void) +-{ +- int ret = 0; +- +- /* Lock communication channel */ +- mutex_lock(&g_request.mutex); +- +- /* Send request and wait for header */ +- ret = request_send(MC_DRV_SIGNAL_CRASH, NULL, false, 0); +- if (ret) +- goto end; +- +- /* Done */ +- request_cancel(); +- +-end: +- mutex_unlock(&g_request.mutex); +-} +- +-static int tbase_object_make(uint32_t spid, struct tbase_object *obj) +-{ +- struct mc_blob_len_info *l_info = (struct mc_blob_len_info *)obj->data; +- uint8_t *address = &obj->data[obj->header_length + obj->length]; +- struct mclf_header_v2 *thdr; +- int ret; +- +- /* Get root container */ +- ret = admin_get_root_container(address); +- if (ret < 0) +- goto err; +- +- l_info->root_size = ret; +- address += ret; +- +- /* Get SP container */ +- ret = admin_get_sp_container(address, spid); +- if (ret < 0) +- goto err; +- +- l_info->sp_size = ret; +- address += ret; +- +- /* Get trustlet container */ +- thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length]; +- ret = admin_get_trustlet_container(address, &thdr->uuid, spid); +- if (ret < 0) +- goto err; +- +- l_info->ta_size = ret; +- address += ret; +- +- /* Setup lengths information */ +- l_info->magic = MC_TLBLOBLEN_MAGIC; +- obj->length += sizeof(*l_info); +- obj->length += l_info->root_size + l_info->sp_size + l_info->ta_size; +- ret = 0; +- +-err: +- return ret; +-} +- +-struct tbase_object *tbase_object_read(uint32_t spid, uintptr_t address, +- size_t length) +-{ +- struct device *dev = g_admin_ctx.dev; +- char __user *addr = (char __user *)address; +- struct tbase_object *obj; +- uint8_t *data; +- struct mclf_header_v2 thdr; +- int ret; +- +- /* Check length */ +- if (length < sizeof(thdr)) { +- dev_err(dev, "%s: buffer shorter than header size\n", __func__); +- return ERR_PTR(-EFAULT); +- } +- +- /* Read header */ +- if (copy_from_user(&thdr, addr, sizeof(thdr))) { +- dev_err(dev, "%s: header: copy_from_user failed\n", __func__); +- return ERR_PTR(-EFAULT); +- } +- +- /* Allocate memory */ +- obj = tbase_object_alloc(thdr.service_type == SERVICE_TYPE_SP_TRUSTLET, +- length); +- if (!obj) +- return ERR_PTR(-ENOMEM); +- +- /* Copy header */ +- data = &obj->data[obj->header_length]; +- memcpy(data, &thdr, sizeof(thdr)); +- /* Copy the rest of the data */ +- data += sizeof(thdr); +- if (copy_from_user(data, &addr[sizeof(thdr)], length - sizeof(thdr))) { +- dev_err(dev, "%s: data: copy_from_user failed\n", __func__); +- vfree(obj); +- return ERR_PTR(-EFAULT); +- } +- +- if (obj->header_length) { +- ret = tbase_object_make(spid, obj); +- if (ret) { +- vfree(obj); +- return ERR_PTR(ret); +- } +- } +- +- return obj; +-} +- +-struct tbase_object *tbase_object_select(const struct mc_uuid_t *uuid) +-{ +- struct tbase_object *obj; +- struct mclf_header_v2 *thdr; +- +- obj = tbase_object_alloc(false, sizeof(*thdr)); +- if (!obj) +- return ERR_PTR(-ENOMEM); +- +- thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length]; +- memcpy(&thdr->uuid, uuid, sizeof(thdr->uuid)); +- return obj; +-} +- +-struct tbase_object *tbase_object_get(const struct mc_uuid_t *uuid, +- uint32_t is_gp_uuid) +-{ +- struct tbase_object *obj; +- uint32_t spid = 0; +- +- /* admin_get_trustlet creates the right object based on service type */ +- obj = admin_get_trustlet(uuid, is_gp_uuid, &spid); +- if (IS_ERR(obj)) +- return obj; +- +- /* SP trustlet: create full secure object with all containers */ +- if (obj->header_length) { +- int ret; +- +- /* Do not return EINVAL in this case as SPID was not found */ +- if (!spid) { +- vfree(obj); +- return ERR_PTR(-ENOENT); +- } +- +- ret = tbase_object_make(spid, obj); +- if (ret) { +- vfree(obj); +- return ERR_PTR(ret); +- } +- } +- +- return obj; +-} +- +-static inline int load_driver(struct tbase_client *client, +- struct mc_admin_load_info *info) +-{ +- struct tbase_object *obj; +- struct mclf_header_v2 *thdr; +- struct mc_identity identity = { +- .login_type = TEEC_LOGIN_PUBLIC, +- }; +- uintptr_t dci = 0; +- uint32_t dci_len = 0; +- uint32_t sid; +- int ret; +- +- obj = tbase_object_read(info->spid, info->address, info->length); +- if (IS_ERR(obj)) +- return PTR_ERR(obj); +- +- thdr = (struct mclf_header_v2 *)&obj->data[obj->header_length]; +- if (!(thdr->flags & MC_SERVICE_HEADER_FLAGS_NO_CONTROL_INTERFACE)) { +- /* +- * The driver requires a DCI, although we won't be able to use +- * it to communicate. +- */ +- dci_len = PAGE_SIZE; +- ret = api_malloc_cbuf(client, dci_len, &dci, NULL); +- if (ret) +- goto end; +- } +- +- /* Open session */ +- ret = client_add_session(client, obj, dci, dci_len, &sid, false, +- &identity); +- if (ret) +- api_free_cbuf(client, dci); +- else +- dev_dbg(g_admin_ctx.dev, "driver loaded with sid %x", sid); +- +-end: +- vfree(obj); +- return ret; +-} +- +-static inline int load_token(struct mc_admin_load_info *token) +-{ +- struct tbase_mmu *mmu; +- struct mcp_buffer_map map; +- int ret; +- +- mmu = tbase_mmu_create(current, (void *)(uintptr_t)token->address, +- token->length); +- if (IS_ERR(mmu)) +- return PTR_ERR(mmu); +- +- tbase_mmu_buffer(mmu, &map); +- ret = mcp_load_token(token->address, &map); +- tbase_mmu_delete(mmu); +- return ret; +-} +- +-static inline int load_check(struct mc_admin_load_info *info) +-{ +- struct tbase_object *obj; +- struct tbase_mmu *mmu; +- struct mcp_buffer_map map; +- int ret; +- +- obj = tbase_object_read(info->spid, info->address, info->length); +- if (IS_ERR(obj)) +- return PTR_ERR(obj); +- +- mmu = tbase_mmu_create(NULL, obj->data, obj->length); +- if (IS_ERR(mmu)) +- return PTR_ERR(mmu); +- +- tbase_mmu_buffer(mmu, &map); +- ret = mcp_load_check(obj, &map); +- tbase_mmu_delete(mmu); +- return ret; +-} +- +-static ssize_t admin_write(struct file *file, const char __user *user, +- size_t len, loff_t *off) +-{ +- int ret; +- +- /* No offset allowed [yet] */ +- if (*off) { +- g_request.response.error_no = EPIPE; +- ret = -ECOMM; +- goto err; +- } +- +- if (server_state_is(REQUEST_RECEIVED)) { +- /* Check client state */ +- if (!client_state_is(REQUEST_SENT)) { +- g_request.response.error_no = EPIPE; +- ret = -EPIPE; +- goto err; +- } +- +- /* Receive response header */ +- if (copy_from_user(&g_request.response, user, +- sizeof(g_request.response))) { +- g_request.response.error_no = EPIPE; +- ret = -ECOMM; +- goto err; +- } +- +- /* Check request ID */ +- if (g_request.request.request_id != +- g_request.response.request_id) { +- g_request.response.error_no = EPIPE; +- ret = -EBADE; +- goto err; +- } +- +- /* Response header is acceptable */ +- ret = sizeof(g_request.response); +- if (g_request.response.length) +- server_state_change(RESPONSE_SENT); +- else +- server_state_change(READY); +- +- goto end; +- } else if (server_state_is(RESPONSE_SENT)) { +- /* Server is waiting */ +- server_state_change(DATA_SENT); +- +- /* Get data */ +- ret = wait_for_completion_interruptible( +- &g_request.client_complete); +- +- /* Server received a signal, let see if it tries again */ +- if (ret) { +- server_state_change(RESPONSE_SENT); +- return ret; +- } +- +- /* Check client state */ +- if (!client_state_is(BUFFERS_READY)) { +- g_request.response.error_no = EPIPE; +- ret = -EPIPE; +- goto err; +- } +- +- /* TODO deal with several writes */ +- if (len != g_request.size) +- len = g_request.size; +- +- ret = copy_from_user(g_request.buffer, user, len); +- if (ret) { +- g_request.response.error_no = EPIPE; +- ret = -ECOMM; +- goto err; +- } +- +- ret = len; +- server_state_change(READY); +- goto end; +- } else { +- ret = -ECOMM; +- goto err; +- } +- +-err: +- server_state_change(READY); +-end: +- complete(&g_request.server_complete); +- return ret; +-} +- +-static long admin_ioctl(struct file *file, unsigned int cmd, +- unsigned long arg) +-{ +- struct tbase_client *client = file->private_data; +- void __user *uarg = (void __user *)arg; +- int ret = -EINVAL; +- +- MCDRV_DBG("%u from %s", _IOC_NR(cmd), current->comm); +- +- if (WARN(!client, "No client data available")) +- return -EFAULT; +- +- switch (cmd) { +- case MC_ADMIN_IO_GET_DRIVER_REQUEST: { +- /* Block until a request is available */ +- ret = wait_for_completion_interruptible( +- &g_request.client_complete); +- if (ret) +- /* Interrupted by signal */ +- break; +- +- /* Check client state */ +- if (!client_state_is(REQUEST_SENT)) { +- g_request.response.error_no = EPIPE; +- complete(&g_request.server_complete); +- ret = -EPIPE; +- break; +- } +- +- /* Send request (the driver request mutex is held) */ +- ret = copy_to_user(uarg, &g_request.request, +- sizeof(g_request.request)); +- if (ret) { +- server_state_change(READY); +- complete(&g_request.server_complete); +- ret = -EPROTO; +- break; +- } +- +- server_state_change(REQUEST_RECEIVED); +- break; +- } +- case MC_ADMIN_IO_GET_INFO: { +- struct mc_admin_driver_info info; +- +- info.drv_version = MC_VERSION(MCDRVMODULEAPI_VERSION_MAJOR, +- MCDRVMODULEAPI_VERSION_MINOR); +- info.initial_cmd_id = g_request.request_id; +- ret = copy_to_user(uarg, &info, sizeof(info)); +- break; +- } +- case MC_ADMIN_IO_LOAD_DRIVER: { +- struct mc_admin_load_info info; +- +- ret = copy_from_user(&info, uarg, sizeof(info)); +- if (ret) +- ret = -EFAULT; +- else +- ret = load_driver(client, &info); +- +- break; +- } +- case MC_ADMIN_IO_LOAD_TOKEN: { +- struct mc_admin_load_info info; +- +- ret = copy_from_user(&info, uarg, sizeof(info)); +- if (ret) +- ret = -EFAULT; +- else +- ret = load_token(&info); +- +- break; +- } +- case MC_ADMIN_IO_LOAD_CHECK: { +- struct mc_admin_load_info info; +- +- ret = copy_from_user(&info, uarg, sizeof(info)); +- if (ret) +- ret = -EFAULT; +- else +- ret = load_check(&info); +- +- break; +- } +- default: +- ret = -ENOIOCTLCMD; +- } +- +- return ret; +-} +- +-/* +- * mc_fd_release() - This function will be called from user space as close(...) +- * The client data are freed and the associated memory pages are unreserved. +- * +- * @inode +- * @file +- * +- * Returns 0 +- */ +-static int admin_release(struct inode *inode, struct file *file) +-{ +- struct tbase_client *client = file->private_data; +- struct device *dev = g_admin_ctx.dev; +- +- if (!client) +- return -EPROTO; +- +- api_close_device(client); +- file->private_data = NULL; +- +- /* Requests from driver to daemon */ +- mutex_lock(&g_request.states_mutex); +- dev_warn(dev, "%s: daemon disconnected\n", __func__); +- g_request.server_state = NOT_CONNECTED; +- /* A non-zero command indicates that a thread is waiting */ +- if (g_request.client_state != IDLE) { +- g_request.response.error_no = ESHUTDOWN; +- complete(&g_request.server_complete); +- } +- +- mutex_unlock(&g_request.states_mutex); +- atomic_set(&g_admin_ctx.daemon_counter, 0); +- /* +- * ret is quite irrelevant here as most apps don't care about the +- * return value from close() and it's quite difficult to recover +- */ +- return 0; +-} +- +-static int admin_open(struct inode *inode, struct file *file) +-{ +- struct device *dev = g_admin_ctx.dev; +- struct tbase_client *client; +- int err; +- +- /* +- * If the daemon is already set we can't allow anybody else to open +- * the admin interface. +- */ +- if (atomic_cmpxchg(&g_admin_ctx.daemon_counter, 0, 1) != 0) { +- MCDRV_ERROR("Daemon is already connected"); +- return -EPROTO; +- } +- +- /* Any value will do */ +- g_request.request_id = 42; +- +- /* Setup the usual variables */ +- MCDRV_DBG("accept %s as tbase daemon", current->comm); +- +- /* +- * daemon is connected so now we can safely suppose +- * the secure world is loaded too +- */ +- if (!IS_ERR_OR_NULL(g_admin_ctx.tee_start_cb)) +- g_admin_ctx.tee_start_cb = ERR_PTR(g_admin_ctx.tee_start_cb()); +- if (IS_ERR(g_admin_ctx.tee_start_cb)) { +- MCDRV_ERROR("Failed initializing the SW"); +- err = PTR_ERR(g_admin_ctx.tee_start_cb); +- goto fail_connection; +-} +- +- /* Create client */ +- client = api_open_device(true); +- if (!client) { +- err = -ENOMEM; +- goto fail_connection; +- } +- +- /* Store client in user file */ +- file->private_data = client; +- +- /* Requests from driver to daemon */ +- server_state_change(READY); +- dev_info(dev, "%s: daemon connected\n", __func__); +- +- return 0; +- +-fail_connection: +- atomic_set(&g_admin_ctx.daemon_counter, 0); +- return err; +-} +- +-/* function table structure of this device driver. */ +-static const struct file_operations mc_admin_fops = { +- .owner = THIS_MODULE, +- .open = admin_open, +- .release = admin_release, +- .unlocked_ioctl = admin_ioctl, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = admin_ioctl, +-#endif +- .write = admin_write, +-}; +- +-int mc_admin_init(struct class *mc_device_class, dev_t *out_dev, +- int (*tee_start_cb)(void)) +-{ +- int err = 0; +- +- if (!out_dev || !mc_device_class) +- return -EINVAL; +- +- atomic_set(&g_admin_ctx.daemon_counter, 0); +- +- /* Requests from driver to daemon */ +- mutex_init(&g_request.mutex); +- mutex_init(&g_request.states_mutex); +- init_completion(&g_request.client_complete); +- init_completion(&g_request.server_complete); +- mcp_register_crashhandler(mc_admin_sendcrashdump); +- +- /* Create char device */ +- cdev_init(&g_admin_ctx.mc_admin_cdev, &mc_admin_fops); +- err = alloc_chrdev_region(&g_admin_ctx.mc_dev_admin, 0, MC_DEV_MAX, +- "trustonic_tee"); +- if (err < 0) { +- MCDRV_ERROR("failed to allocate char dev region"); +- goto fail_alloc_chrdev_region; +- } +- +- err = cdev_add(&g_admin_ctx.mc_admin_cdev, g_admin_ctx.mc_dev_admin, 1); +- if (err) { +- MCDRV_ERROR("admin device register failed"); +- goto fail_cdev_add; +- } +- +- g_admin_ctx.mc_admin_cdev.owner = THIS_MODULE; +- g_admin_ctx.dev = device_create(mc_device_class, NULL, +- g_admin_ctx.mc_dev_admin, NULL, +- MC_ADMIN_DEVNODE); +- if (IS_ERR(g_admin_ctx.dev)) { +- err = PTR_ERR(g_admin_ctx.dev); +- goto fail_dev_create; +- } +- +- g_admin_ctx.mc_dev_name.name = "driver = &g_admin_ctx.mc_dev_name; +- *out_dev = g_admin_ctx.mc_dev_admin; +- +- /* Register the call back for starting the secure world */ +- g_admin_ctx.tee_start_cb = tee_start_cb; +- +- MCDRV_DBG("done"); +- return 0; +- +-fail_dev_create: +- cdev_del(&g_admin_ctx.mc_admin_cdev); +- +-fail_cdev_add: +- unregister_chrdev_region(g_admin_ctx.mc_dev_admin, MC_DEV_MAX); +- +-fail_alloc_chrdev_region: +- MCDRV_ERROR("fail with %d", err); +- return err; +-} +- +-void mc_admin_exit(struct class *mc_device_class) +-{ +- device_destroy(mc_device_class, g_admin_ctx.mc_dev_admin); +- cdev_del(&g_admin_ctx.mc_admin_cdev); +- unregister_chrdev_region(g_admin_ctx.mc_dev_admin, MC_DEV_MAX); +- /* Requests from driver to daemon */ +- mutex_destroy(&g_request.states_mutex); +- MCDRV_DBG("done"); +-} +diff --git a/drivers/gud/MobiCoreDriver/admin.h b/drivers/gud/MobiCoreDriver/admin.h +deleted file mode 100644 +index 5a78d943752da..0000000000000 +--- a/drivers/gud/MobiCoreDriver/admin.h ++++ /dev/null +@@ -1,32 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef ADMIN_FD_H_ +-#define ADMIN_FD_H_ +- +-struct mc_uuid_t; +-struct tbase_object; +- +-int mc_admin_init(struct class *mc_device_class, dev_t *out_dev, +- int (*tee_start_cb)(void)); +-void mc_admin_exit(struct class *mc_device_class); +- +-struct tbase_object *tbase_object_select(const struct mc_uuid_t *uuid); +-struct tbase_object *tbase_object_get(const struct mc_uuid_t *uuid, +- uint32_t is_gp_uuid); +-struct tbase_object *tbase_object_read(uint32_t spid, uintptr_t address, +- size_t length); +-void tbase_object_free(struct tbase_object *out_robj); +- +-#endif /* ADMIN_FD_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/api.c b/drivers/gud/MobiCoreDriver/api.c +deleted file mode 100644 +index 0d2abaf617aea..0000000000000 +--- a/drivers/gud/MobiCoreDriver/api.c ++++ /dev/null +@@ -1,419 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include /* MC_MAP_MAX */ +-#include "main.h" +-#include "debug.h" +-#include "mcp.h" +-#include "admin.h" +-#include "session.h" +-#include "client.h" +-#include "api.h" +- +-static struct api_ctx { +- struct mutex clients_lock; /* Clients list + temp notifs */ +- struct list_head clients; /* List of user-space clients */ +-} api_ctx; +- +-/* +- * Initialize a new tbase client object +- * @return client pointer or NULL if no allocation was possible. +- */ +-struct tbase_client *api_open_device(bool is_from_kernel) +-{ +- struct tbase_client *client; +- +- /* Allocate and init client object */ +- client = client_create(is_from_kernel); +- if (!client) { +- MCDRV_ERROR("Could not create client"); +- return NULL; +- } +- +- /* Add client to list of clients */ +- mutex_lock(&api_ctx.clients_lock); +- list_add_tail(&client->list, &api_ctx.clients); +- mutex_unlock(&api_ctx.clients_lock); +- +- MCDRV_DBG("created client %p", client); +- return client; +-} +- +-/* +- * Try and mark client as "closing" +- * @return tbase driver error code +- */ +-int api_freeze_device(struct tbase_client *client) +-{ +- int err = 0; +- +- if (!client_set_closing(client)) +- err = -ENOTEMPTY; +- +- MCDRV_DBG("client %p, exit with %d\n", client, err); +- return err; +-} +- +-/* +- * Release a client and the session+cbuf objects it contains. +- * @param client_t client +- * @return tbase driver error code +- */ +-void api_close_device(struct tbase_client *client) +-{ +- /* Remove client from list of active clients */ +- mutex_lock(&api_ctx.clients_lock); +- list_del(&client->list); +- mutex_unlock(&api_ctx.clients_lock); +- /* Close all remaining sessions */ +- client_close_sessions(client); +- client_put(client); +- MCDRV_DBG("client %p closed\n", client); +-} +- +-/* +- * Open TA for given client. TA binary is provided by the daemon. +- * @param +- * @return tbase driver error code +- */ +-int api_open_session(struct tbase_client *client, +- uint32_t *p_session_id, +- const struct mc_uuid_t *uuid, +- uintptr_t tci, +- size_t tci_len, +- bool is_gp_uuid, +- struct mc_identity *identity) +-{ +- int err = 0; +- uint32_t sid = 0; +- struct tbase_object *obj; +- +- /* Check parameters */ +- if (!p_session_id) +- return -EINVAL; +- +- if (!uuid) +- return -EINVAL; +- +- /* Get secure object */ +- obj = tbase_object_get(uuid, is_gp_uuid); +- if (IS_ERR(obj)) { +- /* Try to select secure object inside the SWd if not found */ +- if ((PTR_ERR(obj) == -ENOENT) && g_ctx.f_ta_auth) +- obj = tbase_object_select(uuid); +- +- if (IS_ERR(obj)) { +- err = PTR_ERR(obj); +- goto end; +- } +- } +- +- /* Open session */ +- err = client_add_session(client, obj, tci, tci_len, &sid, is_gp_uuid, +- identity); +- /* Fill in return parameter */ +- if (!err) +- *p_session_id = sid; +- +- /* Delete secure object */ +- tbase_object_free(obj); +- +-end: +- +- MCDRV_DBG("session %x, exit with %d\n", sid, err); +- return err; +-} +- +-/* +- * Open TA for given client. TA binary is provided by the client. +- * @param +- * @return tbase driver error code +- */ +-int api_open_trustlet(struct tbase_client *client, +- uint32_t *p_session_id, +- uint32_t spid, +- uintptr_t trustlet, +- size_t trustlet_len, +- uintptr_t tci, +- size_t tci_len) +-{ +- struct tbase_object *obj; +- struct mc_identity identity = { +- .login_type = TEEC_LOGIN_PUBLIC, +- }; +- uint32_t sid = 0; +- int err = 0; +- +- /* Check parameters */ +- if (!p_session_id) +- return -EINVAL; +- +- /* Create secure object from user-space trustlet binary */ +- obj = tbase_object_read(spid, trustlet, trustlet_len); +- if (IS_ERR(obj)) { +- err = PTR_ERR(obj); +- goto end; +- } +- +- /* Open session */ +- err = client_add_session(client, obj, tci, tci_len, &sid, false, +- &identity); +- /* Fill in return parameter */ +- if (!err) +- *p_session_id = sid; +- +- /* Delete secure object */ +- tbase_object_free(obj); +- +-end: +- MCDRV_DBG("session %x, exit with %d\n", sid, err); +- return err; +-} +- +-/* +- * Close a TA +- * @param +- * @return tbase driver error code +- */ +-int api_close_session(struct tbase_client *client, uint32_t session_id) +-{ +- int ret = client_remove_session(client, session_id); +- +- MCDRV_DBG("session %x, exit with %d\n", session_id, ret); +- return ret; +-} +- +-/* +- * Send a notification to TA +- * @return tbase driver error code +- */ +-int api_notify(struct tbase_client *client, uint32_t session_id) +-{ +- int err = 0; +- struct tbase_session *session = NULL; +- +- /* Acquire session */ +- session = client_ref_session(client, session_id); +- +- /* Send command to SWd */ +- if (!session) { +- err = -ENXIO; +- } else { +- err = session_notify_swd(session); +- +- /* Release session */ +- client_unref_session(session); +- } +- +- MCDRV_DBG("session %x, exit with %d\n", session_id, err); +- return err; +-} +- +-/* +- * Wait for a notification from TA +- * @return tbase driver error code +- */ +-int api_wait_notification(struct tbase_client *client, +- uint32_t session_id, +- int32_t timeout) +-{ +- int err = 0; +- struct tbase_session *session = NULL; +- +- /* Acquire session */ +- session = client_ref_session(client, session_id); +- +- /* Wait for notification */ +- if (!session) { +- err = -ENXIO; +- } else { +- err = session_waitnotif(session, timeout); +- +- /* Release session */ +- client_unref_session(session); +- } +- +- MCDRV_DBG("session %x, exit with %d\n", session_id, err); +- return err; +-} +- +-/* +- * Allocate a contiguous buffer (cbuf) for given client +- * +- * @param client client +- * @param len size of the cbuf +- * @param **p_addr pointer to the cbuf kva +- * @return tbase driver error code +- */ +-int api_malloc_cbuf(struct tbase_client *client, uint32_t len, +- uintptr_t *addr, struct vm_area_struct *vmarea) +-{ +- int err = tbase_cbuf_alloc(client, len, addr, vmarea); +- +- MCDRV_DBG("exit with %d\n", err); +- return err; +-} +- +-/* +- * Free a contiguous buffer from given client +- * @param client +- * @param addr kernel virtual address of the buffer +- * +- * @return tbase driver error code +- */ +-int api_free_cbuf(struct tbase_client *client, uintptr_t addr) +-{ +- int err = tbase_cbuf_free(client, addr); +- +- MCDRV_DBG("@ 0x%lx, exit with %d\n", addr, err); +- return err; +-} +- +-/* Share a buffer with given TA in SWd */ +-int api_map_wsms(struct tbase_client *client, uint32_t session_id, +- struct mc_ioctl_buffer *bufs) +-{ +- struct tbase_session *session = NULL; +- int err = 0; +- +- if (!client) +- return -EINVAL; +- +- if (!bufs) +- return -EINVAL; +- +- /* Acquire session */ +- session = client_ref_session(client, session_id); +- +- if (session) { +- /* Add buffer to the session */ +- err = session_wsms_add(session, bufs); +- +- /* Release session */ +- client_unref_session(session); +- } else { +- err = -ENXIO; +- } +- +- MCDRV_DBG("exit with %d\n", err); +- return err; +-} +- +-/* Stop sharing a buffer with SWd */ +-int api_unmap_wsms(struct tbase_client *client, uint32_t session_id, +- const struct mc_ioctl_buffer *bufs) +-{ +- struct tbase_session *session = NULL; +- int err = 0; +- +- if (!client) +- return -EINVAL; +- +- if (!bufs) +- return -EINVAL; +- +- /* Acquire session */ +- session = client_ref_session(client, session_id); +- +- if (!session) { +- err = -ENXIO; +- } else { +- /* Remove buffer from session */ +- err = session_wsms_remove(session, bufs); +- /* Release session */ +- client_unref_session(session); +- } +- +- MCDRV_DBG("exit with %d\n", err); +- return err; +-} +- +-/* +- * Read session exit/termination code +- */ +-int api_get_session_exitcode(struct tbase_client *client, uint32_t session_id, +- int32_t *exit_code) +-{ +- int err = 0; +- struct tbase_session *session; +- +- /* Acquire session */ +- session = client_ref_session(client, session_id); +- +- if (!session) { +- err = -ENXIO; +- } else { +- /* Retrieve error */ +- *exit_code = session_exitcode(session); +- +- /* Release session */ +- client_unref_session(session); +- +- err = 0; +- } +- +- MCDRV_DBG("session %x, exit with %d\n", session_id, err); +- return err; +-} +- +-void api_init(void) +-{ +- INIT_LIST_HEAD(&api_ctx.clients); +- mutex_init(&api_ctx.clients_lock); +- +- INIT_LIST_HEAD(&g_ctx.closing_sess); +- mutex_init(&g_ctx.closing_lock); +-} +- +-int api_info(struct kasnprintf_buf *buf) +-{ +- struct tbase_client *client; +- struct tbase_session *session; +- ssize_t ret = 0; +- +- mutex_lock(&api_ctx.clients_lock); +- if (list_empty(&api_ctx.clients)) +- goto done; +- +- list_for_each_entry(client, &api_ctx.clients, list) { +- ret = client_info(client, buf); +- if (ret < 0) +- break; +- } +- +-done: +- mutex_unlock(&api_ctx.clients_lock); +- +- if (ret >= 0) { +- mutex_lock(&g_ctx.closing_lock); +- if (!list_empty(&g_ctx.closing_sess)) +- ret = kasnprintf(buf, "closing sessions:\n"); +- +- list_for_each_entry(session, &g_ctx.closing_sess, list) { +- ret = session_info(session, buf); +- if (ret < 0) +- break; +- } +- +- mutex_unlock(&g_ctx.closing_lock); +- } +- +- return ret; +-} +diff --git a/drivers/gud/MobiCoreDriver/api.h b/drivers/gud/MobiCoreDriver/api.h +deleted file mode 100644 +index 740ec7fb2d5b9..0000000000000 +--- a/drivers/gud/MobiCoreDriver/api.h ++++ /dev/null +@@ -1,46 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _API_H_ +-#define _API_H_ +- +-struct tbase_client; +- +-struct tbase_client *api_open_device(bool is_from_kernel); +-int api_freeze_device(struct tbase_client *client); +-void api_close_device(struct tbase_client *client); +-int api_open_session(struct tbase_client *client, uint32_t *session_id, +- const struct mc_uuid_t *uuid, +- uintptr_t tci, size_t tci_len, bool is_gp_uuid, +- struct mc_identity *identity); +-int api_open_trustlet(struct tbase_client *client, uint32_t *session_id, +- uint32_t spid, uintptr_t trustlet, size_t trustlet_len, +- uintptr_t tci, size_t tci_len); +-int api_close_session(struct tbase_client *client, uint32_t session_id); +-int api_notify(struct tbase_client *client, uint32_t session_id); +-int api_wait_notification(struct tbase_client *client, uint32_t session_id, +- int32_t timeout); +-int api_malloc_cbuf(struct tbase_client *client, uint32_t len, uintptr_t *addr, +- struct vm_area_struct *vmarea); +-int api_free_cbuf(struct tbase_client *client, uintptr_t addr); +-int api_map_wsms(struct tbase_client *client, uint32_t session_id, +- struct mc_ioctl_buffer *bufs); +-int api_unmap_wsms(struct tbase_client *client, uint32_t session_id, +- const struct mc_ioctl_buffer *bufs); +-int api_get_session_exitcode(struct tbase_client *client, uint32_t session_id, +- int32_t *exit_code); +-void api_init(void); +-int api_info(struct kasnprintf_buf *buf); +- +-#endif /* _API_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/arm.h b/drivers/gud/MobiCoreDriver/arm.h +deleted file mode 100644 +index 58d91f11f789c..0000000000000 +--- a/drivers/gud/MobiCoreDriver/arm.h ++++ /dev/null +@@ -1,88 +0,0 @@ +-/* +- * Copyright (c) 2013-2014 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#ifndef _MC_ARM_H_ +-#define _MC_ARM_H_ +- +-#include "debug.h" +- +-#ifdef CONFIG_ARM64 +-inline bool has_security_extensions(void) +-{ +- return true; +-} +- +-inline bool is_secure_mode(void) +-{ +- return false; +-} +-#else +-/* +- * ARM Trustzone specific masks and modes +- * Vanilla Linux is unaware of TrustZone extension. +- * I.e. arch/arm/include/asm/ptrace.h does not define monitor mode. +- * Also TZ bits in cpuid are not defined, ARM port uses magic numbers, +- * see arch/arm/kernel/setup.c +- */ +-#define ARM_MONITOR_MODE (0x16) /*(0b10110)*/ +-#define ARM_SECURITY_EXTENSION_MASK (0x30) +- +-/* check if CPU supports the ARM TrustZone Security Extensions */ +-inline bool has_security_extensions(void) +-{ +- u32 fea = 0; +- +- asm volatile( +- "mrc p15, 0, %[fea], cr0, cr1, 0" : +- [fea]"=r" (fea)); +- +- MCDRV_DBG_VERBOSE("CPU Features: 0x%X", fea); +- +- /* +- * If the CPU features ID has 0 for security features then the CPU +- * doesn't support TrustZone at all! +- */ +- if ((fea & ARM_SECURITY_EXTENSION_MASK) == 0) +- return false; +- +- return true; +-} +- +-/* check if running in secure mode */ +-inline bool is_secure_mode(void) +-{ +- u32 cpsr = 0; +- u32 nsacr = 0; +- +- asm volatile( +- "mrc p15, 0, %[nsacr], cr1, cr1, 2\n" +- "mrs %[cpsr], cpsr\n" : +- [nsacr]"=r" (nsacr), +- [cpsr]"=r"(cpsr)); +- +- MCDRV_DBG_VERBOSE("CPRS.M = set to 0x%X\n", cpsr & MODE_MASK); +- MCDRV_DBG_VERBOSE("SCR.NS = set to 0x%X\n", nsacr); +- +- /* +- * If the NSACR contains the reset value(=0) then most likely we are +- * running in Secure MODE. +- * If the cpsr mode is set to monitor mode then we cannot load! +- */ +- if (nsacr == 0 || ((cpsr & MODE_MASK) == ARM_MONITOR_MODE)) +- return true; +- +- return false; +-} +-#endif +- +-#endif /* _MC_ARM_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/build_tag.h b/drivers/gud/MobiCoreDriver/build_tag.h +deleted file mode 100644 +index 51a5d3e0ae7f5..0000000000000 +--- a/drivers/gud/MobiCoreDriver/build_tag.h ++++ /dev/null +@@ -1,15 +0,0 @@ +-/* +- * Copyright (c) 2013-2014 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#define MOBICORE_COMPONENT_BUILD_TAG \ +- "t-base-QC-MSM8996-Android-302B-V001-20150529_084320_16" +diff --git a/drivers/gud/MobiCoreDriver/client.c b/drivers/gud/MobiCoreDriver/client.c +deleted file mode 100644 +index c8bdc07b8742d..0000000000000 +--- a/drivers/gud/MobiCoreDriver/client.c ++++ /dev/null +@@ -1,572 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +-#include "public/mc_admin.h" +- +-#include "main.h" +-#include "debug.h" +-#include "mcp.h" +-#include "mmu.h" +-#include "session.h" +-#include "client.h" +- +-/* +- * Contiguous buffer allocated to TLCs. +- * These buffers are used as world shared memory (wsm) to share with +- * secure world. +- */ +-struct tbase_cbuf { +- /* Client this cbuf belongs to */ +- struct tbase_client *client; +- /* List element for client's list of cbuf's */ +- struct list_head list; +- /* Number of references kept to this buffer */ +- struct kref kref; +- /* virtual Kernel start address */ +- uintptr_t addr; +- /* virtual Userspace start address */ +- uintptr_t uaddr; +- /* physical start address */ +- phys_addr_t phys; +- /* 2^order = number of pages allocated */ +- unsigned int order; +- /* Length of memory mapped to user */ +- uint32_t len; +-}; +- +-/* +- * Map a kernel contiguous buffer to user space +- */ +-static int map_cbuf(struct vm_area_struct *vmarea, uintptr_t addr, uint32_t len, +- uintptr_t *uaddr) +-{ +- int ret; +- +- if (WARN(!uaddr, "No uaddr pointer available")) +- return -EINVAL; +- +- if (WARN(!vmarea, "No vma available")) +- return -EINVAL; +- +- if (WARN(!addr, "No addr available")) +- return -EINVAL; +- +- if (len != (uint32_t)(vmarea->vm_end - vmarea->vm_start)) { +- MCDRV_ERROR("cbuf incompatible with vma"); +- return -EINVAL; +- } +- +- vmarea->vm_flags |= VM_IO; +- +- /* CPI todo: use io_remap_page_range() to be consistent with VM_IO ? */ +- ret = remap_pfn_range(vmarea, vmarea->vm_start, +- page_to_pfn(virt_to_page(addr)), +- vmarea->vm_end - vmarea->vm_start, +- vmarea->vm_page_prot); +- if (ret) { +- *uaddr = 0; +- MCDRV_ERROR("User mapping failed"); +- return ret; +- } +- +- *uaddr = vmarea->vm_start; +- return 0; +-} +- +-/* +- * Allocate and initialize a client object +- */ +-struct tbase_client *client_create(bool is_from_kernel) +-{ +- struct tbase_client *client; +- +- /* allocate client structure */ +- client = kzalloc(sizeof(*client), GFP_KERNEL); +- if (!client) { +- MCDRV_ERROR("Allocation failure"); +- return NULL; +- } +- +- /* init members */ +- client->pid = is_from_kernel ? 0 : current->pid; +- memcpy(client->comm, current->comm, sizeof(client->comm)); +- kref_init(&client->kref); +- INIT_LIST_HEAD(&client->cbufs); +- mutex_init(&client->cbufs_lock); +- INIT_LIST_HEAD(&client->sessions); +- mutex_init(&client->sessions_lock); +- INIT_LIST_HEAD(&client->list); +- +- return client; +-} +- +-/* +- * At this point, nobody has access to the client anymore, so no new sessions +- * are coming. +- */ +-void client_close_sessions(struct tbase_client *client) +-{ +- struct tbase_session *session; +- +- mutex_lock(&client->sessions_lock); +- while (!list_empty(&client->sessions)) { +- session = list_first_entry(&client->sessions, +- struct tbase_session, list); +- +- /* Move session to closing sessions list */ +- mutex_lock(&g_ctx.closing_lock); +- list_move(&session->list, &g_ctx.closing_sess); +- mutex_unlock(&g_ctx.closing_lock); +- /* Call session_close without lock */ +- mutex_unlock(&client->sessions_lock); +- session_close(session); +- mutex_lock(&client->sessions_lock); +- } +- +- mutex_unlock(&client->sessions_lock); +-} +- +-/* +- * Free client object + all objects it contains. +- * Can be called only by last user referencing the client, +- * therefore mutex lock seems overkill +- */ +-static void client_release(struct kref *kref) +-{ +- struct tbase_client *client; +- +- client = container_of(kref, struct tbase_client, kref); +- kfree(client); +-} +- +-void client_put(struct tbase_client *client) +-{ +- kref_put(&client->kref, client_release); +-} +- +-/* +- * Returns true if client is a kernel object. +- */ +-bool client_is_kernel(struct tbase_client *client) +-{ +- return !client->pid; +-} +- +-/* +- * Set client "closing" state, only if it contains no session. +- * Once in "closing" state, system "close" can be called. +- * Return: true if this state could be set. +- */ +-bool client_set_closing(struct tbase_client *client) +-{ +- bool clear = false; +- +- /* Check for sessions */ +- mutex_lock(&client->sessions_lock); +- clear = list_empty(&client->sessions); +- client->closing = clear; +- mutex_unlock(&client->sessions_lock); +- MCDRV_DBG("return %d", clear); +- return clear; +-} +- +-/* +- * Opens a TA and add corresponding session object to given client +- * return: t-base driver error code +- */ +-int client_add_session(struct tbase_client *client, +- const struct tbase_object *obj, uintptr_t tci, +- size_t len, uint32_t *session_id, bool is_gp, +- struct mc_identity *identity) +-{ +- struct tbase_session *session = NULL; +- struct tbase_mmu *obj_mmu = NULL; +- int ret = 0; +- +- /* +- * Create session object with temp sid=0 BEFORE session is started, +- * otherwise if a GP TA is started and NWd session object allocation +- * fails, we cannot handle the potentially delayed GP closing. +- * Adding session to list must be done AFTER it is started (once we have +- * sid), therefore it cannot be done within session_create(). +- */ +- session = session_create(client, is_gp, identity); +- if (IS_ERR(session)) +- return PTR_ERR(session); +- +- /* Create blob L2 table (blob is allocated by driver, so task=NULL) */ +- obj_mmu = tbase_mmu_create(NULL, obj->data, obj->length); +- if (IS_ERR(obj_mmu)) { +- ret = PTR_ERR(obj_mmu); +- goto err; +- } +- +- /* Open session */ +- ret = session_open(session, obj, obj_mmu, tci, len); +- /* Blob table no more needed in any case */ +- tbase_mmu_delete(obj_mmu); +- if (ret) +- goto err; +- +- mutex_lock(&client->sessions_lock); +- if (unlikely(client->closing)) { +- /* Client has been frozen, no more sessions allowed */ +- ret = -ENODEV; +- } else { +- /* Add session to client */ +- list_add(&session->list, &client->sessions); +- /* Set sid returned by SWd */ +- *session_id = session->mcp_session.id; +- } +- +- mutex_unlock(&client->sessions_lock); +- +-err: +- /* Close or free session on error */ +- if (ret == -ENODEV) { +- /* The session must enter the closing process... */ +- mutex_lock(&g_ctx.closing_lock); +- list_add(&session->list, &g_ctx.closing_sess); +- mutex_unlock(&g_ctx.closing_lock); +- session_close(session); +- } else if (ret) { +- session_put(session); +- } +- +- return ret; +-} +- +-/* +- * Remove a session object from client and close corresponding TA +- * Return: true if session was found and closed +- */ +-int client_remove_session(struct tbase_client *client, uint32_t session_id) +-{ +- struct tbase_session *session = NULL, *candidate; +- +- /* Move session from main list to closing list */ +- mutex_lock(&client->sessions_lock); +- list_for_each_entry(candidate, &client->sessions, list) { +- if (candidate->mcp_session.id == session_id) { +- session = candidate; +- mutex_lock(&g_ctx.closing_lock); +- list_move(&session->list, &g_ctx.closing_sess); +- mutex_unlock(&g_ctx.closing_lock); +- break; +- } +- } +- +- mutex_unlock(&client->sessions_lock); +- +- /* Close session */ +- return session_close(session); +-} +- +-/* +- * Find a session object and increment its reference counter. +- * Object cannot be freed until its counter reaches 0. +- * return: pointer to the object, NULL if not found. +- */ +-struct tbase_session *client_ref_session(struct tbase_client *client, +- uint32_t session_id) +-{ +- struct tbase_session *session = NULL, *candidate; +- +- mutex_lock(&client->sessions_lock); +- list_for_each_entry(candidate, &client->sessions, list) { +- if (candidate->mcp_session.id == session_id) { +- session = candidate; +- session_get(session); +- break; +- } +- } +- +- mutex_unlock(&client->sessions_lock); +- return session; +-} +- +-/* +- * Decrement a session object's reference counter, and frees the object if it +- * was the last reference. +- * No lookup since session may have been removed from list +- */ +-void client_unref_session(struct tbase_session *session) +-{ +- session_put(session); +-} +- +-static inline int cbuf_info(struct tbase_cbuf *cbuf, +- struct kasnprintf_buf *buf); +- +-int client_info(struct tbase_client *client, struct kasnprintf_buf *buf) +-{ +- struct tbase_cbuf *cbuf; +- struct tbase_session *session; +- int ret; +- +- if (client->pid) +- ret = kasnprintf(buf, "client %p: %s (%d)\n", client, +- client->comm, client->pid); +- else +- ret = kasnprintf(buf, "client %p: [kernel]\n", client); +- +- if (ret < 0) +- return ret; +- +- /* Buffers */ +- mutex_lock(&client->cbufs_lock); +- if (list_empty(&client->cbufs)) +- goto done_cbufs; +- +- list_for_each_entry(cbuf, &client->cbufs, list) { +- ret = cbuf_info(cbuf, buf); +- if (ret < 0) +- goto done_cbufs; +- } +- +-done_cbufs: +- mutex_unlock(&client->cbufs_lock); +- if (ret < 0) +- return ret; +- +- /* Sessions */ +- mutex_lock(&client->sessions_lock); +- if (list_empty(&client->sessions)) +- goto done_sessions; +- +- list_for_each_entry(session, &client->sessions, list) { +- ret = session_info(session, buf); +- if (ret < 0) +- goto done_sessions; +- } +- +-done_sessions: +- mutex_unlock(&client->sessions_lock); +- +- if (ret < 0) +- return ret; +- +- return 0; +-} +- +-/* +- * This callback is called on remap +- */ +-static void cbuf_vm_open(struct vm_area_struct *vmarea) +-{ +- struct tbase_cbuf *cbuf = vmarea->vm_private_data; +- +- tbase_cbuf_get(cbuf); +-} +- +-/* +- * This callback is called on unmap +- */ +-static void cbuf_vm_close(struct vm_area_struct *vmarea) +-{ +- struct tbase_cbuf *cbuf = vmarea->vm_private_data; +- +- tbase_cbuf_put(cbuf); +-} +- +-static struct vm_operations_struct cbuf_vm_ops = { +- .open = cbuf_vm_open, +- .close = cbuf_vm_close, +-}; +- +-/* +- * Create a cbuf object and add it to client +- */ +-int tbase_cbuf_alloc(struct tbase_client *client, uint32_t len, +- uintptr_t *p_addr, +- struct vm_area_struct *vmarea) +-{ +- int err = 0; +- struct tbase_cbuf *cbuf = NULL; +- unsigned int order; +- +- if (WARN(!client, "No client available")) +- return -EINVAL; +- +- if (WARN(!len, "No len available")) +- return -EINVAL; +- +- order = get_order(len); +- if (order > MAX_ORDER) { +- MCDRV_DBG_WARN("Buffer size too large"); +- return -ENOMEM; +- } +- +- /* Allocate buffer descriptor structure */ +- cbuf = kzalloc(sizeof(*cbuf), GFP_KERNEL); +- if (!cbuf) { +- MCDRV_DBG_WARN("kzalloc failed"); +- return -ENOMEM; +- } +- +- /* Allocate buffer */ +- cbuf->addr = __get_free_pages(GFP_USER | __GFP_ZERO, order); +- if (!cbuf->addr) { +- MCDRV_DBG_WARN("get_free_pages failed"); +- kfree(cbuf); +- return -ENOMEM; +- } +- +- /* Map to user space if applicable */ +- if (!client_is_kernel(client)) { +- err = map_cbuf(vmarea, cbuf->addr, len, &cbuf->uaddr); +- if (err) { +- free_pages(cbuf->addr, order); +- kfree(cbuf); +- return err; +- } +- } +- +- /* Init descriptor members */ +- cbuf->client = client; +- cbuf->phys = virt_to_phys((void *)cbuf->addr); +- cbuf->len = len; +- cbuf->order = order; +- kref_init(&cbuf->kref); +- INIT_LIST_HEAD(&cbuf->list); +- +- /* Keep cbuf in VMA private data for refcounting (user-space clients) */ +- if (vmarea) { +- vmarea->vm_private_data = cbuf; +- vmarea->vm_ops = &cbuf_vm_ops; +- } +- +- /* Fill return parameter for k-api */ +- if (p_addr) +- *p_addr = cbuf->addr; +- +- /* Get a token on the client */ +- client_get(client); +- +- /* Add buffer to list */ +- mutex_lock(&client->cbufs_lock); +- list_add(&cbuf->list, &client->cbufs); +- mutex_unlock(&client->cbufs_lock); +- MCDRV_DBG("created cbuf %p: client %p addr %lx uaddr %lx len %u", +- cbuf, client, cbuf->addr, cbuf->uaddr, cbuf->len); +- return err; +-} +- +-/* +- * Remove a cbuf object from client, and mark it for freeing. +- * Freeing will happen once all current references are released. +- */ +-int tbase_cbuf_free(struct tbase_client *client, uintptr_t addr) +-{ +- struct tbase_cbuf *cbuf = tbase_cbuf_get_by_addr(client, addr); +- +- if (!cbuf) +- return -EINVAL; +- +- /* Two references to put: the caller's and the one we just took */ +- tbase_cbuf_put(cbuf); +- tbase_cbuf_put(cbuf); +- return 0; +-} +- +-/* +- * Find a contiguous buffer (cbuf) in the cbuf list of given client that +- * contains given address and take a reference on it. +- * Return pointer to the object, or NULL if not found. +- */ +-struct tbase_cbuf *tbase_cbuf_get_by_addr(struct tbase_client *client, +- uintptr_t addr) +-{ +- struct tbase_cbuf *cbuf = NULL, *candidate; +- bool is_kernel = client_is_kernel(client); +- +- mutex_lock(&client->cbufs_lock); +- list_for_each_entry(candidate, &client->cbufs, list) { +- /* Compare Vs kernel va OR user va depending on client type */ +- uintptr_t start = is_kernel ? +- candidate->addr : candidate->uaddr; +- uintptr_t end = start + candidate->len; +- +- /* Check that (user) cbuf has not been unmapped */ +- if (!start) +- break; +- +- if ((addr >= start) && (addr < end)) { +- cbuf = candidate; +- break; +- } +- } +- +- if (cbuf) +- tbase_cbuf_get(cbuf); +- +- mutex_unlock(&client->cbufs_lock); +- return cbuf; +-} +- +-void tbase_cbuf_get(struct tbase_cbuf *cbuf) +-{ +- kref_get(&cbuf->kref); +-} +- +-static void cbuf_release(struct kref *kref) +-{ +- struct tbase_cbuf *cbuf = container_of(kref, struct tbase_cbuf, kref); +- struct tbase_client *client = cbuf->client; +- +- /* Unlist from client */ +- mutex_lock(&client->cbufs_lock); +- list_del_init(&cbuf->list); +- mutex_unlock(&client->cbufs_lock); +- /* Release client token */ +- client_put(client); +- /* Free */ +- free_pages(cbuf->addr, cbuf->order); +- MCDRV_DBG("freed cbuf %p: client %p addr %lx uaddr %lx len %u", +- cbuf, client, cbuf->addr, cbuf->uaddr, cbuf->len); +- kfree(cbuf); +-} +- +-void tbase_cbuf_put(struct tbase_cbuf *cbuf) +-{ +- kref_put(&cbuf->kref, cbuf_release); +-} +- +-uintptr_t tbase_cbuf_addr(struct tbase_cbuf *cbuf) +-{ +- return cbuf->addr; +-} +- +-uintptr_t tbase_cbuf_uaddr(struct tbase_cbuf *cbuf) +-{ +- return cbuf->uaddr; +-} +- +-uint32_t tbase_cbuf_len(struct tbase_cbuf *cbuf) +-{ +- return cbuf->len; +-} +- +-static inline int cbuf_info(struct tbase_cbuf *cbuf, struct kasnprintf_buf *buf) +-{ +- return kasnprintf(buf, "\tcbuf %p: addr %lx uaddr %lx len %u\n", +- cbuf, cbuf->addr, cbuf->uaddr, cbuf->len); +-} +diff --git a/drivers/gud/MobiCoreDriver/client.h b/drivers/gud/MobiCoreDriver/client.h +deleted file mode 100644 +index 3cc833eeffb87..0000000000000 +--- a/drivers/gud/MobiCoreDriver/client.h ++++ /dev/null +@@ -1,99 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _CLIENT_H_ +-#define _CLIENT_H_ +- +-#include +-#include /* TASK_COMM_LEN */ +- +-struct task_struct; +-struct tbase_object; +-struct tbase_session; +- +-struct tbase_client { +- /* PID of task that opened the device, 0 if kernel */ +- pid_t pid; +- /* Command for task*/ +- char comm[TASK_COMM_LEN]; +- /* Number of references kept to this object */ +- struct kref kref; +- /* List of contiguous buffers allocated by mcMallocWsm for the client */ +- struct list_head cbufs; +- struct mutex cbufs_lock; /* lock for the cbufs list */ +- /* List of tbase TA sessions opened by this client */ +- struct list_head sessions; +- struct mutex sessions_lock; /* sessions list + closing */ +- /* Client state */ +- bool closing; +- /* The list entry to attach to "ctx.clients" list */ +- struct list_head list; +-}; +- +-struct tbase_client *client_create(bool is_from_kernel); +- +-void client_close_sessions(struct tbase_client *client); +- +-static inline void client_get(struct tbase_client *client) +-{ +- kref_get(&client->kref); +-} +- +-void client_put(struct tbase_client *client); +- +-bool client_is_kernel(struct tbase_client *client); +- +-bool client_set_closing(struct tbase_client *client); +- +-int client_add_session(struct tbase_client *client, +- const struct tbase_object *obj, uintptr_t tci, +- size_t len, uint32_t *p_sid, bool is_gp_uuid, +- struct mc_identity *identity); +- +-int client_remove_session(struct tbase_client *client, uint32_t session_id); +- +-struct tbase_session *client_ref_session(struct tbase_client *client, +- uint32_t session_id); +- +-void client_unref_session(struct tbase_session *session); +- +-int client_info(struct tbase_client *client, struct kasnprintf_buf *buf); +- +-/* +- * Contiguous buffer allocated to TLCs. +- * These buffers are uses as world shared memory (wsm) and shared with +- * secure world. +- * The virtual kernel address is added for a simpler search algorithm. +- */ +-struct tbase_cbuf; +- +-int tbase_cbuf_alloc(struct tbase_client *client, uint32_t len, +- uintptr_t *addr, struct vm_area_struct *vmarea); +- +-int tbase_cbuf_free(struct tbase_client *client, uintptr_t addr); +- +-struct tbase_cbuf *tbase_cbuf_get_by_addr(struct tbase_client *client, +- uintptr_t addr); +- +-void tbase_cbuf_get(struct tbase_cbuf *cbuf); +- +-void tbase_cbuf_put(struct tbase_cbuf *cbuf); +- +-uintptr_t tbase_cbuf_addr(struct tbase_cbuf *cbuf); +- +-uintptr_t tbase_cbuf_uaddr(struct tbase_cbuf *cbuf); +- +-uint32_t tbase_cbuf_len(struct tbase_cbuf *cbuf); +- +-#endif /* _CLIENT_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/clientlib.c b/drivers/gud/MobiCoreDriver/clientlib.c +deleted file mode 100644 +index c7d6d023b3a80..0000000000000 +--- a/drivers/gud/MobiCoreDriver/clientlib.c ++++ /dev/null +@@ -1,433 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +-#include "public/mc_admin.h" +-#include "public/mobicore_driver_api.h" +- +-#include "main.h" +-#include "debug.h" +-#include "client.h" +-#include "session.h" +-#include "api.h" +- +-enum mc_result convert(int err) +-{ +- switch (-err) { +- case 0: +- return MC_DRV_OK; +- case ENOMSG: +- return MC_DRV_NO_NOTIFICATION; +- case EBADMSG: +- return MC_DRV_ERR_NOTIFICATION; +- case EAGAIN: +- return MC_DRV_ERR_OUT_OF_RESOURCES; +- case EHOSTDOWN: +- return MC_DRV_ERR_INIT; +- case ENODEV: +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- case ENXIO: +- return MC_DRV_ERR_UNKNOWN_SESSION; +- case EPERM: +- return MC_DRV_ERR_INVALID_OPERATION; +- case EBADE: +- return MC_DRV_ERR_INVALID_RESPONSE; +- case ETIME: +- return MC_DRV_ERR_TIMEOUT; +- case ENOMEM: +- return MC_DRV_ERR_NO_FREE_MEMORY; +- case EUCLEAN: +- return MC_DRV_ERR_FREE_MEMORY_FAILED; +- case ENOTEMPTY: +- return MC_DRV_ERR_SESSION_PENDING; +- case EHOSTUNREACH: +- return MC_DRV_ERR_DAEMON_UNREACHABLE; +- case ENOENT: +- return MC_DRV_ERR_INVALID_DEVICE_FILE; +- case EINVAL: +- return MC_DRV_ERR_INVALID_PARAMETER; +- case EPROTO: +- return MC_DRV_ERR_KERNEL_MODULE; +- case EADDRINUSE: +- return MC_DRV_ERR_BULK_MAPPING; +- case EADDRNOTAVAIL: +- return MC_DRV_ERR_BULK_UNMAPPING; +- case ECOMM: +- return MC_DRV_INFO_NOTIFICATION; +- case EUNATCH: +- return MC_DRV_ERR_NQ_FAILED; +- default: +- MCDRV_DBG("error is %d", err); +- return MC_DRV_ERR_UNKNOWN; +- } +-} +- +-static inline bool is_valid_device(uint32_t device_id) +-{ +- return MC_DEVICE_ID_DEFAULT == device_id; +-} +- +-static struct tbase_client *client; +-static int open_count; +-static DEFINE_MUTEX(dev_mutex); /* Lock for the device */ +- +-static bool clientlib_client_get(void) +-{ +- int ret = true; +- +- mutex_lock(&dev_mutex); +- if (!client) +- ret = false; +- else +- client_get(client); +- +- mutex_unlock(&dev_mutex); +- return ret; +-} +- +-static void clientlib_client_put(void) +-{ +- mutex_lock(&dev_mutex); +- client_put(client); +- mutex_unlock(&dev_mutex); +-} +- +-enum mc_result mc_open_device(uint32_t device_id) +-{ +- enum mc_result mc_result = MC_DRV_OK; +- +- /* Check parameters */ +- if (!is_valid_device(device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- mutex_lock(&dev_mutex); +- if (!open_count) +- client = api_open_device(true); +- +- if (client) { +- open_count++; +- MCDRV_DBG("Successfully opened the device."); +- } else { +- mc_result = MC_DRV_ERR_INVALID_DEVICE_FILE; +- MCDRV_DBG("Could not open device"); +- } +- +- mutex_unlock(&dev_mutex); +- return mc_result; +-} +-EXPORT_SYMBOL(mc_open_device); +- +-enum mc_result mc_close_device(uint32_t device_id) +-{ +- enum mc_result mc_result = MC_DRV_OK; +- +- /* Check parameters */ +- if (!is_valid_device(device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- mutex_lock(&dev_mutex); +- if (!client) { +- mc_result = MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- goto end; +- } +- +- if (open_count > 1) { +- open_count--; +- goto end; +- } +- +- /* Check sessions and freeze client */ +- mc_result = convert(api_freeze_device(client)); +- if (MC_DRV_OK != mc_result) +- goto end; +- +- /* Close the device */ +- api_close_device(client); +- client = NULL; +- open_count = 0; +- +-end: +- mutex_unlock(&dev_mutex); +- return mc_result; +-} +-EXPORT_SYMBOL(mc_close_device); +- +-enum mc_result mc_open_session(struct mc_session_handle *session, +- const struct mc_uuid_t *uuid, +- uint8_t *tci, uint32_t len) +-{ +- struct mc_identity identity = { +- .login_type = TEEC_LOGIN_PUBLIC, +- }; +- enum mc_result ret; +- +- /* Check parameters */ +- if (!session) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!is_valid_device(session->device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- ret = convert(api_open_session(client, &session->session_id, uuid, +- (uintptr_t)tci, len, false, &identity)); +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_open_session); +- +-enum mc_result mc_open_trustlet(struct mc_session_handle *session, +- uint32_t spid, +- uint8_t *trustlet, uint32_t trustlet_len, +- uint8_t *tci, uint32_t len) +-{ +- enum mc_result ret; +- +- /* Check parameters */ +- if (!session) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!is_valid_device(session->device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- ret = convert(api_open_trustlet(client, &session->session_id, spid, +- (uintptr_t)trustlet, trustlet_len, +- (uintptr_t)tci, len)); +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_open_trustlet); +- +-enum mc_result mc_close_session(struct mc_session_handle *session) +-{ +- enum mc_result ret; +- +- /* Check parameters */ +- if (!session) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!is_valid_device(session->device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- ret = convert(api_close_session(client, session->session_id)); +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_close_session); +- +-enum mc_result mc_notify(struct mc_session_handle *session) +-{ +- enum mc_result ret; +- +- /* Check parameters */ +- if (!session) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!is_valid_device(session->device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- ret = convert(api_notify(client, session->session_id)); +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_notify); +- +-enum mc_result mc_wait_notification(struct mc_session_handle *session, +- int32_t timeout) +-{ +- enum mc_result ret; +- +- /* Check parameters */ +- if (!session) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!is_valid_device(session->device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- ret = convert(api_wait_notification(client, session->session_id, +- timeout)); +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_wait_notification); +- +-enum mc_result mc_malloc_wsm(uint32_t device_id, uint32_t align, uint32_t len, +- uint8_t **wsm, uint32_t wsm_flags) +-{ +- enum mc_result ret; +- uintptr_t va; +- +- /* Check parameters */ +- if (!is_valid_device(device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!len) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!wsm) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- ret = convert(api_malloc_cbuf(client, len, &va, NULL)); +- if (ret == MC_DRV_OK) +- *wsm = (uint8_t *)va; +- +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_malloc_wsm); +- +-enum mc_result mc_free_wsm(uint32_t device_id, uint8_t *wsm) +-{ +- enum mc_result ret; +- uintptr_t va = (uintptr_t)wsm; +- +- /* Check parameters */ +- if (!is_valid_device(device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- ret = convert(api_free_cbuf(client, va)); +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_free_wsm); +- +-enum mc_result mc_map(struct mc_session_handle *session, void *address, +- uint32_t length, struct mc_bulk_map *map_info) +-{ +- enum mc_result ret; +- struct mc_ioctl_buffer bufs[MC_MAP_MAX]; +- uint32_t i; +- +- /* Check parameters */ +- if (!session) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!is_valid_device(session->device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!map_info) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- bufs[0].va = (uintptr_t)address; +- bufs[0].len = length; +- for (i = 1; i < MC_MAP_MAX; i++) +- bufs[i].va = 0; +- +- ret = convert(api_map_wsms(client, session->session_id, bufs)); +- if (ret == MC_DRV_OK) { +- map_info->secure_virt_addr = bufs[0].sva; +- map_info->secure_virt_len = bufs[0].len; +- } +- +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_map); +- +-enum mc_result mc_unmap(struct mc_session_handle *session, void *address, +- struct mc_bulk_map *map_info) +-{ +- enum mc_result ret; +- struct mc_ioctl_buffer bufs[MC_MAP_MAX]; +- uint32_t i; +- +- /* Check parameters */ +- if (!session) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!is_valid_device(session->device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!map_info) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- bufs[0].va = (uintptr_t)address; +- bufs[0].len = map_info->secure_virt_len; +- bufs[0].sva = map_info->secure_virt_addr; +- for (i = 1; i < MC_MAP_MAX; i++) +- bufs[i].va = 0; +- +- ret = convert(api_unmap_wsms(client, session->session_id, bufs)); +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_unmap); +- +-enum mc_result mc_get_session_error_code(struct mc_session_handle *session, +- int32_t *exit_code) +-{ +- enum mc_result ret; +- +- /* Check parameters */ +- if (!session) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!is_valid_device(session->device_id)) +- return MC_DRV_ERR_UNKNOWN_DEVICE; +- +- if (!exit_code) +- return MC_DRV_ERR_INVALID_PARAMETER; +- +- if (!clientlib_client_get()) +- return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; +- +- /* Call core api */ +- ret = convert(api_get_session_exitcode(client, session->session_id, +- exit_code)); +- clientlib_client_put(); +- return ret; +-} +-EXPORT_SYMBOL(mc_get_session_error_code); +diff --git a/drivers/gud/MobiCoreDriver/clock.c b/drivers/gud/MobiCoreDriver/clock.c +deleted file mode 100644 +index 0195ab794f205..0000000000000 +--- a/drivers/gud/MobiCoreDriver/clock.c ++++ /dev/null +@@ -1,161 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#include "platform.h" +- +-#ifdef MC_CRYPTO_CLOCK_MANAGEMENT +- +-#include +-#include +-#include +-#include +- +-#include "debug.h" +-#include "clock.h" +- +-static struct clk_context { +- struct clk *mc_ce_iface_clk; +- struct clk *mc_ce_core_clk; +- struct clk *mc_ce_bus_clk; +- struct clk *mc_ce_core_src_clk; +-} clk_ctx; +- +-int mc_clock_init(void) +-{ +- int ret = 0; +-#ifdef MC_CLOCK_CORESRC_DEFAULTRATE +- int core_src_rate = MC_CLOCK_CORESRC_DEFAULTRATE; +- +- /* Get core clk src */ +- clk_ctx.mc_ce_core_src_clk = clk_get(g_ctx.mcd, "core_clk_src"); +- if (IS_ERR(clk_ctx.mc_ce_core_src_clk)) { +- ret = PTR_ERR(clk_ctx.mc_ce_core_src_clk); +- MCDRV_ERROR("cannot get core src clock: %d", ret); +- goto error; +- } +- +-#ifdef MC_CRYPTO_CLOCK_CORESRC_PROPNAME +- if (of_property_read_u32(g_ctx.mcd->of_node, +- MC_CRYPTO_CLOCK_CORESRC_PROPNAME, +- &core_src_rate)) { +- core_src_rate = MC_CLOCK_CORESRC_DEFAULTRATE; +- MCDRV_ERROR("cannot get ce clock frequency from DT, use %d", +- core_src_rate); +- } +-#endif /* MC_CRYPTO_CLOCK_CORESRC_PROPNAME */ +- +- ret = clk_set_rate(clk_ctx.mc_ce_core_src_clk, core_src_rate); +- if (ret) { +- clk_put(clk_ctx.mc_ce_core_src_clk); +- clk_ctx.mc_ce_core_src_clk = NULL; +- MCDRV_ERROR("cannot set core clock src rate: %d", ret); +- ret = -EIO; +- goto error; +- } +-#endif /* MC_CLOCK_CORESRC_DEFAULTRATE */ +- +- /* Get core clk */ +- clk_ctx.mc_ce_core_clk = clk_get(g_ctx.mcd, "core_clk"); +- if (IS_ERR(clk_ctx.mc_ce_core_clk)) { +- ret = PTR_ERR(clk_ctx.mc_ce_core_clk); +- MCDRV_ERROR("cannot get core clock: %d", ret); +- goto error; +- } +- /* Get Interface clk */ +- clk_ctx.mc_ce_iface_clk = clk_get(g_ctx.mcd, "iface_clk"); +- if (IS_ERR(clk_ctx.mc_ce_iface_clk)) { +- clk_put(clk_ctx.mc_ce_core_clk); +- ret = PTR_ERR(clk_ctx.mc_ce_iface_clk); +- MCDRV_ERROR("cannot get iface clock: %d", ret); +- goto error; +- } +- /* Get AXI clk */ +- clk_ctx.mc_ce_bus_clk = clk_get(g_ctx.mcd, "bus_clk"); +- if (IS_ERR(clk_ctx.mc_ce_bus_clk)) { +- clk_put(clk_ctx.mc_ce_iface_clk); +- clk_put(clk_ctx.mc_ce_core_clk); +- ret = PTR_ERR(clk_ctx.mc_ce_bus_clk); +- MCDRV_ERROR("cannot get AXI bus clock: %d", ret); +- goto error; +- } +- return ret; +- +-error: +- clk_ctx.mc_ce_core_clk = NULL; +- clk_ctx.mc_ce_iface_clk = NULL; +- clk_ctx.mc_ce_bus_clk = NULL; +- clk_ctx.mc_ce_core_src_clk = NULL; +- return ret; +-} +- +-void mc_clock_exit(void) +-{ +- if (clk_ctx.mc_ce_iface_clk) +- clk_put(clk_ctx.mc_ce_iface_clk); +- +- if (clk_ctx.mc_ce_core_clk) +- clk_put(clk_ctx.mc_ce_core_clk); +- +- if (clk_ctx.mc_ce_bus_clk) +- clk_put(clk_ctx.mc_ce_bus_clk); +- +- if (clk_ctx.mc_ce_core_src_clk) +- clk_put(clk_ctx.mc_ce_core_src_clk); +-} +- +-int mc_clock_enable(void) +-{ +- int rc; +- +- rc = clk_prepare_enable(clk_ctx.mc_ce_core_clk); +- if (rc) { +- MCDRV_ERROR("cannot enable core clock"); +- goto err_core; +- } +- +- rc = clk_prepare_enable(clk_ctx.mc_ce_iface_clk); +- if (rc) { +- MCDRV_ERROR("cannot enable interface clock"); +- goto err_iface; +- } +- +- rc = clk_prepare_enable(clk_ctx.mc_ce_bus_clk); +- if (rc) { +- MCDRV_ERROR("cannot enable bus clock"); +- goto err_bus; +- } +- +- return 0; +- +-err_bus: +- clk_disable_unprepare(clk_ctx.mc_ce_iface_clk); +-err_iface: +- clk_disable_unprepare(clk_ctx.mc_ce_core_clk); +-err_core: +- return rc; +-} +- +-void mc_clock_disable(void) +-{ +- if (clk_ctx.mc_ce_iface_clk) +- clk_disable_unprepare(clk_ctx.mc_ce_iface_clk); +- +- if (clk_ctx.mc_ce_core_clk) +- clk_disable_unprepare(clk_ctx.mc_ce_core_clk); +- +- if (clk_ctx.mc_ce_bus_clk) +- clk_disable_unprepare(clk_ctx.mc_ce_bus_clk); +-} +- +-#endif /* MC_CRYPTO_CLOCK_MANAGEMENT */ +diff --git a/drivers/gud/MobiCoreDriver/clock.h b/drivers/gud/MobiCoreDriver/clock.h +deleted file mode 100644 +index 21095499efb53..0000000000000 +--- a/drivers/gud/MobiCoreDriver/clock.h ++++ /dev/null +@@ -1,53 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _MC_CLOCK_H_ +-#define _MC_CLOCK_H_ +- +-#include "platform.h" /* MC_CRYPTO_CLOCK_MANAGEMENT */ +- +-#ifdef MC_CRYPTO_CLOCK_MANAGEMENT +- +-/* Initialize secure crypto clocks */ +-int mc_clock_init(void); +-/* Free secure crypto clocks */ +-void mc_clock_exit(void); +-/* Enable secure crypto clocks */ +-int mc_clock_enable(void); +-/* Disable secure crypto clocks */ +-void mc_clock_disable(void); +- +-#else /* MC_CRYPTO_CLOCK_MANAGEMENT */ +- +-static inline int mc_clock_init(void) +-{ +- return 0; +-} +- +-static inline void mc_clock_exit(void) +-{ +-} +- +-static inline int mc_clock_enable(void) +-{ +- return 0; +-} +- +-static inline void mc_clock_disable(void) +-{ +-} +- +-#endif /* !MC_CRYPTO_CLOCK_MANAGEMENT */ +- +-#endif /* _MC_CLOCK_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/debug.h b/drivers/gud/MobiCoreDriver/debug.h +deleted file mode 100644 +index 9d6a52ab955b6..0000000000000 +--- a/drivers/gud/MobiCoreDriver/debug.h ++++ /dev/null +@@ -1,63 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#ifndef _MC_DEBUG_H_ +-#define _MC_DEBUG_H_ +- +-#include "main.h" /* g_ctx */ +- +-#define MCDRV_ERROR(txt, ...) \ +- dev_err(g_ctx.mcd, "%s() ### ERROR: " txt "\n", \ +- __func__, \ +- ##__VA_ARGS__) +- +-/* dummy function helper macro. */ +-#define DUMMY_FUNCTION() do {} while (0) +- +-#ifdef DEBUG +- +-#ifdef DEBUG_VERBOSE +-#define MCDRV_DBG_VERBOSE MCDRV_DBG +-#else +-#define MCDRV_DBG_VERBOSE(...) DUMMY_FUNCTION() +-#endif +- +-#define MCDRV_DBG(txt, ...) \ +- dev_info(g_ctx.mcd, "%s(): " txt "\n", \ +- __func__, \ +- ##__VA_ARGS__) +- +-#define MCDRV_DBG_WARN(txt, ...) \ +- dev_warn(g_ctx.mcd, "%s() WARNING: " txt "\n", \ +- __func__, \ +- ##__VA_ARGS__) +- +-#define MCDRV_ASSERT(cond) \ +- do { \ +- if (unlikely(!(cond))) { \ +- panic("Assertion failed: %s:%d\n", \ +- __FILE__, __LINE__); \ +- } \ +- } while (0) +- +-#else /* DEBUG */ +- +-#define MCDRV_DBG_VERBOSE(...) DUMMY_FUNCTION() +-#define MCDRV_DBG(...) DUMMY_FUNCTION() +-#define MCDRV_DBG_WARN(...) DUMMY_FUNCTION() +- +-#define MCDRV_ASSERT(...) DUMMY_FUNCTION() +- +-#endif /* !DEBUG */ +- +-#endif /* _MC_DEBUG_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/fastcall.c b/drivers/gud/MobiCoreDriver/fastcall.c +deleted file mode 100644 +index ee612632331c8..0000000000000 +--- a/drivers/gud/MobiCoreDriver/fastcall.c ++++ /dev/null +@@ -1,512 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +-#include "public/mc_linux_api.h" +- +-#include "mci/mcifc.h" +- +-#include "platform.h" /* MC_FASTCALL_WORKER_THREAD and more */ +-#include "debug.h" +-#include "clock.h" /* mc_clock_enable, mc_clock_disable */ +-#include "fastcall.h" +- +-struct fastcall_work { +-#ifdef MC_FASTCALL_WORKER_THREAD +- struct kthread_work work; +-#else +- struct work_struct work; +-#endif +- void *data; +-}; +- +-/* generic fast call parameters */ +-union mc_fc_generic { +- struct { +- uint32_t cmd; +- uint32_t param[3]; +- } as_in; +- struct { +- uint32_t resp; +- uint32_t ret; +- uint32_t param[2]; +- } as_out; +-}; +- +-/* fast call init */ +-union mc_fc_init { +- union mc_fc_generic as_generic; +- struct { +- uint32_t cmd; +- uint32_t base; +- uint32_t nq_info; +- uint32_t mcp_info; +- } as_in; +- struct { +- uint32_t resp; +- uint32_t ret; +- uint32_t rfu[2]; +- } as_out; +-}; +- +-/* fast call info parameters */ +-union mc_fc_info { +- union mc_fc_generic as_generic; +- struct { +- uint32_t cmd; +- uint32_t ext_info_id; +- uint32_t rfu[2]; +- } as_in; +- struct { +- uint32_t resp; +- uint32_t ret; +- uint32_t state; +- uint32_t ext_info; +- } as_out; +-}; +- +-#ifdef TBASE_CORE_SWITCHER +-/* fast call switch Core parameters */ +-union mc_fc_swich_core { +- union mc_fc_generic as_generic; +- struct { +- uint32_t cmd; +- uint32_t core_id; +- uint32_t rfu[2]; +- } as_in; +- struct { +- uint32_t resp; +- uint32_t ret; +- uint32_t state; +- uint32_t ext_info; +- } as_out; +-}; +-#endif +- +-#ifdef MC_FASTCALL_WORKER_THREAD +-static struct task_struct *fastcall_thread; +-static DEFINE_KTHREAD_WORKER(fastcall_worker); +-#endif +- +-/* +- * _smc() - fast call to MobiCore +- * +- * @data: pointer to fast call data +- */ +-static inline int _smc(union mc_fc_generic *mc_fc_generic) +-{ +- if (!mc_fc_generic) +- return -EINVAL; +- +-#ifdef MC_SMC_FASTCALL +- return smc_fastcall(mc_fc_generic, sizeof(*mc_fc_generic)); +-#else /* MC_SMC_FASTCALL */ +- { +-#ifdef CONFIG_ARM64 +- /* SMC expect values in x0-x3 */ +- register u64 reg0 __asm__("x0") = mc_fc_generic->as_in.cmd; +- register u64 reg1 __asm__("x1") = mc_fc_generic->as_in.param[0]; +- register u64 reg2 __asm__("x2") = mc_fc_generic->as_in.param[1]; +- register u64 reg3 __asm__("x3") = mc_fc_generic->as_in.param[2]; +- +- /* +- * According to AARCH64 SMC Calling Convention (ARM DEN 0028A), +- * section 3.1: registers x4-x17 are unpredictable/scratch +- * registers. So we have to make sure that the compiler does +- * not allocate any of those registers by letting him know that +- * the asm code might clobber them. +- */ +- __asm__ volatile ( +- "smc #0\n" +- : "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3) +- : +- : "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", +- "x12", "x13", "x14", "x15", "x16", "x17" +- ); +-#else /* CONFIG_ARM64 */ +- /* SMC expect values in r0-r3 */ +- register u32 reg0 __asm__("r0") = mc_fc_generic->as_in.cmd; +- register u32 reg1 __asm__("r1") = mc_fc_generic->as_in.param[0]; +- register u32 reg2 __asm__("r2") = mc_fc_generic->as_in.param[1]; +- register u32 reg3 __asm__("r3") = mc_fc_generic->as_in.param[2]; +- +- __asm__ volatile ( +-#ifdef MC_ARCH_EXTENSION_SEC +- /* This pseudo op is supported and required from +- * binutils 2.21 on */ +- ".arch_extension sec\n" +-#endif /* MC_ARCH_EXTENSION_SEC */ +- "smc #0\n" +- : "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3) +- ); +- +-#ifdef __ARM_VE_A9X4_QEMU__ +- /* Qemu does not return to the address following the SMC +- * instruction so we have to insert several nop instructions to +- * workaround this Qemu bug. */ +- __asm__ volatile ( +- "nop\n" +- "nop\n" +- "nop\n" +- "nop" +- ); +-#endif /* __ARM_VE_A9X4_QEMU__ */ +-#endif /* !CONFIG_ARM64 */ +- +- /* set response */ +- mc_fc_generic->as_out.resp = reg0; +- mc_fc_generic->as_out.ret = reg1; +- mc_fc_generic->as_out.param[0] = reg2; +- mc_fc_generic->as_out.param[1] = reg3; +- } +- return 0; +-#endif /* !MC_SMC_FASTCALL */ +-} +- +-#ifdef TBASE_CORE_SWITCHER +-static uint32_t active_cpu; +- +-#ifdef MC_FASTCALL_WORKER_THREAD +-static void mc_cpu_offline(int cpu) +-{ +- int i; +- +- if (active_cpu != cpu) { +- MCDRV_DBG("not active CPU, no action taken\n"); +- return; +- } +- +- /* Chose the first online CPU and switch! */ +- for_each_online_cpu(i) { +- if (cpu != i) { +- MCDRV_DBG("CPU %d is dying, switching to %d\n", cpu, i); +- mc_switch_core(i); +- break; +- } +- +- MCDRV_DBG("Skipping CPU %d\n", cpu); +- } +-} +- +-static int mobicore_cpu_callback(struct notifier_block *nfb, +- unsigned long action, void *hcpu) +-{ +- unsigned int cpu = (unsigned long)hcpu; +- +- switch (action) { +- case CPU_DOWN_PREPARE: +- case CPU_DOWN_PREPARE_FROZEN: +- dev_info(g_ctx.mcd, "Cpu %u is going to die\n", cpu); +- mc_cpu_offline(cpu); +- break; +- case CPU_DEAD: +- case CPU_DEAD_FROZEN: +- dev_info(g_ctx.mcd, "Cpu %u is dead\n", cpu); +- break; +- } +- return NOTIFY_OK; +-} +- +-static struct notifier_block mobicore_cpu_notifer = { +- .notifier_call = mobicore_cpu_callback, +-}; +-#endif /* MC_FASTCALL_WORKER_THREAD */ +- +-static cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic) +-{ +- cpumask_t cpu; +- uint32_t new_cpu; +- uint32_t cpu_id[] = CPU_IDS; +- +- new_cpu = mc_fc_generic->as_in.param[0]; +- mc_fc_generic->as_in.param[0] = cpu_id[mc_fc_generic->as_in.param[0]]; +- +- if (_smc(mc_fc_generic) != 0 || mc_fc_generic->as_out.ret != 0) { +- MCDRV_DBG("CoreSwap failed %d -> %d (cpu %d still active)\n", +- raw_smp_processor_id(), +- mc_fc_generic->as_in.param[0], +- raw_smp_processor_id()); +- } else { +- active_cpu = new_cpu; +- MCDRV_DBG("CoreSwap ok %d -> %d\n", +- raw_smp_processor_id(), active_cpu); +- } +- cpumask_clear(&cpu); +- cpumask_set_cpu(active_cpu, &cpu); +- return cpu; +-} +-#else /* TBASE_CORE_SWITCHER */ +-static inline cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic) +-{ +- return CPU_MASK_CPU0; +-} +-#endif /* !TBASE_CORE_SWITCHER */ +- +-#ifdef MC_FASTCALL_WORKER_THREAD +-static void fastcall_work_func(struct kthread_work *work) +-#else +-static void fastcall_work_func(struct work_struct *work) +-#endif +-{ +- struct fastcall_work *fc_work = +- container_of(work, struct fastcall_work, work); +- union mc_fc_generic *mc_fc_generic = fc_work->data; +- +- if (!mc_fc_generic) +- return; +- +- mc_clock_enable(); +- +- if (mc_fc_generic->as_in.cmd == MC_FC_SWAP_CPU) { +-#ifdef MC_FASTCALL_WORKER_THREAD +- cpumask_t new_msk = mc_exec_core_switch(mc_fc_generic); +- +- set_cpus_allowed(fastcall_thread, new_msk); +-#else +- mc_exec_core_switch(mc_fc_generic); +-#endif +- } else { +- _smc(mc_fc_generic); +- } +- +- mc_clock_disable(); +-} +- +-static bool mc_fastcall(void *data) +-{ +-#ifdef MC_FASTCALL_WORKER_THREAD +- struct fastcall_work fc_work = { +- KTHREAD_WORK_INIT(fc_work.work, fastcall_work_func), +- .data = data, +- }; +- +- if (!queue_kthread_work(&fastcall_worker, &fc_work.work)) +- return false; +- +- /* If work is queued or executing, wait for it to finish execution */ +- flush_kthread_work(&fc_work.work); +-#else +- struct fastcall_work fc_work = { +- .data = data, +- }; +- +- INIT_WORK_ONSTACK(&fc_work.work, fastcall_work_func); +- +- if (!schedule_work_on(0, &fc_work.work)) +- return false; +- +- flush_work(&fc_work.work); +-#endif +- return true; +-} +- +-int mc_fastcall_init(void) +-{ +- int ret = mc_clock_init(); +- +- if (ret) +- return ret; +- +-#ifdef MC_FASTCALL_WORKER_THREAD +- fastcall_thread = kthread_create(kthread_worker_fn, &fastcall_worker, +- "mc_fastcall"); +- if (IS_ERR(fastcall_thread)) { +- ret = PTR_ERR(fastcall_thread); +- fastcall_thread = NULL; +- MCDRV_ERROR("cannot create fastcall wq (%d)", ret); +- return ret; +- } +- +- /* this thread MUST run on CPU 0 at startup */ +- set_cpus_allowed(fastcall_thread, CPU_MASK_CPU0); +- +- wake_up_process(fastcall_thread); +-#ifdef TBASE_CORE_SWITCHER +- ret = register_cpu_notifier(&mobicore_cpu_notifer); +-#endif +-#endif /* MC_FASTCALL_WORKER_THREAD */ +- return ret; +-} +- +-void mc_fastcall_exit(void) +-{ +-#ifdef MC_FASTCALL_WORKER_THREAD +- if (!IS_ERR_OR_NULL(fastcall_thread)) { +-#ifdef TBASE_CORE_SWITCHER +- unregister_cpu_notifier(&mobicore_cpu_notifer); +-#endif +- kthread_stop(fastcall_thread); +- fastcall_thread = NULL; +- } +-#endif /* MC_FASTCALL_WORKER_THREAD */ +- mc_clock_exit(); +-} +- +-/* +- * convert fast call return code to linux driver module error code +- */ +-static int convert_fc_ret(uint32_t ret) +-{ +- switch (ret) { +- case MC_FC_RET_OK: +- return 0; +- case MC_FC_RET_ERR_INVALID: +- return -EINVAL; +- case MC_FC_RET_ERR_ALREADY_INITIALIZED: +- return -EBUSY; +- default: +- return -EFAULT; +- } +-} +- +-int mc_fc_init(uintptr_t base_pa, ptrdiff_t off, size_t q_len, size_t buf_len) +-{ +-#ifdef CONFIG_ARM64 +- uint32_t base_high = (uint32_t)(base_pa >> 32); +-#else +- uint32_t base_high = 0; +-#endif +- union mc_fc_init fc_init; +- +- /* Call the INIT fastcall to setup MobiCore initialization */ +- memset(&fc_init, 0, sizeof(fc_init)); +- fc_init.as_in.cmd = MC_FC_INIT; +- /* base address of mci buffer PAGE_SIZE (default is 4KB) aligned */ +- fc_init.as_in.base = (uint32_t)base_pa; +- /* notification buffer start/length [16:16] [start, length] */ +- fc_init.as_in.nq_info = +- ((base_high & 0xFFFF) << 16) | (q_len & 0xFFFF); +- /* mcp buffer start/length [16:16] [start, length] */ +- fc_init.as_in.mcp_info = (off << 16) | (buf_len & 0xFFFF); +- MCDRV_DBG("cmd=0x%08x, base=0x%08x,nq_info=0x%08x, mcp_info=0x%08x", +- fc_init.as_in.cmd, fc_init.as_in.base, fc_init.as_in.nq_info, +- fc_init.as_in.mcp_info); +- mc_fastcall(&fc_init.as_generic); +- MCDRV_DBG("out cmd=0x%08x, ret=0x%08x", fc_init.as_out.resp, +- fc_init.as_out.ret); +- return convert_fc_ret(fc_init.as_out.ret); +-} +- +-int mc_fc_info(uint32_t ext_info_id, uint32_t *state, uint32_t *ext_info) +-{ +- union mc_fc_info fc_info; +- int ret = 0; +- +- memset(&fc_info, 0, sizeof(fc_info)); +- fc_info.as_in.cmd = MC_FC_INFO; +- fc_info.as_in.ext_info_id = ext_info_id; +- mc_fastcall(&fc_info.as_generic); +- ret = convert_fc_ret(fc_info.as_out.ret); +- if (ret) { +- if (state) +- *state = MC_STATUS_NOT_INITIALIZED; +- +- if (ext_info) +- *ext_info = 0; +- +- MCDRV_ERROR("code %d for idx %d", ret, ext_info_id); +- } else { +- if (state) +- *state = fc_info.as_out.state; +- +- if (ext_info) +- *ext_info = fc_info.as_out.ext_info; +- } +- +- return ret; +-} +- +-int mc_fc_mem_trace(phys_addr_t buffer, uint32_t size) +-{ +- union mc_fc_generic mc_fc_generic; +- +- memset(&mc_fc_generic, 0, sizeof(mc_fc_generic)); +- mc_fc_generic.as_in.cmd = MC_FC_MEM_TRACE; +- mc_fc_generic.as_in.param[0] = (uint32_t)buffer; +-#ifdef CONFIG_ARM64 +- mc_fc_generic.as_in.param[1] = (uint32_t)(buffer >> 32); +-#endif +- mc_fc_generic.as_in.param[2] = size; +- mc_fastcall(&mc_fc_generic); +- return convert_fc_ret(mc_fc_generic.as_out.ret); +-} +- +-int mc_fc_nsiq(void) +-{ +- union mc_fc_generic fc; +- int ret; +- +- memset(&fc, 0, sizeof(fc)); +- fc.as_in.cmd = MC_SMC_N_SIQ; +- mc_fastcall(&fc); +- ret = convert_fc_ret(fc.as_out.ret); +- if (ret) +- MCDRV_ERROR("failed: %d", ret); +- +- return ret; +-} +- +-int mc_fc_yield(void) +-{ +- union mc_fc_generic fc; +- int ret; +- +- memset(&fc, 0, sizeof(fc)); +- fc.as_in.cmd = MC_SMC_N_YIELD; +- mc_fastcall(&fc); +- ret = convert_fc_ret(fc.as_out.ret); +- if (ret) +- MCDRV_ERROR("failed: %d", ret); +- +- return ret; +-} +- +-#ifdef TBASE_CORE_SWITCHER +-uint32_t mc_active_core(void) +-{ +- return active_cpu; +-} +- +-int mc_switch_core(uint32_t core_num) +-{ +- int32_t ret = 0; +- union mc_fc_swich_core fc_switch_core; +- +- if (!cpu_online(core_num)) +- return 1; +- +- MCDRV_DBG_VERBOSE("enter\n"); +- memset(&fc_switch_core, 0, sizeof(fc_switch_core)); +- fc_switch_core.as_in.cmd = MC_FC_SWAP_CPU; +- if (core_num < COUNT_OF_CPUS) +- fc_switch_core.as_in.core_id = core_num; +- else +- fc_switch_core.as_in.core_id = 0; +- +- MCDRV_DBG("<- cmd=0x%08x, core_id=0x%08x\n", +- fc_switch_core.as_in.cmd, fc_switch_core.as_in.core_id); +- MCDRV_DBG("<- core_num=0x%08x, active_cpu=0x%08x\n", +- core_num, active_cpu); +- mc_fastcall(&fc_switch_core.as_generic); +- ret = convert_fc_ret(fc_switch_core.as_out.ret); +- MCDRV_DBG_VERBOSE("exit with %d/0x%08X\n", ret, ret); +- return ret; +-} +-#endif +diff --git a/drivers/gud/MobiCoreDriver/fastcall.h b/drivers/gud/MobiCoreDriver/fastcall.h +deleted file mode 100644 +index b19b27687ff38..0000000000000 +--- a/drivers/gud/MobiCoreDriver/fastcall.h ++++ /dev/null +@@ -1,38 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _TBASE_FASTCALL_H_ +-#define _TBASE_FASTCALL_H_ +- +-/* Use the arch_extension sec pseudo op before switching to secure world */ +-#if defined(__GNUC__) && \ +- defined(__GNUC_MINOR__) && \ +- defined(__GNUC_PATCHLEVEL__) && \ +- ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)) \ +- >= 40502 +-#ifndef CONFIG_ARM64 +-#define MC_ARCH_EXTENSION_SEC +-#endif +-#endif +- +-int mc_fc_init(uintptr_t base_pa, ptrdiff_t off, size_t q_len, size_t buf_len); +-int mc_fc_info(uint32_t ext_info_id, uint32_t *state, uint32_t *ext_info); +-int mc_fc_mem_trace(phys_addr_t buffer, uint32_t size); +-int mc_fc_nsiq(void); +-int mc_fc_yield(void); +- +-int mc_fastcall_init(void); +-void mc_fastcall_exit(void); +- +-#endif /* _TBASE_FASTCALL_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/logging.c b/drivers/gud/MobiCoreDriver/logging.c +deleted file mode 100644 +index 953de5f149f78..0000000000000 +--- a/drivers/gud/MobiCoreDriver/logging.c ++++ /dev/null +@@ -1,251 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#include +-#include +-#include +- +-#include "fastcall.h" +-#include "main.h" +-#include "logging.h" +- +-#ifndef CONFIG_TRUSTONIC_TEE_NO_TRACES +- +-/* Supported log buffer version */ +-#define MC_LOG_VERSION 2 +- +-/* Default length of the log ring buffer 256KiB */ +-#define LOG_BUF_ORDER 6 +- +-/* Max Len of a log line for printing */ +-#define LOG_LINE_SIZE 256 +- +-/* Definitions for log version 2 */ +-#define LOG_TYPE_MASK (0x0007) +-#define LOG_TYPE_CHAR 0 +-#define LOG_TYPE_INTEGER 1 +- +-/* Field length */ +-#define LOG_LENGTH_MASK (0x00F8) +-#define LOG_LENGTH_SHIFT 3 +- +-/* Extra attributes */ +-#define LOG_EOL (0x0100) +-#define LOG_INTEGER_DECIMAL (0x0200) +-#define LOG_INTEGER_SIGNED (0x0400) +- +-struct mc_logmsg { +- uint16_t ctrl; /* Type and format of data */ +- uint16_t source; /* Unique value for each event source */ +- uint32_t log_data; /* Value, if any */ +-}; +- +-/* MobiCore internal trace buffer structure. */ +-struct mc_trace_buf { +- uint32_t version; /* version of trace buffer */ +- uint32_t length; /* length of buff */ +- uint32_t head; /* last write position */ +- uint8_t buff[]; /* start of the log buffer */ +-}; +- +-static struct logging_ctx { +- struct work_struct work; +- union { +- struct mc_trace_buf *trace_buf; /* Circular log buffer */ +- unsigned long trace_page; +- }; +- bool buffer_is_shared; /* Log buffer cannot be freed */ +- uint32_t tail; /* MobiCore log read position */ +- uint32_t line_len; /* Log Line buffer current length */ +- int thread_err; +- uint16_t prev_source; /* Previous Log source */ +- char line[LOG_LINE_SIZE]; /* Log Line buffer */ +- bool dead; +-} log_ctx; +- +-static inline void log_eol(uint16_t source) +-{ +- if (!strnlen(log_ctx.line, LOG_LINE_SIZE)) { +- /* In case a TA tries to print a 0x0 */ +- log_ctx.line_len = 0; +- return; +- } +- +- if (log_ctx.prev_source) +- /* MobiCore Userspace */ +- dev_info(g_ctx.mcd, "%03x|%s\n", log_ctx.prev_source, +- log_ctx.line); +- else +- /* MobiCore kernel */ +- dev_info(g_ctx.mcd, "%s\n", log_ctx.line); +- +- log_ctx.line_len = 0; +- log_ctx.line[0] = 0; +-} +- +-/* +- * Collect chars in log_ctx.line buffer and output the buffer when it is full. +- * No locking needed because only "mobicore_log" thread updates this buffer. +- */ +-static inline void log_char(char ch, uint16_t source) +-{ +- if (ch == '\n' || ch == '\r') { +- log_eol(source); +- return; +- } +- +- if ((log_ctx.line_len >= (LOG_LINE_SIZE - 1)) || +- (source != log_ctx.prev_source)) +- log_eol(source); +- +- log_ctx.line[log_ctx.line_len++] = ch; +- log_ctx.line[log_ctx.line_len] = 0; +- log_ctx.prev_source = source; +-} +- +-static inline void log_string(uint32_t ch, uint16_t source) +-{ +- while (ch) { +- log_char(ch & 0xFF, source); +- ch >>= 8; +- } +-} +- +-static inline void log_number(uint32_t format, uint32_t value, uint16_t source) +-{ +- int width = (format & LOG_LENGTH_MASK) >> LOG_LENGTH_SHIFT; +- char fmt[16]; +- char buffer[32]; +- const char *reader = buffer; +- +- if (format & LOG_INTEGER_DECIMAL) +- if (format & LOG_INTEGER_SIGNED) +- snprintf(fmt, sizeof(fmt), "%%%ud", width); +- else +- snprintf(fmt, sizeof(fmt), "%%%uu", width); +- else +- snprintf(fmt, sizeof(fmt), "%%0%ux", width); +- +- snprintf(buffer, sizeof(buffer), fmt, value); +- while (*reader) +- log_char(*reader++, source); +-} +- +-static inline int log_msg(void *data) +-{ +- struct mc_logmsg *msg = (struct mc_logmsg *)data; +- int log_type = msg->ctrl & LOG_TYPE_MASK; +- +- switch (log_type) { +- case LOG_TYPE_CHAR: +- log_string(msg->log_data, msg->source); +- break; +- case LOG_TYPE_INTEGER: +- log_number(msg->ctrl, msg->log_data, msg->source); +- break; +- } +- if (msg->ctrl & LOG_EOL) +- log_eol(msg->source); +- +- return sizeof(*msg); +-} +- +-static void log_worker(struct work_struct *work) +-{ +- while (log_ctx.trace_buf->head != log_ctx.tail) { +- if (log_ctx.trace_buf->version != MC_LOG_VERSION) { +- dev_err(g_ctx.mcd, +- "Bad log data v%d (exp. v%d), stop.\n", +- log_ctx.trace_buf->version, +- MC_LOG_VERSION); +- log_ctx.dead = true; +- break; +- } +- +- log_ctx.tail += log_msg(&log_ctx.trace_buf->buff[log_ctx.tail]); +- /* Wrap over if no space left for a complete message */ +- if ((log_ctx.tail + sizeof(struct mc_logmsg)) > +- log_ctx.trace_buf->length) +- log_ctx.tail = 0; +- } +-} +- +-/* +- * Wake up the log reader thread +- * This should be called from the places where calls into MobiCore have +- * generated some logs(eg, yield, SIQ...) +- */ +-void mc_logging_run(void) +-{ +- if (!log_ctx.dead && (log_ctx.trace_buf->head != log_ctx.tail)) +- schedule_work(&log_ctx.work); +-} +- +-int mc_logging_start(void) +-{ +- int ret = mc_fc_mem_trace(virt_to_phys((void *)(log_ctx.trace_page)), +- BIT(LOG_BUF_ORDER) * PAGE_SIZE); +- +- if (ret) { +- dev_err(g_ctx.mcd, "shared traces setup failed\n"); +- return ret; +- } +- +- log_ctx.buffer_is_shared = true; +- dev_dbg(g_ctx.mcd, "fc_log version %u\n", log_ctx.trace_buf->version); +- mc_logging_run(); +- return 0; +-} +- +-void mc_logging_stop(void) +-{ +- if (!mc_fc_mem_trace(0, 0)) +- log_ctx.buffer_is_shared = false; +- +- mc_logging_run(); +- flush_work(&log_ctx.work); +-} +- +-/* +- * Setup MobiCore kernel log. It assumes it's running on CORE 0! +- * The fastcall will complain is that is not the case! +- */ +-int mc_logging_init(void) +-{ +- /* +- * We are going to map this buffer into virtual address space in SWd. +- * To reduce complexity there, we use a contiguous buffer. +- */ +- log_ctx.trace_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, +- LOG_BUF_ORDER); +- if (!log_ctx.trace_page) +- return -ENOMEM; +- +- INIT_WORK(&log_ctx.work, log_worker); +- return 0; +-} +- +-void mc_logging_exit(void) +-{ +- /* +- * This is not racey as the only caller for mc_logging_run is the +- * scheduler which gets stopped before us, and long before we exit. +- */ +- if (!log_ctx.buffer_is_shared) +- free_pages(log_ctx.trace_page, LOG_BUF_ORDER); +- else +- dev_err(g_ctx.mcd, "log buffer unregister not supported\n"); +-} +- +-#endif /* !CONFIG_TRUSTONIC_TEE_NO_TRACES */ +diff --git a/drivers/gud/MobiCoreDriver/logging.h b/drivers/gud/MobiCoreDriver/logging.h +deleted file mode 100644 +index 744b41880ea31..0000000000000 +--- a/drivers/gud/MobiCoreDriver/logging.h ++++ /dev/null +@@ -1,51 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#ifndef _MC_LOGGING_H_ +-#define _MC_LOGGING_H_ +- +-#include "platform.h" /* CONFIG_TRUSTONIC_TEE_NO_TRACES */ +- +-/* MobiCore internal trace log setup. */ +-#ifndef CONFIG_TRUSTONIC_TEE_NO_TRACES +-void mc_logging_run(void); +-int mc_logging_init(void); +-void mc_logging_exit(void); +-int mc_logging_start(void); +-void mc_logging_stop(void); +-#else /* !CONFIG_TRUSTONIC_TEE_NO_TRACES */ +-static inline void mc_logging_run(void) +-{ +-} +- +-static inline long mc_logging_init(void) +-{ +- return 0; +-} +- +-static inline void mc_logging_exit(void) +-{ +-} +- +-static inline int mc_logging_start(void) +-{ +- return 0; +-} +- +-static inline void mc_logging_stop(void) +-{ +-} +- +-#endif /* CONFIG_TRUSTONIC_TEE_NO_TRACES */ +- +-#endif /* _MC_LOGGING_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/main.c b/drivers/gud/MobiCoreDriver/main.c +deleted file mode 100644 +index 66b232e5bc8b5..0000000000000 +--- a/drivers/gud/MobiCoreDriver/main.c ++++ /dev/null +@@ -1,750 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +- +-#include "main.h" +-#include "fastcall.h" +-#include "arm.h" +-#include "mmu.h" +-#include "scheduler.h" +-#include "pm.h" +-#include "debug.h" +-#include "logging.h" +-#include "admin.h" +-#include "mcp.h" +-#include "session.h" +-#include "client.h" +-#include "api.h" +- +-#include "build_tag.h" +- +-/* Define a MobiCore device structure for use with dev_debug() etc */ +-static struct device_driver driver = { +- .name = "Trustonic" +-}; +- +-static struct device device = { +- .driver = &driver +-}; +- +-struct mc_device_ctx g_ctx = { +- .mcd = &device +-}; +- +-/* device admin */ +-static dev_t mc_dev_admin; +-/* device user */ +-static dev_t mc_dev_user; +- +-/* Need to discover a chrdev region for the driver */ +-static struct cdev mc_user_cdev; +-/* Device class for the driver assigned major */ +-static struct class *mc_device_class; +- +-/* +- * Get client object from file pointer +- */ +-static inline struct tbase_client *get_client(struct file *file) +-{ +- return (struct tbase_client *)file->private_data; +-} +- +-/* +- * Callback for system mmap() +- */ +-static int mc_fd_user_mmap(struct file *file, struct vm_area_struct *vmarea) +-{ +- struct tbase_client *client = get_client(file); +- uint32_t len = (uint32_t)(vmarea->vm_end - vmarea->vm_start); +- +- /* Alloc contiguous buffer for this client */ +- return api_malloc_cbuf(client, len, NULL, vmarea); +-} +- +-/* +- * Check r/w access to referenced memory +- */ +-static inline int ioctl_check_pointer(unsigned int cmd, int __user *uarg) +-{ +- int err = 0; +- +- if (_IOC_DIR(cmd) & _IOC_READ) +- err = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd)); +- else if (_IOC_DIR(cmd) & _IOC_WRITE) +- err = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd)); +- +- if (err) +- return -EFAULT; +- +- return 0; +-} +- +-/* +- * Callback for system ioctl() +- * Implement most of ClientLib API functions +- * @file pointer to file +- * @cmd command +- * @arg arguments +- * +- * Returns 0 for OK and an errno in case of error +- */ +-static long mc_fd_user_ioctl(struct file *file, unsigned int id, +- unsigned long arg) +-{ +- struct tbase_client *client = get_client(file); +- int __user *uarg = (int __user *)arg; +- int ret = -EINVAL; +- +- MCDRV_DBG("%u from %s", _IOC_NR(id), current->comm); +- +- if (WARN(!client, "No client data available")) +- return -EPROTO; +- +- if (ioctl_check_pointer(id, uarg)) +- return -EFAULT; +- +- switch (id) { +- case MC_IO_FREEZE: +- /* Freeze the client */ +- ret = api_freeze_device(client); +- break; +- +- case MC_IO_OPEN_SESSION: { +- struct mc_ioctl_open_sess sess; +- +- if (copy_from_user(&sess, uarg, sizeof(sess))) { +- ret = -EFAULT; +- break; +- } +- +- ret = api_open_session(client, &sess.sid, &sess.uuid, sess.tci, +- sess.tcilen, sess.is_gp_uuid, +- &sess.identity); +- if (ret) +- break; +- +- if (copy_to_user(uarg, &sess, sizeof(sess))) { +- ret = -EFAULT; +- api_close_session(client, sess.sid); +- break; +- } +- break; +- } +- case MC_IO_OPEN_TRUSTLET: { +- struct mc_ioctl_open_trustlet ta_desc; +- +- if (copy_from_user(&ta_desc, uarg, sizeof(ta_desc))) { +- ret = -EFAULT; +- break; +- } +- +- /* Call internal api */ +- ret = api_open_trustlet(client, &ta_desc.sid, ta_desc.spid, +- ta_desc.buffer, ta_desc.tlen, +- ta_desc.tci, ta_desc.tcilen); +- if (ret) +- break; +- +- if (copy_to_user(uarg, &ta_desc, sizeof(ta_desc))) { +- ret = -EFAULT; +- api_close_session(client, ta_desc.sid); +- break; +- } +- break; +- } +- case MC_IO_CLOSE_SESSION: { +- uint32_t sid = (uint32_t)arg; +- +- ret = api_close_session(client, sid); +- break; +- } +- case MC_IO_NOTIFY: { +- uint32_t sid = (uint32_t)arg; +- +- ret = api_notify(client, sid); +- break; +- } +- case MC_IO_WAIT: { +- struct mc_ioctl_wait wait; +- +- if (copy_from_user(&wait, uarg, sizeof(wait))) { +- ret = -EFAULT; +- break; +- } +- ret = api_wait_notification(client, wait.sid, wait.timeout); +- break; +- } +- case MC_IO_MAP: { +- struct mc_ioctl_map map; +- +- if (copy_from_user(&map, uarg, sizeof(map))) { +- ret = -EFAULT; +- break; +- } +- ret = api_map_wsms(client, map.sid, map.bufs); +- if (ret) +- break; +- +- /* Fill in return struct */ +- if (copy_to_user(uarg, &map, sizeof(map))) { +- ret = -EFAULT; +- api_unmap_wsms(client, map.sid, map.bufs); +- break; +- } +- break; +- } +- case MC_IO_UNMAP: { +- struct mc_ioctl_map map; +- +- if (copy_from_user(&map, uarg, sizeof(map))) { +- ret = -EFAULT; +- break; +- } +- +- ret = api_unmap_wsms(client, map.sid, map.bufs); +- break; +- } +- case MC_IO_ERR: { +- struct mc_ioctl_geterr *uerr = (struct mc_ioctl_geterr *)uarg; +- uint32_t sid; +- int32_t exit_code; +- +- if (get_user(sid, &uerr->sid)) { +- ret = -EFAULT; +- break; +- } +- +- ret = api_get_session_exitcode(client, sid, &exit_code); +- if (ret) +- break; +- +- /* Fill in return struct */ +- if (put_user(exit_code, &uerr->value)) { +- ret = -EFAULT; +- break; +- } +- +- break; +- } +- case MC_IO_VERSION: { +- struct mc_version_info version_info; +- +- ret = mcp_get_version(&version_info); +- if (ret) +- break; +- +- if (copy_to_user(uarg, &version_info, sizeof(version_info))) +- ret = -EFAULT; +- +- break; +- } +- case MC_IO_DR_VERSION: { +- uint32_t version = MC_VERSION(MCDRVMODULEAPI_VERSION_MAJOR, +- MCDRVMODULEAPI_VERSION_MINOR); +- +- ret = put_user(version, uarg); +- break; +- } +- default: +- MCDRV_ERROR("unsupported cmd=0x%x", id); +- ret = -ENOIOCTLCMD; +- } +- +- return ret; +-} +- +-/* +- * Callback for system open() +- * A set of internal client data are created and initialized. +- * +- * @inode +- * @file +- * Returns 0 if OK or -ENOMEM if no allocation was possible. +- */ +-static int mc_fd_user_open(struct inode *inode, struct file *file) +-{ +- struct tbase_client *client; +- +- MCDRV_DBG("from %s", current->comm); +- +- /* Create client */ +- client = api_open_device(false); +- if (!client) +- return -ENOMEM; +- +- /* Store client in user file */ +- file->private_data = client; +- return 0; +-} +- +-/* +- * Callback for system close() +- * The client object is freed. +- * @inode +- * @file +- * Returns 0 +- */ +-static int mc_fd_user_release(struct inode *inode, struct file *file) +-{ +- struct tbase_client *client = get_client(file); +- +- MCDRV_DBG("from %s", current->comm); +- +- if (WARN(!client, "No client data available")) +- return -EPROTO; +- +- /* Detach client from user file */ +- file->private_data = NULL; +- +- /* Destroy client, including remaining sessions */ +- api_close_device(client); +- return 0; +-} +- +-static const struct file_operations mc_user_fops = { +- .owner = THIS_MODULE, +- .open = mc_fd_user_open, +- .release = mc_fd_user_release, +- .unlocked_ioctl = mc_fd_user_ioctl, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = mc_fd_user_ioctl, +-#endif +- .mmap = mc_fd_user_mmap, +-}; +- +-int kasnprintf(struct kasnprintf_buf *buf, const char *fmt, ...) +-{ +- va_list args; +- int max_size = buf->size - buf->off; +- int i; +- +- va_start(args, fmt); +- i = vsnprintf(buf->buf + buf->off, max_size, fmt, args); +- if (i >= max_size) { +- int new_size = PAGE_ALIGN(buf->size + i + 1); +- char *new_buf = krealloc(buf->buf, new_size, buf->gfp); +- +- if (!new_buf) { +- i = -ENOMEM; +- } else { +- buf->buf = new_buf; +- buf->size = new_size; +- max_size = buf->size - buf->off; +- i = vsnprintf(buf->buf + buf->off, max_size, fmt, args); +- } +- } +- +- if (i > 0) +- buf->off += i; +- +- va_end(args); +- return i; +-} +- +-static ssize_t debug_info_read(struct file *file, char __user *user_buf, +- size_t count, loff_t *ppos) +-{ +- /* Add/update buffer */ +- if (!file->private_data || !*ppos) { +- struct kasnprintf_buf *buf, *old_buf; +- int ret; +- +- buf = kzalloc(GFP_KERNEL, sizeof(*buf)); +- if (!buf) +- return -ENOMEM; +- +- buf->gfp = GFP_KERNEL; +- ret = api_info(buf); +- if (ret < 0) { +- kfree(buf); +- return ret; +- } +- +- old_buf = file->private_data; +- file->private_data = buf; +- kfree(old_buf); +- } +- +- if (file->private_data) { +- struct kasnprintf_buf *buf = file->private_data; +- +- return simple_read_from_buffer(user_buf, count, ppos, buf->buf, +- buf->off); +- } +- +- return 0; +-} +- +-static int debug_info_release(struct inode *inode, struct file *file) +-{ +- kfree(file->private_data); +- return 0; +-} +- +-static const struct file_operations mc_debug_info_ops = { +- .read = debug_info_read, +- .llseek = default_llseek, +- .release = debug_info_release, +-}; +- +-static inline int device_admin_init(int (*tee_start_cb)(void)) +-{ +- int ret = 0; +- +- cdev_init(&mc_user_cdev, &mc_user_fops); +- +- mc_device_class = class_create(THIS_MODULE, "trustonic_tee"); +- if (IS_ERR(mc_device_class)) { +- MCDRV_ERROR("failed to create device class"); +- return PTR_ERR(mc_device_class); +- } +- +- /* Create the ADMIN node */ +- ret = mc_admin_init(mc_device_class, &mc_dev_admin, tee_start_cb); +- if (ret < 0) { +- MCDRV_ERROR("failed to init mobicore device"); +- class_destroy(mc_device_class); +- return ret; +- } +- return 0; +-} +- +-static inline int device_user_init(void) +-{ +- int ret = 0; +- struct device *dev; +- +- mc_dev_user = MKDEV(MAJOR(mc_dev_admin), 1); +- /* Create the user node */ +- ret = cdev_add(&mc_user_cdev, mc_dev_user, 1); +- if (ret) { +- MCDRV_ERROR("user device register failed"); +- goto err_cdev_add; +- } +- mc_user_cdev.owner = THIS_MODULE; +- dev = device_create(mc_device_class, NULL, mc_dev_user, NULL, +- MC_USER_DEVNODE); +- if (IS_ERR(dev)) { +- ret = PTR_ERR(dev); +- goto err_device_create; +- } +- +- /* Create debugfs info entry */ +- debugfs_create_file("info", 0400, g_ctx.debug_dir, NULL, +- &mc_debug_info_ops); +- +- return 0; +- +-err_device_create: +- cdev_del(&mc_user_cdev); +-err_cdev_add: +- mc_admin_exit(mc_device_class); +- class_destroy(mc_device_class); +- MCDRV_DBG("failed with %d", ret); +- return ret; +-} +- +-static void devices_exit(void) +-{ +- device_destroy(mc_device_class, mc_dev_user); +- cdev_del(&mc_user_cdev); +- mc_admin_exit(mc_device_class); +- class_destroy(mc_device_class); +-} +- +-static inline int mobicore_start(void) +-{ +- int ret; +- struct mc_version_info version_info; +- +- ret = mcp_start(); +- if (ret) { +- MCDRV_ERROR("TEE start failed"); +- goto err_mcp; +- } +- +- ret = mc_logging_start(); +- if (ret) { +- MCDRV_ERROR("Log start failed"); +- goto err_log; +- } +- +- ret = mc_scheduler_start(); +- if (ret) { +- MCDRV_ERROR("Scheduler start failed"); +- goto err_sched; +- } +- +- ret = mc_pm_start(); +- if (ret) { +- MCDRV_ERROR("Power Management start failed"); +- goto err_pm; +- } +- +- ret = mcp_get_version(&version_info); +- if (ret) +- goto err_mcp_cmd; +- +- MCDRV_DBG("\n" +- " product_id = %s\n" +- " version_so = 0x%x\n" +- " version_mci = 0x%x\n" +- " version_mclf = 0x%x\n" +- " version_container = 0x%x\n" +- " version_mc_config = 0x%x\n" +- " version_tl_api = 0x%x\n" +- " version_dr_api = 0x%x\n" +- " version_cmp = 0x%x\n", +- version_info.product_id, +- version_info.version_mci, +- version_info.version_so, +- version_info.version_mclf, +- version_info.version_container, +- version_info.version_mc_config, +- version_info.version_tl_api, +- version_info.version_dr_api, +- version_info.version_cmp); +- +- if (MC_VERSION_MAJOR(version_info.version_mci) > 1) { +- pr_err("MCI version %d.%d is too recent for this driver", +- MC_VERSION_MAJOR(version_info.version_mci), +- MC_VERSION_MINOR(version_info.version_mci)); +- goto err_version; +- } +- +- if ((MC_VERSION_MAJOR(version_info.version_mci) == 0) && +- (MC_VERSION_MINOR(version_info.version_mci) < 6)) { +- pr_err("MCI version %d.%d is too old for this driver", +- MC_VERSION_MAJOR(version_info.version_mci), +- MC_VERSION_MINOR(version_info.version_mci)); +- goto err_version; +- } +- +- dev_info(g_ctx.mcd, "MobiCore MCI version is %d.%d\n", +- MC_VERSION_MAJOR(version_info.version_mci), +- MC_VERSION_MINOR(version_info.version_mci)); +- +- /* Determine which features are supported */ +- switch (version_info.version_mci) { +- case MC_VERSION(1, 2): /* 310 */ +- g_ctx.f_client_login = true; +- /* Fall through */ +- case MC_VERSION(1, 1): +- g_ctx.f_multimap = true; +- /* Fall through */ +- case MC_VERSION(1, 0): /* 302 */ +- g_ctx.f_mem_ext = true; +- g_ctx.f_ta_auth = true; +- /* Fall through */ +- case MC_VERSION(0, 7): +- g_ctx.f_timeout = true; +- /* Fall through */ +- case MC_VERSION(0, 6): /* 301 */ +- break; +- } +- +- ret = device_user_init(); +- if (ret) +- goto err_create_dev_user; +- +- return 0; +- +-err_create_dev_user: +-err_version: +-err_mcp_cmd: +- mc_pm_stop(); +-err_pm: +- mc_scheduler_stop(); +-err_sched: +- mc_logging_stop(); +-err_log: +- mcp_stop(); +-err_mcp: +- return ret; +-} +- +-static inline void mobicore_stop(void) +-{ +- mc_pm_stop(); +- mc_scheduler_stop(); +- mc_logging_stop(); +- mcp_stop(); +-} +- +-/* +- * This function is called by the kernel during startup or by a insmod command. +- * This device is installed and registered as cdev, then interrupt and +- * queue handling is set up +- */ +-static int mobicore_init(void) +-{ +- int err = 0; +- +- dev_set_name(g_ctx.mcd, "TEE"); +- +- /* Do not remove or change the following trace. +- * The string "MobiCore" is used to detect if Cannot continue! */ +- if (!has_security_extensions()) { +- MCDRV_ERROR("Hardware doesn't support ARM TrustZone!"); +- return -ENODEV; +- } +- +- /* Running in secure mode -> Cannot load the driver! */ +- if (is_secure_mode()) { +- MCDRV_ERROR("Running in secure MODE!"); +- return -ENODEV; +- } +- +- /* Init common API layer */ +- api_init(); +- +- /* Init plenty of nice features */ +- err = mc_fastcall_init(); +- if (err) { +- MCDRV_ERROR("Fastcall support init failed!"); +- goto fail_fastcall_init; +- } +- +- err = mcp_init(); +- if (err) { +- MCDRV_ERROR("MCP init failed!"); +- goto fail_mcp_init; +- } +- +- err = mc_logging_init(); +- if (err) { +- MCDRV_ERROR("Log init failed!"); +- goto fail_log_init; +- } +- +- /* The scheduler is the first to create a debugfs entry */ +- g_ctx.debug_dir = debugfs_create_dir("trustonic_tee", NULL); +- err = mc_scheduler_init(); +- if (err) { +- MCDRV_ERROR("Scheduler init failed!"); +- goto fail_mc_device_sched_init; +- } +- +- /* +- * Create admin dev so that daemon can already communicate with +- * the driver +- */ +- err = device_admin_init(mobicore_start); +- if (err) +- goto fail_creat_dev_admin; +- +- return 0; +- +-fail_creat_dev_admin: +- mc_scheduler_exit(); +-fail_mc_device_sched_init: +- debugfs_remove(g_ctx.debug_dir); +- mc_logging_exit(); +-fail_log_init: +- mcp_exit(); +-fail_mcp_init: +- mc_fastcall_exit(); +-fail_fastcall_init: +- return err; +-} +- +-/* +- * This function removes this device driver from the Linux device manager . +- */ +-static void mobicore_exit(void) +-{ +- MCDRV_DBG("enter"); +- +- devices_exit(); +- mobicore_stop(); +- mc_scheduler_exit(); +- mc_logging_exit(); +- mcp_exit(); +- mc_fastcall_exit(); +- debugfs_remove_recursive(g_ctx.debug_dir); +- +- MCDRV_DBG("exit"); +-} +- +-/* Linux Driver Module Macros */ +- +-#ifdef MC_DEVICE_PROPNAME +- +-static int mobicore_probe(struct platform_device *pdev) +-{ +- g_ctx.mcd->of_node = pdev->dev.of_node; +- mobicore_init(); +- return 0; +-} +- +-static const struct of_device_id of_match_table[] = { +- { .compatible = MC_DEVICE_PROPNAME }, +- { } +-}; +- +-static struct platform_driver mc_plat_driver = { +- .probe = mobicore_probe, +- .driver = { +- .name = "mcd", +- .owner = THIS_MODULE, +- .of_match_table = of_match_table, +- } +-}; +- +-static int mobicore_register(void) +-{ +- return platform_driver_register(&mc_plat_driver); +-} +- +-static void mobicore_unregister(void) +-{ +- platform_driver_unregister(&mc_plat_driver); +- mobicore_exit(); +-} +- +-module_init(mobicore_register); +-module_exit(mobicore_unregister); +- +-#else /* MC_DEVICE_PROPNAME */ +- +-module_init(mobicore_init); +-module_exit(mobicore_exit); +- +-#endif /* !MC_DEVICE_PROPNAME */ +- +-MODULE_AUTHOR("Trustonic Limited"); +-MODULE_LICENSE("GPL v2"); +-MODULE_DESCRIPTION("MobiCore driver"); +diff --git a/drivers/gud/MobiCoreDriver/main.h b/drivers/gud/MobiCoreDriver/main.h +deleted file mode 100644 +index cadc3d766147a..0000000000000 +--- a/drivers/gud/MobiCoreDriver/main.h ++++ /dev/null +@@ -1,60 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _MC_MAIN_H_ +-#define _MC_MAIN_H_ +- +-#include /* gfp_t */ +- +-#define MC_VERSION(major, minor) \ +- (((major & 0x0000ffff) << 16) | (minor & 0x0000ffff)) +-#define MC_VERSION_MAJOR(x) ((x) >> 16) +-#define MC_VERSION_MINOR(x) ((x) & 0xffff) +- +-/* MobiCore Driver Kernel Module context data. */ +-struct mc_device_ctx { +- struct device *mcd; +- /* debugfs root */ +- struct dentry *debug_dir; +- +- /* GP sessions waiting final close notif */ +- struct list_head closing_sess; +- struct mutex closing_lock; /* Closing sessions list */ +- +- /* Features */ +- /* - SWd can set a time out to get scheduled at a future time */ +- bool f_timeout; +- /* - SWd supports memory extension which allows for bigger TAs */ +- bool f_mem_ext; +- /* - SWd supports TA authorisation */ +- bool f_ta_auth; +- /* - SWd can map several buffers at once */ +- bool f_multimap; +- /* - SWd supports GP client authentication */ +- bool f_client_login; +-}; +- +-extern struct mc_device_ctx g_ctx; +- +-struct kasnprintf_buf { +- gfp_t gfp; +- void *buf; +- int size; +- int off; +-}; +- +-extern __printf(2, 3) +-int kasnprintf(struct kasnprintf_buf *buf, const char *fmt, ...); +- +-#endif /* _MC_MAIN_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/mci/mcifc.h b/drivers/gud/MobiCoreDriver/mci/mcifc.h +deleted file mode 100644 +index 4848c9e047fba..0000000000000 +--- a/drivers/gud/MobiCoreDriver/mci/mcifc.h ++++ /dev/null +@@ -1,144 +0,0 @@ +-/* +- * Copyright (c) 2013-2014 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#ifndef MCIFC_H_ +-#define MCIFC_H_ +- +-#include "platform.h" +- +-/** @name MobiCore FastCall Defines +- * Defines for the two different FastCall's. +- */ +-/** @{ */ +- +-#include "platform.h" +- +-/* --- global ---- */ +-#define MC_FC_INVALID ((uint32_t)0) /**< Invalid FastCall ID */ +- +-#if defined(CONFIG_ARM64) && !defined(MC_ARMV7_FC) +- +-/* These should be handled as 64-bit FCs; now they are more like 32bits... */ +-#define MC_FC_STD64_BASE ((uint32_t)0xFF000000) +-#define MC_FC_STD64(x) ((uint32_t)(MC_FC_STD64_BASE + (x))) +- +-#define MC_FC_INIT MC_FC_STD64(1) /**< Initializing FastCall. */ +-#define MC_FC_INFO MC_FC_STD64(2) /**< Info FastCall. */ +-#define MC_FC_MEM_TRACE MC_FC_STD64(10) /**< Enable SWd tracing via memory */ +-#define MC_FC_SWAP_CPU MC_FC_STD64(54) /**< Change new active Core */ +- +-#else +- +-#define MC_FC_INIT ((uint32_t)(-1)) /**< Initializing FastCall. */ +-#define MC_FC_INFO ((uint32_t)(-2)) /**< Info FastCall. */ +-#define MC_FC_MEM_TRACE ((uint32_t)(-31)) /**< Enable SWd tracing via memory */ +-#define MC_FC_SWAP_CPU ((uint32_t)(0x84000005)) /**< Change new active Core */ +- +-#endif +- +-/** @} */ +- +-/** @name MobiCore SMC Defines +- * Defines the different secure monitor calls (SMC) for world switching. +- * @{ */ +-/**< Yield to switch from NWd to SWd. */ +-#define MC_SMC_N_YIELD 3 +-/**< SIQ to switch from NWd to SWd. */ +-#define MC_SMC_N_SIQ 4 +-/** @} */ +- +-/** @name MobiCore status +- * MobiCore status information. +- * @{ */ +-/**< MobiCore is not yet initialized. FastCall FcInit() to set up MobiCore.*/ +-#define MC_STATUS_NOT_INITIALIZED 0 +-/**< Bad parameters have been passed in FcInit(). */ +-#define MC_STATUS_BAD_INIT 1 +-/**< MobiCore did initialize properly. */ +-#define MC_STATUS_INITIALIZED 2 +-/**< MobiCore kernel halted due to an unrecoverable exception. Further +- * information is available extended info */ +-#define MC_STATUS_HALT 3 +-/** @} */ +- +-/** @name Extended Info Identifiers +- * Extended info parameters for MC_FC_INFO to obtain further information depending on MobiCore state. +- * @{ */ +-/**< Version of the MobiCore Control Interface (MCI) */ +-#define MC_EXT_INFO_ID_MCI_VERSION 0 +-/**< MobiCore control flags */ +-#define MC_EXT_INFO_ID_FLAGS 1 +-/**< MobiCore halt condition code */ +-#define MC_EXT_INFO_ID_HALT_CODE 2 +-/**< MobiCore halt condition instruction pointer */ +-#define MC_EXT_INFO_ID_HALT_IP 3 +-/**< MobiCore fault counter */ +-#define MC_EXT_INFO_ID_FAULT_CNT 4 +-/**< MobiCore last fault cause */ +-#define MC_EXT_INFO_ID_FAULT_CAUSE 5 +-/**< MobiCore last fault meta */ +-#define MC_EXT_INFO_ID_FAULT_META 6 +-/**< MobiCore last fault threadid */ +-#define MC_EXT_INFO_ID_FAULT_THREAD 7 +-/**< MobiCore last fault instruction pointer */ +-#define MC_EXT_INFO_ID_FAULT_IP 8 +-/**< MobiCore last fault stack pointer */ +-#define MC_EXT_INFO_ID_FAULT_SP 9 +-/**< MobiCore last fault ARM arch information */ +-#define MC_EXT_INFO_ID_FAULT_ARCH_DFSR 10 +-/**< MobiCore last fault ARM arch information */ +-#define MC_EXT_INFO_ID_FAULT_ARCH_ADFSR 11 +-/**< MobiCore last fault ARM arch information */ +-#define MC_EXT_INFO_ID_FAULT_ARCH_DFAR 12 +-/**< MobiCore last fault ARM arch information */ +-#define MC_EXT_INFO_ID_FAULT_ARCH_IFSR 13 +-/**< MobiCore last fault ARM arch information */ +-#define MC_EXT_INFO_ID_FAULT_ARCH_AIFSR 14 +-/**< MobiCore last fault ARM arch information */ +-#define MC_EXT_INFO_ID_FAULT_ARCH_IFAR 15 +-/**< MobiCore configured by Daemon via fc_init flag */ +-#define MC_EXT_INFO_ID_MC_CONFIGURED 16 +-/**< MobiCore scheduling status: idle/non-idle */ +-#define MC_EXT_INFO_ID_MC_SCHED_STATUS 17 +-/**< MobiCore runtime status: initialized, halted */ +-#define MC_EXT_INFO_ID_MC_STATUS 18 +-/**< MobiCore exception handler last partner */ +-#define MC_EXT_INFO_ID_MC_EXC_PARTNER 19 +-/**< MobiCore exception handler last peer */ +-#define MC_EXT_INFO_ID_MC_EXC_IPCPEER 20 +-/**< MobiCore exception handler last IPC message */ +-#define MC_EXT_INFO_ID_MC_EXC_IPCMSG 21 +-/**< MobiCore exception handler last IPC data */ +-#define MC_EXT_INFO_ID_MC_EXC_IPCDATA 22 +-/**< MobiCore exception handler last UUID (uses 4 slots: 23 to 26) */ +-#define MC_EXT_INFO_ID_MC_EXC_UUID 23 +-#define MC_EXT_INFO_ID_MC_EXC_UUID1 24 +-#define MC_EXT_INFO_ID_MC_EXC_UUID2 25 +-#define MC_EXT_INFO_ID_MC_EXC_UUID3 26 +- +-/** @} */ +- +-/** @name FastCall return values +- * Return values of the MobiCore FastCalls. +- * @{ */ +-/**< No error. Everything worked fine. */ +-#define MC_FC_RET_OK 0 +-/**< FastCall was not successful. */ +-#define MC_FC_RET_ERR_INVALID 1 +-/**< MobiCore has already been initialized. */ +-#define MC_FC_RET_ERR_ALREADY_INITIALIZED 5 +-/** @} */ +- +-#endif /** MCIFC_H_ */ +- +-/** @} */ +diff --git a/drivers/gud/MobiCoreDriver/mci/mcimcp.h b/drivers/gud/MobiCoreDriver/mci/mcimcp.h +deleted file mode 100644 +index 3eb2efea2c30c..0000000000000 +--- a/drivers/gud/MobiCoreDriver/mci/mcimcp.h ++++ /dev/null +@@ -1,508 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef MCP_H_ +-#define MCP_H_ +- +-#include "mci/mcloadformat.h" +- +-/** Indicates a response */ +-#define FLAG_RESPONSE BIT(31) +- +-/** Maximum number of buffers that can be mapped at once */ +-#define MCP_MAP_MAX_BUF 4 +- +-/** MobiCore Return Code Defines. +- * List of the possible MobiCore return codes. +- */ +-enum mcp_result { +- /** Memory has successfully been mapped */ +- MC_MCP_RET_OK = 0, +- /** The session ID is invalid */ +- MC_MCP_RET_ERR_INVALID_SESSION = 1, +- /** The UUID of the Trustlet is unknown */ +- MC_MCP_RET_ERR_UNKNOWN_UUID = 2, +- /** The ID of the driver is unknown */ +- MC_MCP_RET_ERR_UNKNOWN_DRIVER_ID = 3, +- /** No more session are allowed */ +- MC_MCP_RET_ERR_NO_MORE_SESSIONS = 4, +- /** The container is invalid */ +- MC_MCP_RET_ERR_CONTAINER_INVALID = 5, +- /** The Trustlet is invalid */ +- MC_MCP_RET_ERR_TRUSTLET_INVALID = 6, +- /** The memory block has already been mapped before */ +- MC_MCP_RET_ERR_ALREADY_MAPPED = 7, +- /** Alignment or length error in the command parameters */ +- MC_MCP_RET_ERR_INVALID_PARAM = 8, +- /** No space left in the virtual address space of the session */ +- MC_MCP_RET_ERR_OUT_OF_RESOURCES = 9, +- /** WSM type unknown or broken WSM */ +- MC_MCP_RET_ERR_INVALID_WSM = 10, +- /** unknown error */ +- MC_MCP_RET_ERR_UNKNOWN = 11, +- /** Length of map invalid */ +- MC_MCP_RET_ERR_INVALID_MAPPING_LENGTH = 12, +- /** Map can only be applied to Trustlet session */ +- MC_MCP_RET_ERR_MAPPING_TARGET = 13, +- /** Couldn't open crypto session */ +- MC_MCP_RET_ERR_OUT_OF_CRYPTO_RESOURCES = 14, +- /** System Trustlet signature verification failed */ +- MC_MCP_RET_ERR_SIGNATURE_VERIFICATION_FAILED = 15, +- /** System Trustlet public key is wrong */ +- MC_MCP_RET_ERR_WRONG_PUBLIC_KEY = 16, +- /** Wrong containter type(s) */ +- MC_MCP_RET_ERR_CONTAINER_TYPE_MISMATCH = 17, +- /** Container is locked (or not activated) */ +- MC_MCP_RET_ERR_CONTAINER_LOCKED = 18, +- /** SPID is not registered with root container */ +- MC_MCP_RET_ERR_SP_NO_CHILD = 19, +- /** UUID is not registered with sp container */ +- MC_MCP_RET_ERR_TL_NO_CHILD = 20, +- /** Unwrapping of root container failed */ +- MC_MCP_RET_ERR_UNWRAP_ROOT_FAILED = 21, +- /** Unwrapping of service provider container failed */ +- MC_MCP_RET_ERR_UNWRAP_SP_FAILED = 22, +- /** Unwrapping of Trustlet container failed */ +- MC_MCP_RET_ERR_UNWRAP_TRUSTLET_FAILED = 23, +- /** Container version mismatch */ +- MC_MCP_RET_ERR_CONTAINER_VERSION_MISMATCH = 24, +- /** Decryption of service provider trustlet failed */ +- MC_MCP_RET_ERR_SP_TL_DECRYPTION_FAILED = 25, +- /** Hash check of service provider trustlet failed */ +- MC_MCP_RET_ERR_SP_TL_HASH_CHECK_FAILED = 26, +- /** Activation/starting of task failed */ +- MC_MCP_RET_ERR_LAUNCH_TASK_FAILED = 27, +- /** Closing of task not yet possible, try again later */ +- MC_MCP_RET_ERR_CLOSE_TASK_FAILED = 28, +- /**< Service is blocked and a session cannot be opened to it */ +- MC_MCP_RET_ERR_SERVICE_BLOCKED = 29, +- /**< Service is locked and a session cannot be opened to it */ +- MC_MCP_RET_ERR_SERVICE_LOCKED = 30, +- /**< Service was forcefully killed (due to an administrative command) */ +- MC_MCP_RET_ERR_SERVICE_KILLED = 31, +- /** The command is unknown */ +- MC_MCP_RET_ERR_UNKNOWN_COMMAND = 50, +- /** The command data is invalid */ +- MC_MCP_RET_ERR_INVALID_DATA = 51 +-}; +- +-/** Possible MCP Command IDs +- * Command ID must be between 0 and 0x7FFFFFFF. +- */ +-enum cmd_id { +- /** Invalid command ID */ +- MC_MCP_CMD_ID_INVALID = 0x00, +- /** Open a session */ +- MC_MCP_CMD_OPEN_SESSION = 0x01, +- /** Close an existing session */ +- MC_MCP_CMD_CLOSE_SESSION = 0x03, +- /** Map WSM to session */ +- MC_MCP_CMD_MAP = 0x04, +- /** Unmap WSM from session */ +- MC_MCP_CMD_UNMAP = 0x05, +- /** Prepare for suspend */ +- MC_MCP_CMD_SUSPEND = 0x06, +- /** Resume from suspension */ +- MC_MCP_CMD_RESUME = 0x07, +- /** Get MobiCore version information */ +- MC_MCP_CMD_GET_MOBICORE_VERSION = 0x09, +- /** Close MCP and unmap MCI */ +- MC_MCP_CMD_CLOSE_MCP = 0x0A, +- /** Load token for device attestation */ +- MC_MCP_CMD_LOAD_TOKEN = 0x0B, +- /** Check that TA can be loaded */ +- MC_MCP_CMD_CHECK_LOAD_TA = 0x0C, +- /** Map multiple WSMs to session */ +- MC_MCP_CMD_MULTIMAP = 0x0D, +- /** Unmap multiple WSMs to session */ +- MC_MCP_CMD_MULTIUNMAP = 0x0E, +-}; +- +-/* +- * Types of WSM known to the MobiCore. +- */ +-#define WSM_TYPE_MASK 0xFF +-#define WSM_INVALID 0 /** Invalid memory type */ +-#define WSM_L2 2 /** Buffer mapping uses L2/L3 table */ +-#define WSM_L1 3 /** Buffer mapping uses fake L1 table */ +- +-/** Magic number used to identify if Open Command supports GP client +- * authentication. +- */ +-#define MC_GP_CLIENT_AUTH_MAGIC 0x47504131 /* "GPA1" */ +- +-/** Command header. +- * It just contains the command ID. Only values specified in cmd_id are +- * allowed as command IDs. If the command ID is unspecified the MobiCore +- * returns an empty response with the result set to +- * MC_MCP_RET_ERR_UNKNOWN_COMMAND. +- */ +-struct cmd_header { +- enum cmd_id cmd_id; /** Command ID of the command */ +-}; +- +-/** Response header. +- * MobiCore will reply to every MCP command with an MCP response. Like the MCP +- * command the response consists of a header followed by response data. The +- * response is written to the same memory location as the MCP command. +- */ +-struct rsp_header { +- uint32_t rsp_id; /** Command ID | FLAG_RESPONSE */ +- enum mcp_result result; /** Result of the command execution */ +-}; +- +-/** @defgroup CMD MCP Commands +- */ +- +-/** @defgroup ASMCMD Administrative Commands +- */ +- +-/** @defgroup MCPGETMOBICOREVERSION GET_MOBICORE_VERSION +- * Get MobiCore version info. +- * +- */ +- +-/** Get MobiCore Version Command */ +-struct cmd_get_version { +- struct cmd_header cmd_header; /** Command header */ +-}; +- +-/** Get MobiCore Version Command Response */ +-struct rsp_get_version { +- struct rsp_header rsp_header; /** Response header */ +- struct mc_version_info version_info; /** MobiCore version info */ +-}; +- +-/** @defgroup POWERCMD Power Management Commands +- */ +- +-/** @defgroup MCPSUSPEND SUSPEND +- * Prepare MobiCore suspension. +- * This command allows MobiCore and MobiCore drivers to release or clean +- * resources and save device state. +- * +- */ +- +-/** Suspend Command */ +-struct cmd_suspend { +- struct cmd_header cmd_header; /** Command header */ +-}; +- +-/** Suspend Command Response */ +-struct rsp_suspend { +- struct rsp_header rsp_header; /** Response header */ +-}; +- +-/** @defgroup MCPRESUME RESUME +- * Resume MobiCore from suspension. +- * This command allows MobiCore and MobiCore drivers to reinitialize hardware +- * affected by suspension. +- * +- */ +- +-/** Resume Command */ +-struct cmd_resume { +- struct cmd_header cmd_header; /** Command header */ +-}; +- +-/** Resume Command Response */ +-struct rsp_resume { +- struct rsp_header rsp_header; /** Response header */ +-}; +- +-/** @defgroup SESSCMD Session Management Commands +- */ +- +-/** @defgroup MCPOPEN OPEN +- * Load and open a session to a Trustlet. +- * The OPEN command loads Trustlet data to the MobiCore context and opens a +- * session to the Trustlet. If wsm_data_type is WSM_INVALID MobiCore tries to +- * start a pre-installed Trustlet associated with the uuid passed. The uuid +- * passed must match the uuid contained in the load data (if available). +- * On success, MobiCore returns the session ID which can be used for further +- * communication. +- */ +- +-/** GP client authentication data */ +-struct cmd_open_data { +- uint32_t mclf_magic; /** ASCII "MCLF" on older versions */ +- struct identity identity; /** Login method and data */ +-}; +- +-/** Open Command */ +-struct cmd_open { +- struct cmd_header cmd_header; /** Command header */ +- struct mc_uuid_t uuid; /** Service UUID */ +- uint8_t unused[4]; /** Padding to be 64-bit aligned */ +- uint64_t adr_tci_buffer; /** Physical address of the TCI MMU */ +- uint64_t adr_load_data; /** Physical address of the data MMU */ +- uint32_t ofs_tci_buffer; /** Offset to the data */ +- uint32_t len_tci_buffer; /** Length of the TCI */ +- uint32_t wsmtype_tci; /** Type of WSM used for the TCI */ +- uint32_t wsm_data_type; /** Type of MMU */ +- uint32_t ofs_load_data; /** Offset to the data */ +- uint32_t len_load_data; /** Length of the data to load */ +- union { +- struct cmd_open_data cmd_open_data; /** Client login data */ +- union mclf_header tl_header; /** Service header */ +- }; +- uint32_t is_gpta; /** true if looking for an SD/GP-TA */ +-}; +- +-/** Open Command Response */ +-struct rsp_open { +- struct rsp_header rsp_header; /** Response header */ +- uint32_t session_id; /** Session ID */ +-}; +- +-/** TA Load Check Command */ +-struct cmd_check_load { +- struct cmd_header cmd_header; /** Command header */ +- struct mc_uuid_t uuid; /** Service UUID */ +- uint64_t adr_load_data; /** Physical address of the data */ +- uint32_t wsm_data_type; /** Type of MMU */ +- uint32_t ofs_load_data; /** Offset to the data */ +- uint32_t len_load_data; /** Length of the data to load */ +- union mclf_header tl_header; /** Service header */ +-}; +- +-/** TA Load Check Response */ +-struct rsp_check_load { +- struct rsp_header rsp_header; /** Response header */ +-}; +- +-/** @defgroup MCPCLOSE CLOSE +- * Close an existing session to a Trustlet. +- * The CLOSE command terminates a session and frees all resources in the +- * MobiCore system which are currently occupied by the session. Before closing +- * the session, the MobiCore runtime management waits until all pending +- * operations, like calls to drivers, invoked by the Trustlet have been +- * terminated. Mapped memory will automatically be unmapped from the MobiCore +- * context. The NWd is responsible for processing the freed memory according to +- * the Rich-OS needs. +- * +- */ +- +-/** Close Command */ +-struct cmd_close { +- struct cmd_header cmd_header; /** Command header */ +- uint32_t session_id; /** Session ID */ +-}; +- +-/** Close Command Response */ +-struct rsp_close { +- struct rsp_header rsp_header; /** Response header */ +-}; +- +-/** @defgroup MCPMAP MAP +- * Map a portion of memory to a session. +- * The MAP command provides a block of memory to the context of a service. +- * The memory then becomes world-shared memory (WSM). +- * The only allowed memory type here is WSM_L2. +- */ +- +-/** Map Command */ +-struct cmd_map { +- struct cmd_header cmd_header; /** Command header */ +- uint32_t session_id; /** Session ID */ +- uint32_t wsm_type; /** Type of MMU */ +- uint32_t ofs_buffer; /** Offset to the payload */ +- uint64_t adr_buffer; /** Physical address of the MMU */ +- uint32_t len_buffer; /** Length of the buffer */ +-}; +- +-#define MCP_MAP_MAX 0x100000 /** Maximum length for MCP map */ +- +-/** Map Command Response */ +-struct rsp_map { +- struct rsp_header rsp_header; /** Response header */ +- /** Virtual address the WSM is mapped to, may include an offset! */ +- uint32_t secure_va; +-}; +- +-/** @defgroup MCPUNMAP UNMAP +- * Unmap a portion of world-shared memory from a session. +- * The UNMAP command is used to unmap a previously mapped block of +- * world shared memory from the context of a session. +- * +- * Attention: The memory block will be immediately unmapped from the specified +- * session. If the service is still accessing the memory, the service will +- * trigger a segmentation fault. +- */ +- +-/** Unmap Command */ +-struct cmd_unmap { +- struct cmd_header cmd_header; /** Command header */ +- uint32_t session_id; /** Session ID */ +- uint32_t wsm_type; /** Type of WSM used of the memory */ +- /** Virtual address the WSM is mapped to, may include an offset! */ +- uint32_t secure_va; +- uint32_t virtual_buffer_len; /** Length of virtual buffer */ +-}; +- +-/** Unmap Command Response */ +-struct rsp_unmap { +- struct rsp_header rsp_header; /** Response header */ +-}; +- +-/** @defgroup MCPLOADTOKEN +- * Load a token from the normal world and share it with type of +- * function. elementCnt must be a power of two and the power needs +- * to be smaller than power of uint32_t (obviously 32). +- */ +-struct notification_queue { +- struct notification_queue_header hdr; /** Queue header */ +- struct notification notification[MIN_NQ_ELEM]; /** Elements */ +-}; +- +-#endif /** NQ_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/mci/mcloadformat.h b/drivers/gud/MobiCoreDriver/mci/mcloadformat.h +deleted file mode 100644 +index f12f618bb0dc6..0000000000000 +--- a/drivers/gud/MobiCoreDriver/mci/mcloadformat.h ++++ /dev/null +@@ -1,134 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#ifndef MCLOADFORMAT_H_ +-#define MCLOADFORMAT_H_ +- +-/** Trustlet Blob length info */ +-#define MC_TLBLOBLEN_MAGIC 0x7672746C /* Magic for SWd: vrtl */ +-#define MAX_SO_CONT_SIZE 512 /* Max size for a container */ +- +-/** MCLF flags */ +-/**< Loaded service cannot be unloaded from MobiCore. */ +-#define MC_SERVICE_HEADER_FLAGS_PERMANENT BIT(0) +-/**< Service has no WSM control interface. */ +-#define MC_SERVICE_HEADER_FLAGS_NO_CONTROL_INTERFACE BIT(1) +-/**< Service can be debugged. */ +-#define MC_SERVICE_HEADER_FLAGS_DEBUGGABLE BIT(2) +-/**< New-layout trusted application or trusted driver. */ +-#define MC_SERVICE_HEADER_FLAGS_EXTENDED_LAYOUT BIT(3) +- +-/** Service type. +- * The service type defines the type of executable. +- */ +-enum service_type { +- SERVICE_TYPE_ILLEGAL = 0, +- SERVICE_TYPE_DRIVER = 1, +- SERVICE_TYPE_SP_TRUSTLET = 2, +- SERVICE_TYPE_SYSTEM_TRUSTLET = 3, +- SERVICE_TYPE_MIDDLEWARE = 4, +- SERVICE_TYPE_LAST_ENTRY = 5, +-}; +- +-/** +- * Descriptor for a memory segment. +- */ +-struct segment_descriptor { +- uint32_t start; /**< Virtual start address */ +- uint32_t len; /**< Segment length in bytes */ +-}; +- +-/** +- * MCLF intro for data structure identification. +- * Must be the first element of a valid MCLF file. +- */ +-struct mclf_intro { +- uint32_t magic; /**< Header magic value ASCII "MCLF" */ +- uint32_t version; /**< Version the MCLF header struct */ +-}; +- +-/** +- * @defgroup MCLF_VER_V2 MCLF Version 32 +- * @ingroup MCLF_VER +- * +- * @addtogroup MCLF_VER_V2 +- */ +- +-/* +- * GP TA identity. +- */ +-struct identity { +- /**< GP TA login type */ +- uint32_t login_type; +- /**< GP TA login data */ +- uint8_t login_data[16]; +-}; +- +-/** +- * Version 2.1/2.2 MCLF header. +- */ +-struct mclf_header_v2 { +- /**< MCLF header start with the mandatory intro */ +- struct mclf_intro intro; +- /**< Service flags */ +- uint32_t flags; +- /**< Type of memory the service must be executed from */ +- uint32_t mem_type; +- /**< Type of service */ +- enum service_type service_type; +- /**< Number of instances which can be run simultaneously */ +- uint32_t num_instances; +- /**< Loadable service unique identifier (UUID) */ +- struct mc_uuid_t uuid; +- /**< If the service_type is SERVICE_TYPE_DRIVER the Driver ID is used */ +- uint32_t driver_id; +- /**< +- * Number of threads (N) in a service: +- * SERVICE_TYPE_SP_TRUSTLET: N = 1 +- * SERVICE_TYPE_SYSTEM_TRUSTLET: N = 1 +- * SERVICE_TYPE_DRIVER: N >= 1 +- */ +- uint32_t num_threads; +- /**< Virtual text segment */ +- struct segment_descriptor text; +- /**< Virtual data segment */ +- struct segment_descriptor data; +- /**< Length of the BSS segment in bytes. MUST be at least 8 byte */ +- uint32_t bss_len; +- /**< Virtual start address of service code */ +- uint32_t entry; +- /**< Version of the interface the driver exports */ +- uint32_t service_version; +-}; +- +-/** +- * @addtogroup MCLF +- */ +- +-/** MCLF header */ +-union mclf_header { +- /**< Intro for data identification */ +- struct mclf_intro intro; +- /**< Version 2 header */ +- struct mclf_header_v2 mclf_header_v2; +-}; +- +-struct mc_blob_len_info { +- uint32_t magic; /**< New blob format magic number */ +- uint32_t root_size; /**< Root container size */ +- uint32_t sp_size; /**< SP container size */ +- uint32_t ta_size; /**< TA container size */ +- uint32_t reserved[4]; /**< Reserved for further Use */ +-}; +- +-#endif /* MCLOADFORMAT_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/mcp.c b/drivers/gud/MobiCoreDriver/mcp.c +deleted file mode 100644 +index 693fd42e2d4b5..0000000000000 +--- a/drivers/gud/MobiCoreDriver/mcp.c ++++ /dev/null +@@ -1,1067 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +-#include "public/mc_admin.h" +- +-#include "mci/mcimcp.h" +-#include "mci/mcifc.h" +-#include "mci/mcinq.h" /* SID_MCP */ +- +-#include "platform.h" /* IRQ number */ +-#include "fastcall.h" +-#include "debug.h" +-#include "logging.h" +-#include "mcp.h" +- +-/* respond timeout for MCP notification, in secs */ +-#define MCP_TIMEOUT 10 +-#define MCP_RETRIES 5 +-#define MCP_NF_QUEUE_SZ 8 +-#define NQ_NUM_ELEMS 16 +- +-static void mc_irq_worker(struct work_struct *data); +-DECLARE_WORK(irq_work, mc_irq_worker); +- +-static const struct { +- unsigned int index; +- const char *msg; +-} status_map[] = { +- /**< MobiCore control flags */ +- { MC_EXT_INFO_ID_FLAGS, "flags"}, +- /**< MobiCore halt condition code */ +- { MC_EXT_INFO_ID_HALT_CODE, "haltCode"}, +- /**< MobiCore halt condition instruction pointer */ +- { MC_EXT_INFO_ID_HALT_IP, "haltIp"}, +- /**< MobiCore fault counter */ +- { MC_EXT_INFO_ID_FAULT_CNT, "faultRec.cnt"}, +- /**< MobiCore last fault cause */ +- { MC_EXT_INFO_ID_FAULT_CAUSE, "faultRec.cause"}, +- /**< MobiCore last fault meta */ +- { MC_EXT_INFO_ID_FAULT_META, "faultRec.meta"}, +- /**< MobiCore last fault threadid */ +- { MC_EXT_INFO_ID_FAULT_THREAD, "faultRec.thread"}, +- /**< MobiCore last fault instruction pointer */ +- { MC_EXT_INFO_ID_FAULT_IP, "faultRec.ip"}, +- /**< MobiCore last fault stack pointer */ +- { MC_EXT_INFO_ID_FAULT_SP, "faultRec.sp"}, +- /**< MobiCore last fault ARM arch information */ +- { MC_EXT_INFO_ID_FAULT_ARCH_DFSR, "faultRec.arch.dfsr"}, +- /**< MobiCore last fault ARM arch information */ +- { MC_EXT_INFO_ID_FAULT_ARCH_ADFSR, "faultRec.arch.adfsr"}, +- /**< MobiCore last fault ARM arch information */ +- { MC_EXT_INFO_ID_FAULT_ARCH_DFAR, "faultRec.arch.dfar"}, +- /**< MobiCore last fault ARM arch information */ +- { MC_EXT_INFO_ID_FAULT_ARCH_IFSR, "faultRec.arch.ifsr"}, +- /**< MobiCore last fault ARM arch information */ +- { MC_EXT_INFO_ID_FAULT_ARCH_AIFSR, "faultRec.arch.aifsr"}, +- /**< MobiCore last fault ARM arch information */ +- { MC_EXT_INFO_ID_FAULT_ARCH_IFAR, "faultRec.arch.ifar"}, +- /**< MobiCore configured by Daemon via fc_init flag */ +- { MC_EXT_INFO_ID_MC_CONFIGURED, "mcData.flags"}, +- /**< MobiCore exception handler last partner */ +- { MC_EXT_INFO_ID_MC_EXC_PARTNER, "mcExcep.partner"}, +- /**< MobiCore exception handler last peer */ +- { MC_EXT_INFO_ID_MC_EXC_IPCPEER, "mcExcep.peer"}, +- /**< MobiCore exception handler last IPC message */ +- { MC_EXT_INFO_ID_MC_EXC_IPCMSG, "mcExcep.cause"}, +- /**< MobiCore exception handler last IPC data */ +- {MC_EXT_INFO_ID_MC_EXC_IPCDATA, "mcExcep.meta"}, +-}; +- +-static struct mcp_context { +- struct mutex buffer_lock; /* Lock on SWd communication buffer */ +- struct mutex queue_lock; /* Lock for MCP messages */ +- struct mcp_buffer *mcp_buffer; +- struct tbase_session *session; +- struct completion complete; +- bool mcp_dead; +- int irq; +- int (*scheduler_cb)(enum mcp_scheduler_commands); +- void (*crashhandler_cb)(void); +- /* MobiCore MCI information */ +- unsigned int order; +- union { +- void *base; +- struct { +- struct notification_queue *tx; +- struct notification_queue *rx; +- } nq; +- }; +- /* +- * This notifications list is to be used to queue notifications when the +- * notification queue overflows, so no session gets its notification +- * lost, especially MCP. +- */ +- struct mutex notifications_mutex; +- struct list_head notifications; +- struct mcp_session mcp_session; /* Pseudo session for MCP */ +- /* Unexpected notification (during MCP open) */ +- struct mutex unexp_notif_mutex; +- struct notification unexp_notif; +- /* Sessions */ +- struct mutex sessions_lock; +- struct list_head sessions; +- /* Dump buffer */ +- struct kasnprintf_buf dump; +-} mcp_ctx; +- +-static inline void mark_mcp_dead(void) +-{ +- mcp_ctx.mcp_dead = true; +- complete(&mcp_ctx.complete); +-} +- +-static inline int mcp_set_sleep_mode_rq(uint16_t sleep_req) +-{ +- mutex_lock(&mcp_ctx.buffer_lock); +- mcp_ctx.mcp_buffer->mc_flags.sleep_mode.sleep_req = sleep_req; +- mutex_unlock(&mcp_ctx.buffer_lock); +- return 0; +-} +- +-static ssize_t debug_crashdump_read(struct file *file, char __user *user_buf, +- size_t count, loff_t *ppos) +-{ +- if (mcp_ctx.dump.off) +- return simple_read_from_buffer(user_buf, count, ppos, +- mcp_ctx.dump.buf, +- mcp_ctx.dump.off); +- +- return 0; +-} +- +-static const struct file_operations mc_debug_crashdump_ops = { +- .read = debug_crashdump_read, +- .llseek = default_llseek, +-}; +- +-static void mcp_dump_mobicore_status(void) +-{ +- char uuid_str[33]; +- int ret = 0; +- int i; +- +- if (mcp_ctx.dump.off) +- ret = -EBUSY; +- +- /* read additional info about exception-point and print */ +- dev_err(g_ctx.mcd, "= 0) +- ret = kasnprintf(&mcp_ctx.dump, +- "%-20s= 0x%08x\n", +- status_map[i].msg, info); +- } +- } +- +- /* construct UUID string */ +- for (i = 0; i < 4; i++) { +- uint32_t info; +- int j; +- +- if (mc_fc_info(MC_EXT_INFO_ID_MC_EXC_UUID + i, NULL, &info)) +- return; +- +- for (j = 0; j < sizeof(info); j++) { +- snprintf(&uuid_str[(i * sizeof(info) + j) * 2], 3, +- "%02x", (info >> (j * 8)) & 0xff); +- } +- } +- +- dev_err(g_ctx.mcd, " %-20s= 0x%s\n", "mcExcep.uuid", uuid_str); +- if (ret >= 0) +- ret = kasnprintf(&mcp_ctx.dump, "%-20s= 0x%s\n", "mcExcep.uuid", +- uuid_str); +- +- if (ret < 0) { +- kfree(mcp_ctx.dump.buf); +- mcp_ctx.dump.off = 0; +- return; +- } +- +- debugfs_create_file("crashdump", 0400, g_ctx.debug_dir, NULL, +- &mc_debug_crashdump_ops); +- if (mcp_ctx.crashhandler_cb) +- mcp_ctx.crashhandler_cb(); +-} +- +-void mcp_session_init(struct mcp_session *session, bool is_gp, +- const struct identity *identity) +-{ +- /* close_work is initialized by the caller */ +- INIT_LIST_HEAD(&session->list); +- INIT_LIST_HEAD(&session->notifications_list); +- mutex_init(&session->notif_wait_lock); +- init_completion(&session->completion); +- mutex_init(&session->exit_code_lock); +- session->state = MCP_SESSION_RUNNING; +- session->is_gp = is_gp; +- if (is_gp) +- session->identity = *identity; +-} +- +-static inline bool mcp_session_isrunning(struct mcp_session *session) +-{ +- bool ret; +- +- mutex_lock(&mcp_ctx.sessions_lock); +- ret = session->state == MCP_SESSION_RUNNING; +- mutex_unlock(&mcp_ctx.sessions_lock); +- return ret; +-} +- +-/* +- * session remains valid thanks to the upper layers reference counters, but the +- * SWd session may have died, in which case we are informed. +- */ +-int mcp_session_waitnotif(struct mcp_session *session, int32_t timeout) +-{ +- int ret = 0; +- +- mutex_lock(&session->notif_wait_lock); +- if (!mcp_session_isrunning(session)) { +- ret = -ENXIO; +- goto end; +- } +- +- if (mcp_session_exitcode(session)) { +- ret = -ECOMM; +- goto end; +- } +- +- if (timeout < 0) { +- ret = wait_for_completion_interruptible(&session->completion); +- if (ret) +- goto end; +- } else { +- ret = wait_for_completion_interruptible_timeout( +- &session->completion, timeout * HZ / 1000); +- if (ret < 0) +- /* Interrupted */ +- goto end; +- +- if (!ret) { +- /* Timed out */ +- ret = -ETIME; +- goto end; +- } +- +- ret = 0; +- } +- +- if (mcp_session_exitcode(session)) { +- ret = -ECOMM; +- goto end; +- } +- +- if (!mcp_session_isrunning(session)) { +- ret = -ENXIO; +- goto end; +- } +- +-end: +- mutex_unlock(&session->notif_wait_lock); +- if (ret) +- dev_info(g_ctx.mcd, "%s session %x ec %d ret %d\n", __func__, +- session->id, session->exit_code, ret); +- +- return ret; +-} +- +-int32_t mcp_session_exitcode(struct mcp_session *session) +-{ +- int32_t exit_code; +- +- mutex_lock(&session->exit_code_lock); +- exit_code = session->exit_code; +- mutex_unlock(&session->exit_code_lock); +- if (exit_code) +- dev_info(g_ctx.mcd, "%s session %x ec %d\n", __func__, +- session->id, exit_code); +- +- return exit_code; +-} +- +-int mcp_suspend(void) +-{ +- return mcp_set_sleep_mode_rq(MC_FLAG_REQ_TO_SLEEP); +-} +- +-int mcp_resume(void) +-{ +- return mcp_set_sleep_mode_rq(MC_FLAG_NO_SLEEP_REQ); +-} +- +-bool mcp_suspended(void) +-{ +- struct mcp_flags *flags = &mcp_ctx.mcp_buffer->mc_flags; +- bool ret; +- +- mutex_lock(&mcp_ctx.buffer_lock); +- ret = flags->sleep_mode.ready_to_sleep & MC_STATE_READY_TO_SLEEP; +- if (!ret) { +- MCDRV_DBG("IDLE=%d!", flags->schedule); +- MCDRV_DBG("Request Sleep=%d!", flags->sleep_mode.sleep_req); +- MCDRV_DBG("Sleep Ready=%d!", flags->sleep_mode.ready_to_sleep); +- } +- +- mutex_unlock(&mcp_ctx.buffer_lock); +- return ret; +-} +- +-bool mcp_get_idle_timeout(int32_t *timeout) +-{ +- uint32_t schedule; +- bool ret; +- +- mutex_lock(&mcp_ctx.buffer_lock); +- schedule = mcp_ctx.mcp_buffer->mc_flags.schedule; +- if (schedule == MC_FLAG_SCHEDULE_IDLE) { +- if (g_ctx.f_timeout) +- *timeout = mcp_ctx.mcp_buffer->mc_flags.timeout_ms; +- else +- *timeout = -1; +- +- ret = true; +- } else { +- ret = false; +- } +- +- mutex_unlock(&mcp_ctx.buffer_lock); +- return ret; +-} +- +-void mcp_reset_idle_timeout(void) +-{ +- mutex_lock(&mcp_ctx.buffer_lock); +- mcp_ctx.mcp_buffer->mc_flags.timeout_ms = -1; +- mutex_unlock(&mcp_ctx.buffer_lock); +-} +- +-static inline int wait_mcp_notification(void) +-{ +- unsigned long timeout = msecs_to_jiffies(MCP_TIMEOUT * 1000); +- int try; +- +- /* +- * Total timeout is MCP_TIMEOUT * MCP_RETRIES, but we check for a crash +- * to try and terminate before then if things go wrong. +- */ +- for (try = 1; try <= MCP_RETRIES; try++) { +- uint32_t status; +- int ret; +- +- /* +- * Wait non-interruptible to keep MCP synchronised even if caller +- * is interrupted by signal. +- */ +- ret = wait_for_completion_timeout(&mcp_ctx.complete, timeout); +- if (ret > 0) +- return 0; +- +- MCDRV_ERROR("No answer after %ds", MCP_TIMEOUT * try); +- +- /* If SWd halted, exit now */ +- if (!mc_fc_info(MC_EXT_INFO_ID_MCI_VERSION, &status, NULL) && +- (status == MC_STATUS_HALT)) +- break; +- } +- +- /* mcp_message; +- enum cmd_id cmd_id = cmd->cmd_header.cmd_id; +- +- mutex_lock(&mcp_ctx.queue_lock); +- if (mcp_ctx.mcp_dead) +- goto out; +- +- /* Copy message to MCP buffer */ +- memcpy(msg, cmd, sizeof(*msg)); +- +- /* Poke tbase */ +- err = mcp_notify(&mcp_ctx.mcp_session); +- if (!err) +- err = wait_mcp_notification(); +- +- if (err) +- goto out; +- +- /* Check response ID */ +- if (msg->rsp_header.rsp_id != (cmd_id | FLAG_RESPONSE)) { +- MCDRV_ERROR("MCP command got invalid response (0x%X)", +- msg->rsp_header.rsp_id); +- err = -EBADE; +- goto out; +- } +- +- /* Convert result */ +- switch (msg->rsp_header.result) { +- case MC_MCP_RET_OK: +- err = 0; +- break; +- case MC_MCP_RET_ERR_CLOSE_TASK_FAILED: +- case MC_MCP_RET_ERR_NO_MORE_SESSIONS: +- err = -EBUSY; +- break; +- case MC_MCP_RET_ERR_OUT_OF_RESOURCES: +- err = -ENOSPC; +- break; +- case MC_MCP_RET_ERR_UNKNOWN_UUID: +- err = -ENOENT; +- break; +- case MC_MCP_RET_ERR_WRONG_PUBLIC_KEY: +- err = -EKEYREJECTED; +- break; +- case MC_MCP_RET_ERR_SERVICE_BLOCKED: +- err = -ECONNREFUSED; +- break; +- case MC_MCP_RET_ERR_SERVICE_LOCKED: +- err = -ECONNABORTED; +- break; +- case MC_MCP_RET_ERR_SERVICE_KILLED: +- err = -ECONNRESET; +- break; +- default: +- MCDRV_ERROR("cmd %d returned %d.", cmd_id, +- msg->rsp_header.result); +- err = -EPERM; +- goto out; +- } +- +- /* Copy response back to caller struct */ +- memcpy(cmd, msg, sizeof(*cmd)); +- +-out: +- mutex_unlock(&mcp_ctx.queue_lock); +- return err; +-} +- +-int mcp_get_version(struct mc_version_info *version_info) +-{ +- union mcp_message cmd; +- int ret; +- +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_GET_MOBICORE_VERSION; +- ret = mcp_cmd(&cmd); +- if (!ret) +- memcpy(version_info, &cmd.rsp_get_version.version_info, +- sizeof(*version_info)); +- +- return ret; +-} +- +-int mcp_load_token(uintptr_t data, const struct mcp_buffer_map *map) +-{ +- union mcp_message cmd; +- +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_LOAD_TOKEN; +- cmd.cmd_load_token.wsm_data_type = map->type; +- cmd.cmd_load_token.adr_load_data = map->phys_addr; +- cmd.cmd_load_token.ofs_load_data = map->offset; +- cmd.cmd_load_token.len_load_data = map->length; +- return mcp_cmd(&cmd); +-} +- +-int mcp_load_check(const struct tbase_object *obj, +- const struct mcp_buffer_map *map) +-{ +- const union mclf_header *header; +- union mcp_message cmd; +- +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_CHECK_LOAD_TA; +- /* Data */ +- cmd.cmd_check_load.wsm_data_type = map->type; +- cmd.cmd_check_load.adr_load_data = map->phys_addr; +- cmd.cmd_check_load.ofs_load_data = map->offset; +- cmd.cmd_check_load.len_load_data = map->length; +- /* Header */ +- header = (union mclf_header *)(obj->data + obj->header_length); +- cmd.cmd_check_load.uuid = header->mclf_header_v2.uuid; +- return mcp_cmd(&cmd); +-} +- +-int mcp_open_session(struct mcp_session *session, +- const struct tbase_object *obj, +- const struct mcp_buffer_map *map, +- const struct mcp_buffer_map *tci_map) +-{ +- static DEFINE_MUTEX(local_mutex); +- const union mclf_header *header; +- union mcp_message cmd; +- int ret; +- +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_OPEN_SESSION; +- /* Data */ +- cmd.cmd_open.wsm_data_type = map->type; +- cmd.cmd_open.adr_load_data = map->phys_addr; +- cmd.cmd_open.ofs_load_data = map->offset; +- cmd.cmd_open.len_load_data = map->length; +- /* Buffer */ +- if (tci_map) { +- cmd.cmd_open.wsmtype_tci = tci_map->type; +- cmd.cmd_open.adr_tci_buffer = tci_map->phys_addr; +- cmd.cmd_open.ofs_tci_buffer = tci_map->offset; +- cmd.cmd_open.len_tci_buffer = tci_map->length; +- } else { +- cmd.cmd_open.wsmtype_tci = WSM_INVALID; +- } +- /* Header */ +- header = (union mclf_header *)(obj->data + obj->header_length); +- cmd.cmd_open.uuid = header->mclf_header_v2.uuid; +- cmd.cmd_open.is_gpta = session->is_gp; +- /* Reset unexpected notification */ +- mutex_lock(&local_mutex); +- mcp_ctx.unexp_notif.session_id = SID_MCP; /* Cannot be */ +- if (!g_ctx.f_client_login) { +- memcpy(&cmd.cmd_open.tl_header, header, +- sizeof(cmd.cmd_open.tl_header)); +- } else { +- cmd.cmd_open.cmd_open_data.mclf_magic = MC_GP_CLIENT_AUTH_MAGIC; +- if (session->is_gp) +- cmd.cmd_open.cmd_open_data.identity = session->identity; +- } +- +- /* Send MCP open command */ +- ret = mcp_cmd(&cmd); +- if (!ret) { +- session->id = cmd.rsp_open.session_id; +- /* Add to list of sessions */ +- mutex_lock(&mcp_ctx.sessions_lock); +- list_add(&session->list, &mcp_ctx.sessions); +- mutex_unlock(&mcp_ctx.sessions_lock); +- /* Check for spurious notification */ +- mutex_lock(&mcp_ctx.unexp_notif_mutex); +- if (mcp_ctx.unexp_notif.session_id == session->id) { +- mutex_lock(&session->exit_code_lock); +- session->exit_code = mcp_ctx.unexp_notif.payload; +- mutex_unlock(&session->exit_code_lock); +- complete(&session->completion); +- } +- +- mutex_unlock(&mcp_ctx.unexp_notif_mutex); +- } +- +- mutex_unlock(&local_mutex); +- return ret; +-} +- +-/* +- * Legacy and GP TAs close differently: +- * - GP TAs always send a notification with payload, whether on close or crash +- * - Legacy TAs only send a notification with payload on crash +- * - GP TAs may take time to close, and we get -EBUSY back from mcp_cmd +- * - Legacy TAs always close when asked, unless they are driver in which case +- * they just don't close at all +- */ +-int mcp_close_session(struct mcp_session *session) +-{ +- union mcp_message cmd; +- int ret; +- +- /* state is either MCP_SESSION_RUNNING or MCP_SESSION_CLOSING_GP */ +- mutex_lock(&mcp_ctx.sessions_lock); +- if (session->state == MCP_SESSION_RUNNING) +- session->state = MCP_SESSION_CLOSE_PREPARE; +- +- mutex_unlock(&mcp_ctx.sessions_lock); +- /* Signal an eventual waiter that SWd session is going away */ +- complete(&session->completion); +- /* Send MCP command */ +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_CLOSE_SESSION; +- cmd.cmd_close.session_id = session->id; +- ret = mcp_cmd(&cmd); +- mutex_lock(&mcp_ctx.sessions_lock); +- /* +- * The GP TA may already have sent its exit code, in which case the +- * state has also been changed to MCP_SESSION_CLOSE_NOTIFIED. +- */ +- if (!ret) { +- session->state = MCP_SESSION_CLOSED; +- list_del(&session->list); +- mutex_lock(&mcp_ctx.notifications_mutex); +- list_del(&session->notifications_list); +- mutex_unlock(&mcp_ctx.notifications_mutex); +- } else if (ret == -EBUSY) { +- if (session->state == MCP_SESSION_CLOSE_NOTIFIED) +- /* GP TA already closed */ +- schedule_work(&session->close_work); +- +- session->state = MCP_SESSION_CLOSING_GP; +- } else { +- /* Something is not right, assume session is still running */ +- session->state = MCP_SESSION_RUNNING; +- } +- +- mutex_unlock(&mcp_ctx.sessions_lock); +- return ret; +-} +- +-int mcp_map(uint32_t session_id, struct mcp_buffer_map *map) +-{ +- union mcp_message cmd; +- int ret; +- +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_MAP; +- cmd.cmd_map.session_id = session_id; +- cmd.cmd_map.wsm_type = map->type; +- cmd.cmd_map.adr_buffer = map->phys_addr; +- cmd.cmd_map.ofs_buffer = map->offset; +- cmd.cmd_map.len_buffer = map->length; +- ret = mcp_cmd(&cmd); +- if (!ret) +- map->secure_va = cmd.rsp_map.secure_va; +- +- return ret; +-} +- +-int mcp_unmap(uint32_t session_id, const struct mcp_buffer_map *map) +-{ +- union mcp_message cmd; +- +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_UNMAP; +- cmd.cmd_unmap.session_id = session_id; +- cmd.cmd_unmap.wsm_type = map->type; +- cmd.cmd_unmap.virtual_buffer_len = map->length; +- cmd.cmd_unmap.secure_va = map->secure_va; +- return mcp_cmd(&cmd); +-} +- +-int mcp_multimap(uint32_t session_id, struct mcp_buffer_map *maps) +-{ +- struct mcp_buffer_map *map = maps; +- union mcp_message cmd; +- struct buffer_map *buf = cmd.cmd_multimap.bufs; +- int ret = 0; +- uint32_t i; +- +- /* Prepare command */ +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_MULTIMAP; +- cmd.cmd_multimap.session_id = session_id; +- for (i = 0; i < MC_MAP_MAX; i++, map++, buf++) { +- buf->wsm_type = map->type; +- buf->adr_buffer = map->phys_addr; +- buf->ofs_buffer = map->offset; +- buf->len_buffer = map->length; +- } +- +- ret = mcp_cmd(&cmd); +- if (ret) +- return ret; +- +- /* Return secure virtual addresses */ +- map = maps; +- for (i = 0; i < MC_MAP_MAX; i++, map++) +- map->secure_va = cmd.rsp_multimap.secure_va[i]; +- +- return 0; +-} +- +-int mcp_multiunmap(uint32_t session_id, const struct mcp_buffer_map *maps) +-{ +- const struct mcp_buffer_map *map = maps; +- union mcp_message cmd; +- struct buffer_unmap *buf = cmd.cmd_multiunmap.bufs; +- uint32_t i; +- +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_MULTIUNMAP; +- cmd.cmd_multiunmap.session_id = session_id; +- for (i = 0; i < MC_MAP_MAX; i++, map++, buf++) { +- buf->secure_va = map->secure_va; +- buf->len_buffer = map->length; +- } +- +- return mcp_cmd(&cmd); +-} +- +-static int mcp_close(void) +-{ +- union mcp_message cmd; +- +- memset(&cmd, 0, sizeof(cmd)); +- cmd.cmd_header.cmd_id = MC_MCP_CMD_CLOSE_MCP; +- return mcp_cmd(&cmd); +-} +- +-static inline bool notif_queue_full(void) +-{ +- struct notification_queue *tx = mcp_ctx.nq.tx; +- +- return (tx->hdr.write_cnt - tx->hdr.read_cnt) == tx->hdr.queue_size; +-} +- +-static inline void notif_queue_push(uint32_t session_id) +-{ +- struct notification_queue_header *hdr = &mcp_ctx.nq.tx->hdr; +- uint32_t i = hdr->write_cnt % hdr->queue_size; +- +- mcp_ctx.nq.tx->notification[i].session_id = session_id; +- mcp_ctx.nq.tx->notification[i].payload = 0; +- hdr->write_cnt++; +-} +- +-static inline bool mcp_notifications_flush_nolock(void) +-{ +- bool flushed = false; +- +- while (!list_empty(&mcp_ctx.notifications) && !notif_queue_full()) { +- struct mcp_session *session; +- +- session = list_first_entry(&mcp_ctx.notifications, +- struct mcp_session, +- notifications_list); +- dev_dbg(g_ctx.mcd, "pop %x\n", session->id); +- notif_queue_push(session->id); +- list_del_init(&session->notifications_list); +- flushed = true; +- } +- +- return flushed; +-} +- +-bool mcp_notifications_flush(void) +-{ +- bool flushed = false; +- +- mutex_lock(&mcp_ctx.notifications_mutex); +- flushed = mcp_notifications_flush_nolock(); +- mutex_unlock(&mcp_ctx.notifications_mutex); +- return flushed; +-} +- +-int mcp_notify(struct mcp_session *session) +-{ +- int ret = 0; +- +- if (!mcp_ctx.scheduler_cb) +- return -EAGAIN; +- +- mutex_lock(&mcp_ctx.notifications_mutex); +- if (session->id == SID_MCP) +- dev_dbg(g_ctx.mcd, "notify MCP"); +- else +- dev_dbg(g_ctx.mcd, "notify %x", session->id); +- +- /* Notify TEE */ +- if (!list_empty(&mcp_ctx.notifications) || notif_queue_full()) { +- if (!list_empty(&session->notifications_list)) { +- ret = -EAGAIN; +- dev_dbg(g_ctx.mcd, "skip %x\n", session->id); +- } else { +- list_add(&session->notifications_list, +- &mcp_ctx.notifications); +- dev_dbg(g_ctx.mcd, "push %x\n", session->id); +- } +- +- mcp_notifications_flush_nolock(); +- +- if (mcp_ctx.scheduler_cb(MCP_YIELD)) { +- MCDRV_ERROR("MC_SMC_N_YIELD failed"); +- ret = -EPROTO; +- } +- } else { +- notif_queue_push(session->id); +- if (mcp_ctx.scheduler_cb(MCP_NSIQ)) { +- MCDRV_ERROR("MC_SMC_N_SIQ failed"); +- ret = -EPROTO; +- } +- } +- +- mutex_unlock(&mcp_ctx.notifications_mutex); +- return ret; +-} +- +-static inline void handle_mcp_notif(uint32_t exit_code) +-{ +- dev_dbg(g_ctx.mcd, "notification from MCP ec %d\n", exit_code); +- complete(&mcp_ctx.complete); +-} +- +-static inline void handle_session_notif(uint32_t session_id, uint32_t exit_code) +-{ +- struct mcp_session *session = NULL, *s; +- +- dev_dbg(g_ctx.mcd, "notification from %x ec %d\n", session_id, +- exit_code); +- mutex_lock(&mcp_ctx.sessions_lock); +- list_for_each_entry(s, &mcp_ctx.sessions, list) { +- if (s->id == session_id) { +- session = s; +- break; +- } +- } +- +- if (session) { +- /* TA has terminated */ +- if (exit_code) { +- /* Update exit code, or not */ +- mutex_lock(&session->exit_code_lock); +- /* +- * In GP, the only way to recover the sessions exit code +- * is to call TEEC_InvokeCommand which will notify. But +- * notifying a dead session would change the exit code +- * to ERR_SID_NOT_ACTIVE, hence the check below. +- */ +- if (!session->is_gp || !session->exit_code || +- (exit_code != ERR_SID_NOT_ACTIVE)) +- session->exit_code = exit_code; +- +- mutex_unlock(&session->exit_code_lock); +- +- /* Update state or schedule close worker */ +- if (session->state == MCP_SESSION_CLOSE_PREPARE) +- session->state = MCP_SESSION_CLOSE_NOTIFIED; +- else if (session->state == MCP_SESSION_CLOSING_GP) +- schedule_work(&session->close_work); +- } +- +- /* Unblock waiter */ +- complete(&session->completion); +- } +- mutex_unlock(&mcp_ctx.sessions_lock); +- +- /* Unknown session, probably being started */ +- if (!session) { +- mutex_lock(&mcp_ctx.unexp_notif_mutex); +- mcp_ctx.unexp_notif.session_id = session_id; +- mcp_ctx.unexp_notif.payload = exit_code; +- mutex_unlock(&mcp_ctx.unexp_notif_mutex); +- } +-} +- +-static void mc_irq_worker(struct work_struct *data) +-{ +- struct notification_queue *rx = mcp_ctx.nq.rx; +- +- /* Deal with all pending notifications in one go */ +- while ((rx->hdr.write_cnt - rx->hdr.read_cnt) > 0) { +- struct notification nf; +- +- nf = rx->notification[rx->hdr.read_cnt++ % rx->hdr.queue_size]; +- if (nf.session_id == SID_MCP) +- handle_mcp_notif(nf.payload); +- else +- handle_session_notif(nf.session_id, nf.payload); +- } +- +- /* +- * Finished processing notifications. It does not matter whether +- * there actually were any notification or not. S-SIQs can also +- * be triggered by an SWd driver which was waiting for a FIQ. +- * In this case the S-SIQ tells NWd that SWd is no longer idle +- * an will need scheduling again. +- */ +- if (mcp_ctx.scheduler_cb) +- mcp_ctx.scheduler_cb(MCP_NSIQ); +-} +- +-/* +- * This function represents the interrupt function of the mcDrvModule. +- * It signals by incrementing of an event counter and the start of the read +- * waiting queue, the read function a interrupt has occurred. +- */ +-static irqreturn_t irq_handler(int intr, void *arg) +-{ +- /* wake up thread to continue handling this interrupt */ +- schedule_work(&irq_work); +- return IRQ_HANDLED; +-} +- +-void mcp_register_scheduler(int (*scheduler_cb)(enum mcp_scheduler_commands)) +-{ +- mcp_ctx.scheduler_cb = scheduler_cb; +-} +- +-void mcp_register_crashhandler(void (*crashhandler_cb)(void)) +-{ +- mcp_ctx.crashhandler_cb = crashhandler_cb; +-} +- +-int mcp_start(void) +-{ +- size_t q_len = ALIGN(2 * (sizeof(struct notification_queue_header) + +- NQ_NUM_ELEMS * sizeof(struct notification)), 4); +- int ret; +- +- /* Make sure we have an interrupt number before going on */ +-#if defined(CONFIG_OF) +- mcp_ctx.irq = irq_of_parse_and_map(g_ctx.mcd->of_node, 0); +-#endif +-#if defined(MC_INTR_SSIQ) +- if (mcp_ctx.irq <= 0) +- mcp_ctx.irq = MC_INTR_SSIQ; +-#endif +- +- if (mcp_ctx.irq <= 0) { +- MCDRV_ERROR("No IRQ number, aborting"); +- return -EINVAL; +- } +- +- /* Call the INIT fastcall to setup shared buffers */ +- ret = mc_fc_init(virt_to_phys(mcp_ctx.base), +- (uintptr_t)mcp_ctx.mcp_buffer - +- (uintptr_t)mcp_ctx.base, +- q_len, sizeof(*mcp_ctx.mcp_buffer)); +- if (ret) +- return ret; +- +- /* First empty N-SIQ to setup of the MCI structure */ +- ret = mc_fc_nsiq(); +- if (ret) +- return ret; +- +- /* +- * Wait until (uint16_t)-1) { +- MCDRV_DBG_WARN("queues too large (more than 64k), sorry..."); +- return -EINVAL; +- } +- +- mcp_ctx.order = get_order(q_len + sizeof(*mcp_ctx.mcp_buffer)); +- mci = __get_free_pages(GFP_USER | __GFP_ZERO, mcp_ctx.order); +- if (!mci) +- return -ENOMEM; +- +- mcp_ctx.nq.tx = (struct notification_queue *)mci; +- mcp_ctx.nq.tx->hdr.queue_size = NQ_NUM_ELEMS; +- mci += sizeof(struct notification_queue_header) + +- mcp_ctx.nq.tx->hdr.queue_size * sizeof(struct notification); +- +- mcp_ctx.nq.rx = (struct notification_queue *)mci; +- mcp_ctx.nq.rx->hdr.queue_size = NQ_NUM_ELEMS; +- mci += sizeof(struct notification_queue_header) + +- mcp_ctx.nq.rx->hdr.queue_size * sizeof(struct notification); +- +- mcp_ctx.mcp_buffer = (void *)ALIGN(mci, 4); +- return 0; +-} +- +-void mcp_exit(void) +-{ +- mark_mcp_dead(); +- if (mcp_ctx.dump.off) +- kfree(mcp_ctx.dump.buf); +- +- free_pages((unsigned long)mcp_ctx.base, mcp_ctx.order); +-} +diff --git a/drivers/gud/MobiCoreDriver/mcp.h b/drivers/gud/MobiCoreDriver/mcp.h +deleted file mode 100644 +index 0eefe573de8bf..0000000000000 +--- a/drivers/gud/MobiCoreDriver/mcp.h ++++ /dev/null +@@ -1,121 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _MC_MCP_H_ +-#define _MC_MCP_H_ +- +-#include "mci/mcloadformat.h" /* struct identity */ +- +-/* Structure to hold the TA/driver descriptor to pass to MCP */ +-struct tbase_object { +- uint32_t length; /* Total length */ +- uint32_t header_length; /* Length of header before payload */ +- uint8_t data[]; /* Header followed by payload */ +-}; +- +-/* Structure to hold all mapped buffer data to pass to MCP */ +-struct mcp_buffer_map { +- uint64_t phys_addr; /** Page-aligned physical address */ +- uint64_t secure_va; /** Page-aligned physical address */ +- uint32_t offset; /** Data offset inside the first page */ +- uint32_t length; /** Length of the data */ +- uint32_t type; /** Type of MMU */ +-}; +- +-struct mcp_session { +- /* Work descriptor to handle delayed closing, set by upper layer */ +- struct work_struct close_work; +- /* Sessions list (protected by mcp sessions_lock) */ +- struct list_head list; +- /* Notifications list (protected by mcp notifications_mutex) */ +- struct list_head notifications_list; +- /* Notification waiter lock */ +- struct mutex notif_wait_lock; /* Only one at a time */ +- /* Notification received */ +- struct completion completion; +- /* Notification lock */ +- struct mutex exit_code_lock; +- /* Last notification */ +- int32_t exit_code; +- /* Session id */ +- uint32_t id; +- /* Session state (protected by mcp sessions_lock) */ +- enum mcp_session_state { +- MCP_SESSION_RUNNING, +- MCP_SESSION_CLOSE_PREPARE, +- MCP_SESSION_CLOSE_NOTIFIED, +- MCP_SESSION_CLOSING_GP, +- MCP_SESSION_CLOSED, +- } state; +- /* This TA is of Global Platform type, set by upper layer */ +- bool is_gp; +- /* GP TAs have login information */ +- struct identity identity; +-}; +- +-/* Init for the mcp_session structure */ +-void mcp_session_init(struct mcp_session *session, bool is_gp, +- const struct identity *identity); +-int mcp_session_waitnotif(struct mcp_session *session, int32_t timeout); +-int32_t mcp_session_exitcode(struct mcp_session *mcp_session); +- +-/* SWd suspend/resume */ +-int mcp_suspend(void); +-int mcp_resume(void); +-bool mcp_suspended(void); +- +-/* Callback to scheduler registration */ +-enum mcp_scheduler_commands { +- MCP_YIELD, +- MCP_NSIQ, +-}; +- +-void mcp_register_scheduler(int (*scheduler_cb)(enum mcp_scheduler_commands)); +-bool mcp_notifications_flush(void); +-void mcp_register_crashhandler(void (*crashhandler_cb)(void)); +- +-/* +- * Get the requested SWd sleep timeout value (ms) +- * - if the timeout is -1, wait indefinitely +- * - if the timeout is 0, re-schedule immediately (timeouts in µs in the SWd) +- * - otherwise sleep for the required time +- * returns true if sleep is required, false otherwise +- */ +-bool mcp_get_idle_timeout(int32_t *timeout); +-void mcp_reset_idle_timeout(void); +- +-/* MCP commands */ +-int mcp_get_version(struct mc_version_info *version_info); +-int mcp_load_token(uintptr_t data, const struct mcp_buffer_map *buffer_map); +-int mcp_load_check(const struct tbase_object *obj, +- const struct mcp_buffer_map *buffer_map); +-int mcp_open_session(struct mcp_session *session, +- const struct tbase_object *obj, +- const struct mcp_buffer_map *map, +- const struct mcp_buffer_map *tci_map); +-int mcp_close_session(struct mcp_session *session); +-int mcp_map(uint32_t session_id, struct mcp_buffer_map *buffer_map); +-int mcp_unmap(uint32_t session_id, const struct mcp_buffer_map *buffer_map); +-int mcp_multimap(uint32_t session_id, struct mcp_buffer_map *buffer_maps); +-int mcp_multiunmap(uint32_t session_id, +- const struct mcp_buffer_map *buffer_maps); +-int mcp_notify(struct mcp_session *mcp_session); +- +-/* MCP initialisation/cleanup */ +-int mcp_init(void); +-void mcp_exit(void); +-int mcp_start(void); +-void mcp_stop(void); +- +-#endif /* _MC_MCP_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/mmu.c b/drivers/gud/MobiCoreDriver/mmu.c +deleted file mode 100644 +index fc769be4d15db..0000000000000 +--- a/drivers/gud/MobiCoreDriver/mmu.c ++++ /dev/null +@@ -1,450 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +- +-#include "mci/mcimcp.h" +- +-#include "platform.h" /* CONFIG_TRUSTONIC_TEE_LPAE */ +-#include "main.h" +-#include "debug.h" +-#include "mcp.h" /* mcp_buffer_map */ +-#include "mmu.h" +- +-#ifdef CONFIG_TRUSTONIC_TEE_LPAE +-#define MMU_TYPE_PAGE (3 << 0) +-#define MMU_BUFFERABLE BIT(2) /* AttrIndx[0] */ +-#define MMU_CACHEABLE BIT(3) /* AttrIndx[1] */ +-#define MMU_NS BIT(5) +-#define MMU_AP_RW_ALL BIT(6) /* AP[2:1], RW, at any privilege level */ +-#define MMU_EXT_SHARED (3 << 8) /* SH[1:0], inner shareable */ +-#define MMU_EXT_AF BIT(10) /* Access Flag */ +-#define MMU_EXT_NG BIT(11) +-#define MMU_EXT_XN (((uint64_t)1) << 54) /* XN */ +-#else +-#define MMU_TYPE_EXT (3 << 0) /* v5 */ +-#define MMU_TYPE_SMALL (2 << 0) +-#define MMU_BUFFERABLE BIT(2) +-#define MMU_CACHEABLE BIT(3) +-#define MMU_EXT_AP0 BIT(4) +-#define MMU_EXT_AP1 (2 << 4) +-#define MMU_EXT_TEX(x) ((x) << 6) /* v5 */ +-#define MMU_EXT_SHARED BIT(10) /* v6 */ +-#define MMU_EXT_NG BIT(11) /* v6 */ +-#endif +- +-/* +- * MobiCore specific page tables for world shared memory. +- * Linux uses shadow page tables, see arch/arm/include/asm/pgtable-2level. +- * MobiCore uses the default ARM format. +- * +- * Number of page table entries in one L2 MMU table. This is ARM specific, an +- * MMU table covers 1 MiB by using 256 entries referring to 4KiB pages each. +- */ +-#define L2_ENTRIES_MAX 256 +- +-/* +- * Small buffers (below 1MiB) are mapped using the legacy L2 table, but bigger +- * buffers now use a fake L1 table that holds 64-bit pointers to L2 tables. As +- * this must be exactly one page, we can hold up to 512 entries. +- */ +-#define L1_ENTRIES_MAX 512 +- +-#ifdef CONFIG_TRUSTONIC_TEE_LPAE +- +-/* +- * Secure world uses 64-bit physical addresses +- */ +-typedef u64 tbase_pte_t; +- +-/* +- * Linux uses different mappings for SMP systems(the sharing flag is set for +- * the pte. In order not to confuse things too much in Mobicore make sure the +- * shared buffers have the same flags. This should also be done in SWD side. +- */ +-static tbase_pte_t pte_flags = MMU_BUFFERABLE | MMU_CACHEABLE | MMU_EXT_NG | +-#ifdef CONFIG_SMP +- MMU_EXT_SHARED | +-#endif /* CONFIG_SMP */ +- MMU_EXT_XN | MMU_EXT_AF | MMU_AP_RW_ALL | +- MMU_NS | MMU_TYPE_PAGE; +- +-#else /* CONFIG_TRUSTONIC_TEE_LPAE */ +- +-/* +- * Secure world uses 32-bit physical addresses +- */ +-typedef u32 tbase_pte_t; +- +-/* +- * Linux uses different mappings for SMP systems(the sharing flag is set for +- * the pte. In order not to confuse things too much in Mobicore make sure the +- * shared buffers have the same flags. This should also be done in SWD side. +- */ +-static tbase_pte_t pte_flags = MMU_BUFFERABLE | MMU_CACHEABLE | MMU_EXT_NG | +-#ifdef CONFIG_SMP +- MMU_EXT_SHARED | MMU_EXT_TEX(1) | +-#endif /* CONFIG_SMP */ +- MMU_EXT_AP1 | MMU_EXT_AP0 | +- MMU_TYPE_SMALL | MMU_TYPE_EXT; +- +-#endif /* !CONFIG_TRUSTONIC_TEE_LPAE */ +- +-/* +- * Fake L1 MMU table. +- */ +-union l1_table { +- u64 *pages_phys; /* Array of physical page addresses */ +- unsigned long page; +-}; +- +-/* +- * L2 MMU table, which is more a L3 table in the LPAE case. +- */ +-union l2_table { +- tbase_pte_t *ptes; /* Array of PTEs */ +- unsigned long page; +-}; +- +-/* +- * MMU table allocated to the Daemon or a TLC describing a world shared +- * buffer. +- * When users map a malloc()ed area into SWd, a MMU table is allocated. +- * In addition, the area of maximum 1MB virtual address space is mapped into +- * the MMU table and a handle for this table is returned to the user. +- */ +-struct tbase_mmu { +- union l2_table l2_tables[L1_ENTRIES_MAX]; /* L2 tables */ +- size_t l2_tables_nr; /* Actual number of L2 tables */ +- union l1_table l1_table; /* Fake L1 table */ +- union l2_table l1_l2_table; /* L2 table for the L1 table */ +- uint32_t offset; +- uint32_t length; +- bool user; /* Pages are from user space */ +-}; +- +-static void free_all_pages(struct tbase_mmu *mmu_table) +-{ +- union l2_table *l2_table = &mmu_table->l2_tables[0]; +- size_t i; +- +- for (i = 0; i < mmu_table->l2_tables_nr; i++, l2_table++) { +- if (!l2_table->page) +- break; +- +- free_page(l2_table->page); +- } +- +- if (mmu_table->l1_l2_table.page) +- free_page(mmu_table->l1_l2_table.page); +- +- if (mmu_table->l1_table.page) +- free_page(mmu_table->l1_table.page); +-} +- +-/* +- * Create a MMU table for a buffer or trustlet. +- */ +-static inline int map_buffer(struct task_struct *task, const void *data, +- unsigned int length, struct tbase_mmu *mmu_table) +-{ +- const void *reader = (const void *)((uintptr_t)data & PAGE_MASK); +- struct page **pages; /* Same as above, conveniently typed */ +- unsigned long pages_page; /* Page to contain the page pointers */ +- size_t chunk; +- unsigned long total_pages_nr; +- int l1_entries_max; +- int ret = 0; +- +- /* Check that we have enough space to map data */ +- mmu_table->length = length; +- mmu_table->offset = (uintptr_t)data & ~PAGE_MASK; +- total_pages_nr = PAGE_ALIGN(mmu_table->offset + length) / PAGE_SIZE; +- if (g_ctx.f_mem_ext) +- l1_entries_max = L1_ENTRIES_MAX; +- else +- l1_entries_max = 1; +- +- if (total_pages_nr > (l1_entries_max * L2_ENTRIES_MAX)) { +- dev_err(g_ctx.mcd, "data mapping exceeds %d pages", +- l1_entries_max * L2_ENTRIES_MAX); +- return -EINVAL; +- } +- +- /* Get number of L2 tables needed */ +- mmu_table->l2_tables_nr = (total_pages_nr + L2_ENTRIES_MAX - 1) / +- L2_ENTRIES_MAX; +- dev_dbg(g_ctx.mcd, "total_pages_nr %lu l2_tables_nr %zu", +- total_pages_nr, mmu_table->l2_tables_nr); +- +- /* Get a page to store page pointers */ +- pages_page = get_zeroed_page(GFP_KERNEL); +- if (!pages_page) +- return -ENOMEM; +- +- pages = (struct page **)pages_page; +- +- /* Allocate a page for the L1 table */ +- if (mmu_table->l2_tables_nr > 1) { +- tbase_pte_t *pte; +- +- mmu_table->l1_table.page = get_zeroed_page(GFP_KERNEL); +- mmu_table->l1_l2_table.page = get_zeroed_page(GFP_KERNEL); +- if (!mmu_table->l1_table.page || !mmu_table->l1_l2_table.page) { +- ret = -ENOMEM; +- goto end; +- } +- +- /* Map it */ +- pte = &mmu_table->l1_l2_table.ptes[0]; +- *pte = virt_to_phys(mmu_table->l1_table.pages_phys); +- *pte |= pte_flags; +- } +- +- for (chunk = 0; chunk < mmu_table->l2_tables_nr; chunk++) { +- unsigned long pages_nr, i; +- tbase_pte_t *pte; +- struct page **page_ptr; +- +- /* Size to map for this chunk */ +- if (chunk == (mmu_table->l2_tables_nr - 1)) +- pages_nr = ((total_pages_nr - 1) % L2_ENTRIES_MAX) + 1; +- else +- pages_nr = L2_ENTRIES_MAX; +- +- /* Allocate a page for the MMU descriptor */ +- mmu_table->l2_tables[chunk].page = get_zeroed_page(GFP_KERNEL); +- if (!mmu_table->l2_tables[chunk].page) { +- ret = -ENOMEM; +- goto end; +- } +- +- /* Add page address to L1 table if needed */ +- if (mmu_table->l1_table.page) +- mmu_table->l1_table.pages_phys[chunk] = +- virt_to_phys(mmu_table->l2_tables[chunk].ptes); +- +- /* Get pages */ +- if (task) { +- long gup_ret; +- +- /* Buffer was allocated in user space */ +- down_read(&task->mm->mmap_sem); +- gup_ret = get_user_pages(task, task->mm, +- (uintptr_t)reader, pages_nr, +- 1, 0, pages, 0); +- reader += pages_nr * PAGE_SIZE; +- up_read(&task->mm->mmap_sem); +- if (gup_ret < 0) { +- ret = gup_ret; +- dev_err(g_ctx.mcd, +- "failed to get user pages: %d", ret); +- goto end; +- } +- +- /* check if we could lock all pages. */ +- if (gup_ret != pages_nr) { +- dev_err(g_ctx.mcd, +- "get_user_pages() failed, ret: %ld", +- gup_ret); +- release_pages(pages, gup_ret, 0); +- ret = -ENOMEM; +- goto end; +- } +- +- mmu_table->user = true; +- } else if (is_vmalloc_addr(data)) { +- /* Buffer vmalloc'ed in kernel space */ +- page_ptr = &pages[0]; +- for (i = 0; i < pages_nr; i++) { +- struct page *page = vmalloc_to_page(reader); +- +- if (!page) { +- dev_err(g_ctx.mcd, +- "failed to map address"); +- ret = -EINVAL; +- goto end; +- } +- +- *page_ptr++ = page; +- reader += PAGE_SIZE; +- } +- } else { +- /* Buffer kmalloc'ed in kernel space */ +- struct page *page = virt_to_page(reader); +- +- reader += pages_nr * PAGE_SIZE; +- page_ptr = &pages[0]; +- for (i = 0; i < pages_nr; i++) +- *page_ptr++ = page++; +- } +- +- /* Create MMU Table entries */ +- page_ptr = &pages[0]; +- pte = &mmu_table->l2_tables[chunk].ptes[0]; +- for (i = 0; i < pages_nr; i++, page_ptr++, pte++) { +- /* +- * Create MMU table entry, see ARM MMU docu for details +- * about flags stored in the lowest 12 bits. As a side +- * reference, the Article "ARM's multiply-mapped memory +- * mess" found in the collection at +- * http://lwn.net/Articles/409032/ is also worth reading. +- */ +- unsigned long phys = page_to_phys(*page_ptr); +-#if defined CONFIG_ARM64 && !defined CONFIG_TRUSTONIC_TEE_LPAE +- if (phys & 0xffffffff00000000) { +- dev_err(g_ctx.mcd, +- "Pointer too big for non-LPAE: 0x%16lx", +- phys); +- ret = -EFAULT; +- goto end; +- } +-#endif +- *pte = phys; +- *pte |= pte_flags; +- } +- } +- +-end: +- if (ret) +- free_all_pages(mmu_table); +- +- free_page(pages_page); +- return ret; +-} +- +-static inline void unmap_buffer(struct tbase_mmu *mmu_table) +-{ +- int t; +- +- dev_dbg(g_ctx.mcd, "clear MMU table, virt %p", mmu_table); +- if (!mmu_table->user) +- goto end; +- +- /* Release all locked user space pages */ +- for (t = 0; t < mmu_table->l2_tables_nr; t++) { +- tbase_pte_t *pte = mmu_table->l2_tables[t].ptes; +- int i; +- +- for (i = 0; i < L2_ENTRIES_MAX; i++, pte++) { +- struct page *page; +- +- /* If not all entries are used, unused ones are 0 */ +- if (!*pte) +- break; +- +- /* pte_page() cannot return NULL */ +- page = pte_page(*pte); +- dev_dbg(g_ctx.mcd, "MMU entry %d: 0x%llx, virt %p", +- i, (u64)*pte, page); +- +- page_cache_release(page); +- } +- } +- +-end: +- free_all_pages(mmu_table); +-} +- +-/* +- * Delete a MMU table. +- */ +-void tbase_mmu_delete(struct tbase_mmu *mmu) +-{ +- if (WARN(!mmu, "NULL mmu pointer given")) +- return; +- +- unmap_buffer(mmu); +- MCDRV_DBG("freed mmu %p: %s len %u off %u table %lx type L%d", +- mmu, mmu->user ? "user" : "kernel", mmu->length, mmu->offset, +- (uintptr_t)(mmu->l1_table.page ? mmu->l1_l2_table.ptes : +- mmu->l2_tables[0].ptes), +- mmu->l1_table.page ? 1 : 2); +- kfree(mmu); +-} +- +-/* +- * Allocate MMU table and map buffer into it. +- * That is, create respective table entries. +- */ +-struct tbase_mmu *tbase_mmu_create(struct task_struct *task, +- const void *addr, +- unsigned int length) +-{ +- struct tbase_mmu *mmu; +- int ret; +- +- /* Check input arguments */ +- if (WARN(!addr, "data address is NULL")) +- return ERR_PTR(-EINVAL); +- +- if (WARN(!length, "data length is 0")) +- return ERR_PTR(-EINVAL); +- +- /* Allocate the struct */ +- mmu = kmalloc(sizeof(*mmu), GFP_KERNEL | __GFP_ZERO); +- if (!mmu) +- return ERR_PTR(-ENOMEM); +- +- /* Create the MMU mapping for the data */ +- ret = map_buffer(task, addr, length, mmu); +- if (ret) { +- kfree(mmu); +- return ERR_PTR(ret); +- } +- +- MCDRV_DBG("created mmu %p: %s addr %p len %u off %u table %lx type L%d", +- mmu, mmu->user ? "user" : "kernel", addr, mmu->length, +- mmu->offset, +- (uintptr_t)(mmu->l1_table.page ? mmu->l1_l2_table.ptes : +- mmu->l2_tables[0].ptes), +- mmu->l1_table.page ? 1 : 2); +- return mmu; +-} +- +-void tbase_mmu_buffer(const struct tbase_mmu *mmu, struct mcp_buffer_map *map) +-{ +- if (mmu->l1_table.page) { +- map->phys_addr = virt_to_phys(mmu->l1_l2_table.ptes); +- map->type = WSM_L1; +- } else { +- map->phys_addr = virt_to_phys(mmu->l2_tables[0].ptes); +- map->type = WSM_L2; +- } +- +- map->secure_va = 0; +- map->offset = mmu->offset; +- map->length = mmu->length; +-} +- +-int tbase_mmu_info(const struct tbase_mmu *mmu, struct kasnprintf_buf *buf) +-{ +- return kasnprintf(buf, +- "\t\t\tmmu %p: %s len %u off %u table %lx type L%d\n", +- mmu, mmu->user ? "user" : "kernel", mmu->length, +- mmu->offset, +- (uintptr_t)(mmu->l1_table.page ? +- mmu->l1_l2_table.ptes : mmu->l2_tables[0].ptes), +- mmu->l1_table.page ? 1 : 2); +-} +diff --git a/drivers/gud/MobiCoreDriver/mmu.h b/drivers/gud/MobiCoreDriver/mmu.h +deleted file mode 100644 +index 09efea480bef8..0000000000000 +--- a/drivers/gud/MobiCoreDriver/mmu.h ++++ /dev/null +@@ -1,44 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _TBASE_MEM_H_ +-#define _TBASE_MEM_H_ +- +-struct tbase_mmu; +-struct mcp_buffer_map; +- +-/* +- * Allocate MMU table and map buffer into it. +- * That is, create respective table entries. +- */ +-struct tbase_mmu *tbase_mmu_create(struct task_struct *task, +- const void *wsm_buffer, +- unsigned int wsm_len); +- +-/* +- * Delete a used MMU table. +- */ +-void tbase_mmu_delete(struct tbase_mmu *mmu); +- +-/* +- * Fill in buffer info for MMU table. +- */ +-void tbase_mmu_buffer(const struct tbase_mmu *mmu, struct mcp_buffer_map *map); +- +-/* +- * Add info to debug buffer. +- */ +-int tbase_mmu_info(const struct tbase_mmu *mmu, struct kasnprintf_buf *buf); +- +-#endif /* _TBASE_MEM_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/platform.h b/drivers/gud/MobiCoreDriver/platform.h +deleted file mode 100644 +index f9c801450f64e..0000000000000 +--- a/drivers/gud/MobiCoreDriver/platform.h ++++ /dev/null +@@ -1,150 +0,0 @@ +-/* +- * Copyright (c) 2013-2014 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#ifndef _MC_PLATFORM_H_ +-#define _MC_PLATFORM_H_ +- +-/* MobiCore Interrupt for Qualcomm (DT IRQ has priority if present) */ +-#define MC_INTR_SSIQ 280 +- +-/* Use SMC for fastcalls */ +-#define MC_SMC_FASTCALL +- +-#include +- +-/*--------------- Implementation -------------- */ +-#if defined(CONFIG_ARCH_APQ8084) || defined(CONFIG_ARCH_MSM8916) || \ +- defined(CONFIG_ARCH_MSM8994) || defined(CONFIG_ARCH_MSM8909) || \ +- defined(CONFIG_ARCH_MSM8996) +- +-#include +- +-#if defined(CONFIG_ARM64) || defined(CONFIG_ARCH_MSM8916) +- +- #include +- #include +- #include +- #include +- #include +- #include +- +- #define SCM_MOBIOS_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) \ +- | 0x33000000) +- +- #define TZ_EXECUTIVE_EXT_ID_PARAM_ID \ +- TZ_SYSCALL_CREATE_PARAM_ID_4( \ +- TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ +- TZ_SYSCALL_PARAM_TYPE_VAL, \ +- TZ_SYSCALL_PARAM_TYPE_BUF_RW, \ +- TZ_SYSCALL_PARAM_TYPE_VAL) +- +-#endif +- +-#else +-#include +-#endif +- +-/* from following file */ +-#define SCM_SVC_MOBICORE 250 +-#define SCM_CMD_MOBICORE 1 +- +-static inline int smc_fastcall(void *fc_generic, size_t size) +-{ +-#if defined(CONFIG_ARCH_APQ8084) || defined(CONFIG_ARCH_MSM8916) || \ +- defined(CONFIG_ARCH_MSM8994) || defined(CONFIG_ARCH_MSM8996) +- if (is_scm_armv8()) { +- struct scm_desc desc = {0}; +- int ret; +- void *scm_buf = NULL; +- +- scm_buf = kzalloc(PAGE_ALIGN(size), GFP_KERNEL); +- if (!scm_buf) +- return -ENOMEM; +- memcpy(scm_buf, fc_generic, size); +- dmac_flush_range(scm_buf, scm_buf + size); +- +- desc.arginfo = TZ_EXECUTIVE_EXT_ID_PARAM_ID; +- desc.args[0] = virt_to_phys(scm_buf); +- desc.args[1] = (u32)size; +- desc.args[2] = virt_to_phys(scm_buf); +- desc.args[3] = (u32)size; +- +- ret = scm_call2( +- SCM_MOBIOS_FNID(SCM_SVC_MOBICORE, SCM_CMD_MOBICORE), +- &desc); +- +- dmac_flush_range(scm_buf, scm_buf + size); +- +- memcpy(fc_generic, scm_buf, size); +- kfree(scm_buf); +- return ret; +- } +-#endif +- +- return scm_call(SCM_SVC_MOBICORE, SCM_CMD_MOBICORE, +- fc_generic, size, +- fc_generic, size); +-} +- +-/* Fastcall value should be the one for armv7, even if on armv8, +- * as long as the __aarch32__ flag is not activated in SW. +- * But for 8996, architecture is armv8 with __aarch32__ in Sw. +- */ +-#if !defined(CONFIG_ARCH_MSM8996) +-#define MC_ARMV7_FC +-#endif +- +-#if defined(CONFIG_ARCH_MSM8996) +-#define CONFIG_TRUSTONIC_TEE_LPAE +-#endif +- +-/* +- * Perform crypto clock enable/disable +- * of clocks +- * "bus_clk" +- * "core_clk" +- * "iface_clk" +- */ +-#if (!defined(CONFIG_ARCH_MSM8960) && !defined(CONFIG_ARCH_MSM8994)) || \ +- defined(CONFIG_ARCH_MSM8996) +-#define MC_CRYPTO_CLOCK_MANAGEMENT +-#endif +- +-/* +- * Perform clock enable/disable for clock "core_clk_src" +- */ +-#if defined(CONFIG_ARCH_MSM8916) || defined(CONFIG_ARCH_MSM8909) || \ +- defined(CONFIG_ARCH_MSM8996) +-#define MC_DEVICE_PROPNAME "qcom,mcd" +-#if defined(MC_CRYPTO_CLOCK_MANAGEMENT) +-#define MC_CLOCK_CORESRC_PROPNAME "qcom,ce-opp-freq" +-#define MC_CLOCK_CORESRC_DEFAULTRATE 100000000 +-#endif /* MC_CRYPTO_CLOCK_MANAGEMENT */ +-#endif +- +- +-#if !defined(CONFIG_ARCH_MSM8996) +-/* uid/gid behave like old kernels but with new types */ +-/* This flag does not exist on 8996 3.10 kernel version */ +-#if !defined(CONFIG_UIDGID_STRICT_TYPE_CHECKS) +-#define MC_UIDGID_OLDSTYLE +-#endif +-/* Fastcall value should be the one for armv7, even if on armv8, +- * as long as the __aarch32__ flag is not activated in SW. +- * But for 8996, architecture is armv8 with __aarch32__ in Sw. +- */ +-#define MC_ARMV7_FC +-#endif /* not CONFIG_ARCH_MSM8996 */ +- +-#endif /* _MC_PLATFORM_H_ */ +- +diff --git a/drivers/gud/MobiCoreDriver/pm.c b/drivers/gud/MobiCoreDriver/pm.c +deleted file mode 100644 +index 98310f73dfeab..0000000000000 +--- a/drivers/gud/MobiCoreDriver/pm.c ++++ /dev/null +@@ -1,62 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +- +-#include "platform.h" /* MC_PM_RUNTIME */ +-#include "debug.h" +-#include "scheduler.h" /* SWd suspend/resume commands */ +-#include "pm.h" +- +-#ifdef MC_PM_RUNTIME +-static struct pm_context { +- struct notifier_block pm_notifier; +-} pm_ctx; +- +-static int mc_suspend_notifier(struct notifier_block *nb, unsigned long event, +- void *dummy) +-{ +- switch (event) { +- case PM_SUSPEND_PREPARE: +- return mc_scheduler_suspend(); +- case PM_POST_SUSPEND: +- return mc_scheduler_resume(); +- } +- +- return 0; +-} +- +- +-/* CPI todo: inconsistent handling of ret in below 2 functions */ +-int mc_pm_start(void) +-{ +- int ret = 0; +- +- pm_ctx.pm_notifier.notifier_call = mc_suspend_notifier; +- ret = register_pm_notifier(&pm_ctx.pm_notifier); +- MCDRV_DBG_VERBOSE("done, ret = %d", ret); +- +- return ret; +-} +- +-void mc_pm_stop(void) +-{ +- unregister_pm_notifier(&pm_ctx.pm_notifier); +-} +- +-#endif /* MC_PM_RUNTIME */ +diff --git a/drivers/gud/MobiCoreDriver/pm.h b/drivers/gud/MobiCoreDriver/pm.h +deleted file mode 100644 +index 999599a70b1ab..0000000000000 +--- a/drivers/gud/MobiCoreDriver/pm.h ++++ /dev/null +@@ -1,36 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _MC_PM_H_ +-#define _MC_PM_H_ +- +-#include "platform.h" /* MC_PM_RUNTIME */ +- +-#ifdef MC_PM_RUNTIME +-/* Initialize Power Management */ +-int mc_pm_start(void); +-/* Free all Power Management resources*/ +-void mc_pm_stop(void); +-#else +-static inline int mc_pm_start(void) +-{ +- return 0; +-} +- +-static inline void mc_pm_stop(void) +-{ +-} +-#endif +- +-#endif /* _MC_PM_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/public/mc_admin.h b/drivers/gud/MobiCoreDriver/public/mc_admin.h +deleted file mode 100644 +index 3a4078dd6fc30..0000000000000 +--- a/drivers/gud/MobiCoreDriver/public/mc_admin.h ++++ /dev/null +@@ -1,80 +0,0 @@ +-/* +- * Copyright (c) 2013-2014 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef __MC_ADMIN_IOCTL_H__ +-#define __MC_ADMIN_IOCTL_H__ +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-#define MC_ADMIN_DEVNODE "mobicore" +- +-/* Driver/daemon commands */ +-enum { +- /* Command 0 is reserved */ +- MC_DRV_GET_ROOT_CONTAINER = 1, +- MC_DRV_GET_SP_CONTAINER = 2, +- MC_DRV_GET_TRUSTLET_CONTAINER = 3, +- MC_DRV_GET_TRUSTLET = 4, +- MC_DRV_SIGNAL_CRASH = 5, +-}; +- +-/* MobiCore IOCTL magic number */ +-#define MC_IOC_MAGIC 'M' +- +-struct mc_admin_request { +- uint32_t request_id; /* Unique request identifier */ +- uint32_t command; /* Command to daemon */ +- struct mc_uuid_t uuid; /* UUID of trustlet, if relevant */ +- uint32_t is_gp; /* Whether trustlet is GP */ +- uint32_t spid; /* SPID of trustlet, if relevant */ +-}; +- +-struct mc_admin_response { +- uint32_t request_id; /* Unique request identifier */ +- uint32_t error_no; /* Errno from daemon */ +- uint32_t spid; /* SPID of trustlet, if relevant */ +- uint32_t service_type; /* Type of trustlet being returned */ +- uint32_t length; /* Length of data to get */ +- /* Any data follows */ +-}; +- +-struct mc_admin_driver_info { +- /* Version, and something else..*/ +- uint32_t drv_version; +- uint32_t initial_cmd_id; +-}; +- +-struct mc_admin_load_info { +- uint32_t spid; /* SPID of trustlet, if relevant */ +- uint64_t address; /* Address of the data */ +- uint32_t length; /* Length of data to get */ +-}; +- +-#define MC_ADMIN_IO_GET_DRIVER_REQUEST \ +- _IOR(MC_IOC_MAGIC, 0, struct mc_admin_request) +-#define MC_ADMIN_IO_GET_INFO \ +- _IOR(MC_IOC_MAGIC, 1, struct mc_admin_driver_info) +-#define MC_ADMIN_IO_LOAD_DRIVER \ +- _IOW(MC_IOC_MAGIC, 2, struct mc_admin_load_info) +-#define MC_ADMIN_IO_LOAD_TOKEN \ +- _IOW(MC_IOC_MAGIC, 3, struct mc_admin_load_info) +-#define MC_ADMIN_IO_LOAD_CHECK \ +- _IOW(MC_IOC_MAGIC, 4, struct mc_admin_load_info) +- +-#ifdef __cplusplus +-} +-#endif +-#endif /* __MC_ADMIN_IOCTL_H__ */ +diff --git a/drivers/gud/MobiCoreDriver/public/mc_linux.h b/drivers/gud/MobiCoreDriver/public/mc_linux.h +deleted file mode 100644 +index 2368653f8890d..0000000000000 +--- a/drivers/gud/MobiCoreDriver/public/mc_linux.h ++++ /dev/null +@@ -1,170 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _MC_LINUX_H_ +-#define _MC_LINUX_H_ +- +-#define MCDRVMODULEAPI_VERSION_MAJOR 2 +-#define MCDRVMODULEAPI_VERSION_MINOR 1 +- +-#ifndef __KERNEL__ +-#include +-#endif +- +-#define MC_USER_DEVNODE "mobicore-user" +- +-/** Maximum length of MobiCore product ID string. */ +-#define MC_PRODUCT_ID_LEN 64 +- +-/** Number of buffers that can be mapped at once */ +-#define MC_MAP_MAX 4 +- +-/* +- * Universally Unique Identifier (UUID) according to ISO/IEC 11578. +- */ +-struct mc_uuid_t { +- uint8_t value[16]; /* Value of the UUID. */ +-}; +- +-/* +- * GP TA login types. +- */ +-enum mc_login_type { +- TEEC_LOGIN_PUBLIC = 0, +- TEEC_LOGIN_USER, +- TEEC_LOGIN_GROUP, +- TEEC_LOGIN_APPLICATION = 4, +- TEEC_LOGIN_USER_APPLICATION, +- TEEC_LOGIN_GROUP_APPLICATION, +-}; +- +-/* +- * GP TA identity structure. +- */ +-struct mc_identity { +- enum mc_login_type login_type; +- union { +- uint8_t login_data[16]; +- gid_t gid; /* Requested group id */ +- struct { +- uid_t euid; +- uid_t ruid; +- } uid; +- }; +-}; +- +-/* +- * Data exchange structure of the MC_IO_OPEN_SESSION ioctl command. +- */ +-struct mc_ioctl_open_sess { +- struct mc_uuid_t uuid; /* trustlet uuid */ +- uint32_t is_gp_uuid; /* uuid is for GP TA */ +- uint32_t sid; /* session id (out) */ +- uint64_t tci; /* tci buffer pointer */ +- uint32_t tcilen; /* tci length */ +- struct mc_identity identity; /* GP TA identity */ +-}; +- +-/* +- * Data exchange structure of the MC_IO_OPEN_TRUSTLET ioctl command. +- */ +-struct mc_ioctl_open_trustlet { +- uint32_t sid; /* session id (out) */ +- uint32_t spid; /* trustlet spid */ +- uint64_t buffer; /* trustlet binary pointer */ +- uint32_t tlen; /* binary length */ +- uint64_t tci; /* tci buffer pointer */ +- uint32_t tcilen; /* tci length */ +-}; +- +-/* +- * Data exchange structure of the MC_IO_WAIT ioctl command. +- */ +-struct mc_ioctl_wait { +- uint32_t sid; /* session id (in) */ +- int32_t timeout; /* notification timeout */ +-}; +- +-/* +- * Data exchange structure of the MC_IO_ALLOC ioctl command. +- */ +-struct mc_ioctl_alloc { +- uint32_t len; /* buffer length */ +- uint32_t handle; /* user handle for the buffer (out) */ +-}; +- +-/* +- * Buffer mapping incoming and outgoing information. +- */ +-struct mc_ioctl_buffer { +- uint64_t va; /* user space address of buffer */ +- uint32_t len; /* buffer length */ +- uint64_t sva; /* SWd virt address of buffer (out) */ +-}; +- +-/* +- * Data exchange structure of the MC_IO_MAP and MC_IO_UNMAP ioctl commands. +- */ +-struct mc_ioctl_map { +- uint32_t sid; /* session id */ +- struct mc_ioctl_buffer bufs[MC_MAP_MAX];/* buffers info */ +-}; +- +-/* +- * Data exchange structure of the MC_IO_ERR ioctl command. +- */ +-struct mc_ioctl_geterr { +- uint32_t sid; /* session id */ +- int32_t value; /* error value (out) */ +-}; +- +-/* +- * Global MobiCore Version Information. +- */ +-struct mc_version_info { +- char product_id[MC_PRODUCT_ID_LEN]; /** Product ID string */ +- uint32_t version_mci; /** Mobicore Control Interface */ +- uint32_t version_so; /** Secure Objects */ +- uint32_t version_mclf; /** MobiCore Load Format */ +- uint32_t version_container; /** MobiCore Container Format */ +- uint32_t version_mc_config; /** MobiCore Config. Block Format */ +- uint32_t version_tl_api; /** MobiCore Trustlet API */ +- uint32_t version_dr_api; /** MobiCore Driver API */ +- uint32_t version_cmp; /** Content Management Protocol */ +-}; +- +-/* +- * defines for the ioctl mobicore driver module function call from user space. +- */ +-/* MobiCore IOCTL magic number */ +-#define MC_IOC_MAGIC 'M' +- +-/* +- * Implement corresponding functions from user api +- */ +-#define MC_IO_OPEN_SESSION \ +- _IOWR(MC_IOC_MAGIC, 0, struct mc_ioctl_open_sess) +-#define MC_IO_OPEN_TRUSTLET \ +- _IOWR(MC_IOC_MAGIC, 1, struct mc_ioctl_open_trustlet) +-#define MC_IO_CLOSE_SESSION _IO(MC_IOC_MAGIC, 2) +-#define MC_IO_NOTIFY _IO(MC_IOC_MAGIC, 3) +-#define MC_IO_WAIT _IOW(MC_IOC_MAGIC, 4, struct mc_ioctl_wait) +-#define MC_IO_MAP _IOWR(MC_IOC_MAGIC, 5, struct mc_ioctl_map) +-#define MC_IO_UNMAP _IOW(MC_IOC_MAGIC, 6, struct mc_ioctl_map) +-#define MC_IO_ERR _IOWR(MC_IOC_MAGIC, 7, struct mc_ioctl_geterr) +-#define MC_IO_FREEZE _IO(MC_IOC_MAGIC, 8) +-#define MC_IO_VERSION _IOR(MC_IOC_MAGIC, 9, struct mc_version_info) +-#define MC_IO_DR_VERSION _IOR(MC_IOC_MAGIC, 10, uint32_t) +- +-#endif /* _MC_LINUX_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/public/mc_linux_api.h b/drivers/gud/MobiCoreDriver/public/mc_linux_api.h +deleted file mode 100644 +index 211bc2682b754..0000000000000 +--- a/drivers/gud/MobiCoreDriver/public/mc_linux_api.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-/* +- * Copyright (c) 2013-2014 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#ifndef _MC_LINUX_API_H_ +-#define _MC_LINUX_API_H_ +- +-/* +- * Switch tbase active core to core_num, defined as linux +- * core id +- */ +-int mc_switch_core(uint32_t core_num); +- +-/* +- * Return tbase active core as Linux core id +- */ +-uint32_t mc_active_core(void); +- +-#endif /* _MC_LINUX_API_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h b/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h +deleted file mode 100644 +index 005099532d73a..0000000000000 +--- a/drivers/gud/MobiCoreDriver/public/mobicore_driver_api.h ++++ /dev/null +@@ -1,450 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#ifndef _MOBICORE_DRIVER_API_H_ +-#define _MOBICORE_DRIVER_API_H_ +- +-#include "mc_linux.h" +- +-#define __MC_CLIENT_LIB_API +- +-/* +- * Return values of MobiCore driver functions. +- */ +-enum mc_result { +- /* Function call succeeded. */ +- MC_DRV_OK = 0, +- /* No notification available. */ +- MC_DRV_NO_NOTIFICATION = 1, +- /* Error during notification on communication level. */ +- MC_DRV_ERR_NOTIFICATION = 2, +- /* Function not implemented. */ +- MC_DRV_ERR_NOT_IMPLEMENTED = 3, +- /* No more resources available. */ +- MC_DRV_ERR_OUT_OF_RESOURCES = 4, +- /* Driver initialization failed. */ +- MC_DRV_ERR_INIT = 5, +- /* Unknown error. */ +- MC_DRV_ERR_UNKNOWN = 6, +- /* The specified device is unknown. */ +- MC_DRV_ERR_UNKNOWN_DEVICE = 7, +- /* The specified session is unknown.*/ +- MC_DRV_ERR_UNKNOWN_SESSION = 8, +- /* The specified operation is not allowed. */ +- MC_DRV_ERR_INVALID_OPERATION = 9, +- /* The response header from the MC is invalid. */ +- MC_DRV_ERR_INVALID_RESPONSE = 10, +- /* Function call timed out. */ +- MC_DRV_ERR_TIMEOUT = 11, +- /* Can not allocate additional memory. */ +- MC_DRV_ERR_NO_FREE_MEMORY = 12, +- /* Free memory failed. */ +- MC_DRV_ERR_FREE_MEMORY_FAILED = 13, +- /* Still some open sessions pending. */ +- MC_DRV_ERR_SESSION_PENDING = 14, +- /* MC daemon not reachable */ +- MC_DRV_ERR_DAEMON_UNREACHABLE = 15, +- /* The device file of the kernel module could not be opened. */ +- MC_DRV_ERR_INVALID_DEVICE_FILE = 16, +- /* Invalid parameter. */ +- MC_DRV_ERR_INVALID_PARAMETER = 17, +- /* Unspecified error from Kernel Module*/ +- MC_DRV_ERR_KERNEL_MODULE = 18, +- /* Error during mapping of additional bulk memory to session. */ +- MC_DRV_ERR_BULK_MAPPING = 19, +- /* Error during unmapping of additional bulk memory to session. */ +- MC_DRV_ERR_BULK_UNMAPPING = 20, +- /* Notification received, exit code available. */ +- MC_DRV_INFO_NOTIFICATION = 21, +- /* Set up of NWd connection failed. */ +- MC_DRV_ERR_NQ_FAILED = 22, +- /* Wrong daemon version. */ +- MC_DRV_ERR_DAEMON_VERSION = 23, +- /* Wrong container version. */ +- MC_DRV_ERR_CONTAINER_VERSION = 24, +- /* System Trustlet public key is wrong. */ +- MC_DRV_ERR_WRONG_PUBLIC_KEY = 25, +- /* Wrong container type(s). */ +- MC_DRV_ERR_CONTAINER_TYPE_MISMATCH = 26, +- /* Container is locked (or not activated). */ +- MC_DRV_ERR_CONTAINER_LOCKED = 27, +- /* SPID is not registered with root container. */ +- MC_DRV_ERR_SP_NO_CHILD = 28, +- /* UUID is not registered with sp container. */ +- MC_DRV_ERR_TL_NO_CHILD = 29, +- /* Unwrapping of root container failed. */ +- MC_DRV_ERR_UNWRAP_ROOT_FAILED = 30, +- /* Unwrapping of service provider container failed. */ +- MC_DRV_ERR_UNWRAP_SP_FAILED = 31, +- /* Unwrapping of Trustlet container failed. */ +- MC_DRV_ERR_UNWRAP_TRUSTLET_FAILED = 32, +- /* No device associated with connection. */ +- MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN = 33, +- /* TA blob attestation is incorrect. */ +- MC_DRV_ERR_TA_ATTESTATION_ERROR = 34, +- /* Interrupted system call. */ +- MC_DRV_ERR_INTERRUPTED_BY_SIGNAL = 35, +- /* Service is blocked and opensession is thus not allowed. */ +- MC_DRV_ERR_SERVICE_BLOCKED = 36, +- /* Service is locked and opensession is thus not allowed. */ +- MC_DRV_ERR_SERVICE_LOCKED = 37, +- /* Service was killed by the TEE (due to an administrative command). */ +- MC_DRV_ERR_SERVICE_KILLED = 38, +- /* All permitted instances to the service are used */ +- MC_DRV_ERR_NO_FREE_INSTANCES = 39, +- /* TA blob header is incorrect. */ +- MC_DRV_ERR_TA_HEADER_ERROR = 40, +-}; +- +-/* +- * Structure of Session Handle, includes the Session ID and the Device ID the +- * Session belongs to. +- * The session handle will be used for session-based MobiCore communication. +- * It will be passed to calls which address a communication end point in the +- * MobiCore environment. +- */ +-struct mc_session_handle { +- uint32_t session_id; /* MobiCore session ID */ +- uint32_t device_id; /* Device ID the session belongs to */ +-}; +- +-/* +- * Information structure about additional mapped Bulk buffer between the +- * Trustlet Connector (NWd) and the Trustlet (SWd). This structure is +- * initialized from a Trustlet Connector by calling mc_map(). +- * In order to use the memory within a Trustlet the Trustlet Connector has to +- * inform the Trustlet with the content of this structure via the TCI. +- */ +-struct mc_bulk_map { +- /* The virtual address of the Bulk buffer regarding the address space +- * of the Trustlet, already includes a possible offset! */ +- uint32_t secure_virt_addr; +- uint32_t secure_virt_len; /* Length of the mapped Bulk buffer */ +-}; +- +-/* The default device ID */ +-#define MC_DEVICE_ID_DEFAULT 0 +-/* Wait infinite for a response of the MC. */ +-#define MC_INFINITE_TIMEOUT ((int32_t)(-1)) +-/* Do not wait for a response of the MC. */ +-#define MC_NO_TIMEOUT 0 +-/* TCI/DCI must not exceed 1MiB */ +-#define MC_MAX_TCI_LEN 0x100000 +- +-/** +- * mc_open_device() - Open a new connection to a MobiCore device. +- * @device_id: Identifier for the MobiCore device to be used. +- * MC_DEVICE_ID_DEFAULT refers to the default device. +- * +- * Initializes all device specific resources required to communicate with a +- * MobiCore instance located on the specified device in the system. If the +- * device does not exist the function will return MC_DRV_ERR_UNKNOWN_DEVICE. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_ERR_INVALID_OPERATION: device already opened +- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon +- * MC_DRV_ERR_UNKNOWN_DEVICE: device_id unknown +- * MC_DRV_ERR_INVALID_DEVICE_FILE: kernel module under /dev/mobicore +- * cannot be opened +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_open_device(uint32_t device_id); +- +-/** +- * mc_close_device() - Close the connection to a MobiCore device. +- * @device_id: Identifier for the MobiCore device. +- * +- * When closing a device, active sessions have to be closed beforehand. +- * Resources associated with the device will be released. +- * The device may be opened again after it has been closed. +- * +- * MC_DEVICE_ID_DEFAULT refers to the default device. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid +- * MC_DRV_ERR_SESSION_PENDING: a session is still open +- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_close_device(uint32_t device_id); +- +-/** +- * mc_open_session() - Open a new session to a Trustlet. +- * @session: On success, the session data will be returned +- * @uuid: UUID of the Trustlet to be opened +- * @tci: TCI buffer for communicating with the Trustlet +- * @tci_len: Length of the TCI buffer. Maximum allowed value +- * is MC_MAX_TCI_LEN +- * +- * The Trustlet with the given UUID has to be available in the flash filesystem. +- * +- * Write MCP open message to buffer and notify MobiCore about the availability +- * of a new command. +- * +- * Waits till the MobiCore responses with the new session ID (stored in the MCP +- * buffer). +- * +- * Note that session.device_id has to be the device id of an opened device. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: session parameter is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid +- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon socket occur +- * MC_DRV_ERR_NQ_FAILED: daemon returns an error +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_open_session( +- struct mc_session_handle *session, const struct mc_uuid_t *uuid, +- uint8_t *tci, uint32_t tci_len); +- +-/** +- * mc_open_trustlet() - Open a new session to the provided Trustlet. +- * @session: On success, the session data will be returned +- * @spid: Service Provider ID (for SP trustlets otherwise ignored) +- * @trustlet Memory buffer containing the Trusted Application binary +- * @trustlet_len Trusted Application length +- * @tci: TCI buffer for communicating with the Trustlet +- * @tci_len: Length of the TCI buffer. Maximum allowed value +- * is MC_MAX_TCI_LEN +- * +- * Write MCP open message to buffer and notify MobiCore about the availability +- * of a new command. +- * +- * Waits till the MobiCore responses with the new session ID (stored in the MCP +- * buffer). +- * +- * Note that session.device_id has to be the device id of an opened device. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: session parameter is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid +- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon socket occur +- * MC_DRV_ERR_NQ_FAILED: daemon returns an error +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_open_trustlet( +- struct mc_session_handle *session, uint32_t spid, +- uint8_t *trustlet, uint32_t trustlet_len, uint8_t *tci, uint32_t len); +- +-/** +- * mc_close_session() - Close a Trustlet session. +- * @session: Session to be closed. +- * +- * Closes the specified MobiCore session. The call will block until the +- * session has been closed. +- * +- * Device device_id has to be opened in advance. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: session parameter is invalid +- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid +- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur +- * MC_DRV_ERR_INVALID_DEVICE_FILE: daemon cannot open Trustlet file +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_close_session( +- struct mc_session_handle *session); +- +-/** +- * mc_notify() - Notify a session. +- * @session: The session to be notified. +- * +- * Notifies the session end point about available message data. +- * If the session parameter is correct, notify will always succeed. +- * Corresponding errors can only be received by mc_wait_notification(). +- * +- * A session has to be opened in advance. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: session parameter is invalid +- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_notify(struct mc_session_handle *session); +- +-/** +- * mc_wait_notification() - Wait for a notification. +- * @session: The session the notification should correspond to. +- * @timeout: Time in milliseconds to wait +- * (MC_NO_TIMEOUT : direct return, > 0 : milliseconds, +- * MC_INFINITE_TIMEOUT : wait infinitely) +- * +- * Wait for a notification issued by the MobiCore for a specific session. +- * The timeout parameter specifies the number of milliseconds the call will wait +- * for a notification. +- * +- * If the caller passes 0 as timeout value the call will immediately return. +- * If timeout value is below 0 the call will block until a notification for the +- * session has been received. +- * +- * If timeout is below 0, call will block. +- * +- * Caller has to trust the other side to send a notification to wake him up +- * again. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_ERR_TIMEOUT: no notification arrived in time +- * MC_DRV_INFO_NOTIFICATION: a problem with the session was +- * encountered. Get more details with +- * mc_get_session_error_code() +- * MC_DRV_ERR_NOTIFICATION: a problem with the socket occurred +- * MC_DRV_INVALID_PARAMETER: a parameter is invalid +- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_wait_notification( +- struct mc_session_handle *session, int32_t timeout); +- +-/** +- * mc_malloc_wsm() - Allocate a block of world shared memory (WSM). +- * @device_id: The ID of an opened device to retrieve the WSM from. +- * @align: The alignment (number of pages) of the memory block +- * (e.g. 0x00000001 for 4kb). +- * @len: Length of the block in bytes. +- * @wsm: Virtual address of the world shared memory block. +- * @wsm_flags: Platform specific flags describing the memory to +- * be allocated. +- * +- * The MC driver allocates a contiguous block of memory which can be used as +- * WSM. +- * This implicates that the allocated memory is aligned according to the +- * alignment parameter. +- * +- * Always returns a buffer of size WSM_SIZE aligned to 4K. +- * +- * Align and wsm_flags are currently ignored +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: a parameter is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id is invalid +- * MC_DRV_ERR_NO_FREE_MEMORY: no more contiguous memory is +- * available in this size or for this +- * process +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_malloc_wsm( +- uint32_t device_id, +- uint32_t align, +- uint32_t len, +- uint8_t **wsm, +- uint32_t wsm_flags +-); +- +-/** +- * mc_free_wsm() - Free a block of world shared memory (WSM). +- * @device_id: The ID to which the given address belongs +- * @wsm: Address of WSM block to be freed +- * +- * The MC driver will free a block of world shared memory (WSM) previously +- * allocated with mc_malloc_wsm(). The caller has to assure that the address +- * handed over to the driver is a valid WSM address. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: a parameter is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: when device id is invalid +- * MC_DRV_ERR_FREE_MEMORY_FAILED: on failure +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_free_wsm(uint32_t device_id, +- uint8_t *wsm); +- +-/** +- *mc_map() - Map additional bulk buffer between a Trustlet Connector (TLC) +- * and the Trustlet (TL) for a session +- * @session: Session handle with information of the device_id and +- * the session_id. The given buffer is mapped to the +- * session specified in the sessionHandle +- * @buf: Virtual address of a memory portion (relative to TLC) +- * to be shared with the Trustlet, already includes a +- * possible offset! +- * @len: length of buffer block in bytes. +- * @map_info: Information structure about the mapped Bulk buffer +- * between the TLC (NWd) and the TL (SWd). +- * +- * Memory allocated in user space of the TLC can be mapped as additional +- * communication channel (besides TCI) to the Trustlet. Limitation of the +- * Trustlet memory structure apply: only 6 chunks can be mapped with a maximum +- * chunk size of 1 MiB each. +- * +- * It is up to the application layer (TLC) to inform the Trustlet +- * about the additional mapped bulk memory. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: a parameter is invalid +- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid +- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur +- * MC_DRV_ERR_BULK_MAPPING: buf is already uses as bulk buffer or +- * when registering the buffer failed +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_map( +- struct mc_session_handle *session, void *buf, uint32_t len, +- struct mc_bulk_map *map_info); +- +-/** +- * mc_unmap() - Remove additional mapped bulk buffer between Trustlet Connector +- * (TLC) and the Trustlet (TL) for a session +- * @session: Session handle with information of the device_id and +- * the session_id. The given buffer is unmapped from the +- * session specified in the sessionHandle. +- * @buf: Virtual address of a memory portion (relative to TLC) +- * shared with the TL, already includes a possible offset! +- * @map_info: Information structure about the mapped Bulk buffer +- * between the TLC (NWd) and the TL (SWd) +- * +- * The bulk buffer will immediately be unmapped from the session context. +- * +- * The application layer (TLC) must inform the TL about unmapping of the +- * additional bulk memory before calling mc_unmap! +- * +- * The clientlib currently ignores the len field in map_info. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: a parameter is invalid +- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid +- * MC_DRV_ERR_DAEMON_UNREACHABLE: problems with daemon occur +- * MC_DRV_ERR_BULK_UNMAPPING: buf was not registered earlier +- * or when unregistering failed +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_unmap( +- struct mc_session_handle *session, void *buf, +- struct mc_bulk_map *map_info); +- +-/* +- * mc_get_session_error_code() - Get additional error information of the last +- * error that occurred on a session. +- * @session: Session handle with information of the device_id and +- * the session_id +- * @exit_code: >0 Trustlet has terminated itself with this value, +- * <0 Trustlet is dead because of an error within the +- * MobiCore (e.g. Kernel exception). See also MCI +- * definition. +- * +- * After the request the stored error code will be deleted. +- * +- * Return codes: +- * MC_DRV_OK: operation completed successfully +- * MC_DRV_INVALID_PARAMETER: a parameter is invalid +- * MC_DRV_ERR_UNKNOWN_SESSION: session id is invalid +- * MC_DRV_ERR_UNKNOWN_DEVICE: device id of session is invalid +- */ +-__MC_CLIENT_LIB_API enum mc_result mc_get_session_error_code( +- struct mc_session_handle *session, int32_t *exit_code); +- +-#endif /* _MOBICORE_DRIVER_API_H_ */ +diff --git a/drivers/gud/MobiCoreDriver/scheduler.c b/drivers/gud/MobiCoreDriver/scheduler.c +deleted file mode 100644 +index 444f839d8ad1d..0000000000000 +--- a/drivers/gud/MobiCoreDriver/scheduler.c ++++ /dev/null +@@ -1,231 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +- +-#include "main.h" +-#include "fastcall.h" +-#include "debug.h" +-#include "logging.h" +-#include "mcp.h" +-#include "scheduler.h" +- +-#define SCHEDULING_FREQ 5 /**< N-SIQ every n-th time */ +- +-static struct sched_ctx { +- struct task_struct *thread; +- bool thread_run; +- struct completion idle_complete; /* Unblock scheduler thread */ +- struct completion sleep_complete; /* Wait for sleep status */ +- struct mutex sleep_mutex; /* Protect sleep request */ +- struct mutex request_mutex; /* Protect all below */ +- /* The order of this enum matters */ +- enum { +- NONE, /* No specific request */ +- YIELD, /* Run the SWd */ +- NSIQ, /* Schedule the SWd */ +- SUSPEND, /* Suspend the SWd */ +- RESUME, /* Resume the SWd */ +- } request; +- bool suspended; +-} sched_ctx; +- +-static int mc_scheduler_command(int command) +-{ +- if (IS_ERR_OR_NULL(sched_ctx.thread)) +- return -EFAULT; +- +- mutex_lock(&sched_ctx.request_mutex); +- if (sched_ctx.request < command) { +- sched_ctx.request = command; +- complete(&sched_ctx.idle_complete); +- } +- +- mutex_unlock(&sched_ctx.request_mutex); +- return 0; +-} +- +-static int mc_scheduler_pm_command(int command) +-{ +- int ret = -EPERM; +- +- if (IS_ERR_OR_NULL(sched_ctx.thread)) +- return -EFAULT; +- +- mutex_lock(&sched_ctx.sleep_mutex); +- +- /* Send request */ +- mc_scheduler_command(command); +- +- /* Wait for scheduler to reply */ +- wait_for_completion(&sched_ctx.sleep_complete); +- mutex_lock(&sched_ctx.request_mutex); +- if (command == SUSPEND) { +- if (sched_ctx.suspended) +- ret = 0; +- } else { +- if (!sched_ctx.suspended) +- ret = 0; +- } +- +- mutex_unlock(&sched_ctx.request_mutex); +- +- mutex_unlock(&sched_ctx.sleep_mutex); +- return ret; +-} +- +-static int mc_dev_command(enum mcp_scheduler_commands command) +-{ +- switch (command) { +- case MCP_YIELD: +- return mc_scheduler_command(YIELD); +- case MCP_NSIQ: +- return mc_scheduler_command(NSIQ); +- } +- +- return -EINVAL; +-} +- +-int mc_scheduler_suspend(void) +-{ +- return mc_scheduler_pm_command(SUSPEND); +-} +- +-int mc_scheduler_resume(void) +-{ +- return mc_scheduler_pm_command(RESUME); +-} +- +-/* +- * This thread, and only this thread, schedules the SWd. Hence, reading the idle +- * status and its associated timeout is safe from race conditions. +- */ +-static int tee_scheduler(void *arg) +-{ +- int timeslice = 0; /* Actually scheduling period */ +- int ret = 0; +- +- MCDRV_DBG("enter"); +- while (1) { +- int32_t timeout_ms = -1; +- bool pm_request = false; +- +- if (sched_ctx.suspended || mcp_get_idle_timeout(&timeout_ms)) { +- /* If timeout is 0 we keep scheduling the SWd */ +- if (!timeout_ms) +- mc_scheduler_command(NSIQ); +- else if (timeout_ms < 0) +- wait_for_completion(&sched_ctx.idle_complete); +- else if (!wait_for_completion_timeout( +- &sched_ctx.idle_complete, +- msecs_to_jiffies(timeout_ms))) +- /* Timed out, force SWd schedule */ +- mc_scheduler_command(NSIQ); +- } +- +- if (kthread_should_stop() || !sched_ctx.thread_run) +- break; +- +- /* Get requested command if any */ +- mutex_lock(&sched_ctx.request_mutex); +- if (sched_ctx.request == YIELD) +- /* Yield forced: increment timeslice */ +- timeslice++; +- else if (sched_ctx.request >= NSIQ) { +- /* Force N_SIQ, also to suspend/resume SWd */ +- timeslice = 0; +- if (sched_ctx.request == SUSPEND) { +- mcp_suspend(); +- pm_request = true; +- } else if (sched_ctx.request == RESUME) { +- mcp_resume(); +- pm_request = true; +- } +- } +- +- sched_ctx.request = NONE; +- mutex_unlock(&sched_ctx.request_mutex); +- +- /* Reset timeout so we don't loop if SWd halted */ +- mcp_reset_idle_timeout(); +- if (timeslice--) { +- /* Resume SWd from where it was */ +- ret = mc_fc_yield(); +- } else { +- timeslice = SCHEDULING_FREQ; +- /* Call SWd scheduler */ +- ret = mc_fc_nsiq(); +- } +- +- /* Always flush log buffer after the SWd has run */ +- mc_logging_run(); +- if (ret) +- break; +- +- /* Should have suspended by now if requested */ +- mutex_lock(&sched_ctx.request_mutex); +- if (pm_request) { +- sched_ctx.suspended = mcp_suspended(); +- complete(&sched_ctx.sleep_complete); +- } +- +- mutex_unlock(&sched_ctx.request_mutex); +- +- /* Flush pending notifications if possible */ +- if (mcp_notifications_flush()) +- complete(&sched_ctx.idle_complete); +- } +- +- MCDRV_DBG("exit, ret is %d", ret); +- return ret; +-} +- +-int mc_scheduler_start(void) +-{ +- sched_ctx.thread_run = true; +- sched_ctx.thread = kthread_run(tee_scheduler, NULL, "tee_scheduler"); +- if (IS_ERR(sched_ctx.thread)) { +- MCDRV_ERROR("tee_scheduler thread creation failed"); +- return PTR_ERR(sched_ctx.thread); +- } +- +- mcp_register_scheduler(mc_dev_command); +- complete(&sched_ctx.idle_complete); +- return 0; +-} +- +-void mc_scheduler_stop(void) +-{ +- mcp_register_scheduler(NULL); +- sched_ctx.thread_run = false; +- complete(&sched_ctx.idle_complete); +- kthread_stop(sched_ctx.thread); +-} +- +-int mc_scheduler_init(void) +-{ +- init_completion(&sched_ctx.idle_complete); +- init_completion(&sched_ctx.sleep_complete); +- mutex_init(&sched_ctx.sleep_mutex); +- mutex_init(&sched_ctx.request_mutex); +- return 0; +-} +diff --git a/drivers/gud/MobiCoreDriver/scheduler.h b/drivers/gud/MobiCoreDriver/scheduler.h +deleted file mode 100644 +index c3c17f1c9017c..0000000000000 +--- a/drivers/gud/MobiCoreDriver/scheduler.h ++++ /dev/null +@@ -1,25 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef __MC_SCHEDULER_H__ +-#define __MC_SCHEDULER_H__ +- +-int mc_scheduler_init(void); +-static inline void mc_scheduler_exit(void) {} +-int mc_scheduler_start(void); +-void mc_scheduler_stop(void); +-int mc_scheduler_suspend(void); +-int mc_scheduler_resume(void); +- +-#endif /* __MC_SCHEDULER_H__ */ +diff --git a/drivers/gud/MobiCoreDriver/session.c b/drivers/gud/MobiCoreDriver/session.c +deleted file mode 100644 +index 1dbb8900b2b3a..0000000000000 +--- a/drivers/gud/MobiCoreDriver/session.c ++++ /dev/null +@@ -1,779 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "public/mc_linux.h" +-#include "public/mc_admin.h" +- +-#include "platform.h" /* MC_UIDGID_OLDSTYLE */ +-#include "main.h" +-#include "debug.h" +-#include "mmu.h" +-#include "mcp.h" +-#include "client.h" /* *cbuf* */ +-#include "session.h" +-#include "mci/mcimcp.h" +- +-#define SHA1_HASH_SIZE 20 +- +-struct tbase_wsm { +- /* Buffer NWd addr (uva or kva, used only for lookup) */ +- uintptr_t va; +- /* buffer length */ +- uint32_t len; +- /* Buffer SWd addr */ +- uint32_t sva; +- /* mmu L2 table */ +- struct tbase_mmu *mmu; +- /* possibly a pointer to a cbuf */ +- struct tbase_cbuf *cbuf; +- /* list node */ +- struct list_head list; +-}; +- +-/* +- * Postponed closing for GP TAs. +- * Implemented as a worker because cannot be executed from within isr_worker. +- */ +-static void session_close_worker(struct work_struct *work) +-{ +- struct mcp_session *mcp_session; +- struct tbase_session *session; +- +- mcp_session = container_of(work, struct mcp_session, close_work); +- session = container_of(mcp_session, struct tbase_session, mcp_session); +- session_close(session); +-} +- +-/* Forward declarations */ +-static struct tbase_wsm *wsm_create(struct tbase_session *session, +- uintptr_t buf, uint32_t len); +-static void wsm_free(struct tbase_wsm *wsm); +- +-static int hash_path_and_data(char *hash, const void *data, +- unsigned int data_len) +-{ +- struct mm_struct *mm = current->mm; +- struct hash_desc desc; +- struct scatterlist sg; +- char *buf; +- char *path; +- unsigned int path_len; +- int ret = 0; +- +- buf = (char *)__get_free_page(GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- +- down_read(&mm->mmap_sem); +- if (!mm->exe_file) { +- ret = -ENOENT; +- goto end; +- } +- +- path = d_path(&mm->exe_file->f_path, buf, PAGE_SIZE); +- if (IS_ERR(path)) { +- ret = PTR_ERR(path); +- goto end; +- } +- +- MCDRV_DBG("current process path = "); +- { +- char *c; +- +- for (c = path; *c; c++) +- MCDRV_DBG("%c %d", *c, *c); +- } +- +- path_len = strnlen(path, PAGE_SIZE); +- MCDRV_DBG("path_len = %u", path_len); +- desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); +- if (IS_ERR(desc.tfm)) { +- ret = PTR_ERR(desc.tfm); +- MCDRV_DBG("could not alloc hash = %d", ret); +- goto end; +- } +- +- desc.flags = 0; +- sg_init_one(&sg, path, path_len); +- crypto_hash_init(&desc); +- crypto_hash_update(&desc, &sg, path_len); +- if (data) { +- MCDRV_DBG("current process path: hashing additional data\n"); +- sg_init_one(&sg, data, data_len); +- crypto_hash_update(&desc, &sg, data_len); +- } +- +- crypto_hash_final(&desc, hash); +- crypto_free_hash(desc.tfm); +- +-end: +- up_read(&mm->mmap_sem); +- free_page((unsigned long)buf); +- +- return ret; +-} +- +-static int check_prepare_identity(const struct mc_identity *identity, +- struct identity *mcp_identity) +-{ +- struct mc_identity *mcp_id = (struct mc_identity *)mcp_identity; +- uint8_t hash[SHA1_HASH_SIZE]; +- bool application = false; +- const void *data; +- unsigned int data_len; +- +- /* Mobicore doesn't support GP client authentication. */ +- if (!g_ctx.f_client_login && +- (identity->login_type != TEEC_LOGIN_PUBLIC)) { +- MCDRV_DBG_WARN("Unsupported login type %d", +- identity->login_type); +- return -EINVAL; +- } +- +- /* Copy login type */ +- mcp_identity->login_type = identity->login_type; +- +- /* Fill in uid field */ +- if ((identity->login_type == TEEC_LOGIN_USER) || +- (identity->login_type == TEEC_LOGIN_USER_APPLICATION)) { +- /* Set euid and ruid of the process. */ +-#if !defined(KUIDT_INIT) || defined(MC_UIDGID_OLDSTYLE) +- mcp_id->uid.euid = current_euid(); +- mcp_id->uid.ruid = current_uid(); +-#else +- mcp_id->uid.euid = current_euid().val; +- mcp_id->uid.ruid = current_uid().val; +-#endif +- } +- +- /* Check gid field */ +- if ((identity->login_type == TEEC_LOGIN_GROUP) || +- (identity->login_type == TEEC_LOGIN_GROUP_APPLICATION)) { +-#if !defined(KUIDT_INIT) || defined(MC_UIDGID_OLDSTYLE) +- gid_t gid = identity->gid; +-#else +- kgid_t gid = { +- .val = identity->gid, +- }; +-#endif +- /* Check if gid is one of: egid of the process, its rgid or one +- * of its supplementary groups */ +- if (!in_egroup_p(gid) && !in_group_p(gid)) { +- MCDRV_DBG("group %d not allowed", identity->gid); +- return -EACCES; +- } +- +- MCDRV_DBG("group %d found", identity->gid); +- mcp_id->gid = identity->gid; +- } +- +- switch (identity->login_type) { +- case TEEC_LOGIN_PUBLIC: +- case TEEC_LOGIN_USER: +- case TEEC_LOGIN_GROUP: +- break; +- case TEEC_LOGIN_APPLICATION: +- application = true; +- data = NULL; +- data_len = 0; +- break; +- case TEEC_LOGIN_USER_APPLICATION: +- application = true; +- data = &mcp_id->uid; +- data_len = sizeof(mcp_id->uid); +- break; +- case TEEC_LOGIN_GROUP_APPLICATION: +- application = true; +- data = &identity->gid; +- data_len = sizeof(identity->gid); +- break; +- default: +- /* Any other login_type value is invalid. */ +- MCDRV_DBG_WARN("Invalid login type"); +- return -EINVAL; +- } +- +- if (application) { +- if (hash_path_and_data(hash, data, data_len)) { +- MCDRV_DBG("error in hash calculation"); +- return -EAGAIN; +- } +- +- memcpy(&mcp_id->login_data, hash, sizeof(mcp_id->login_data)); +- } +- +- return 0; +-} +- +-/* +- * Create a session object. +- * Note: object is not attached to client yet. +- */ +-struct tbase_session *session_create(struct tbase_client *client, bool is_gp, +- struct mc_identity *identity) +-{ +- struct tbase_session *session; +- struct identity mcp_identity; +- +- if (is_gp) { +- /* Check identity method and data. */ +- int ret = check_prepare_identity(identity, &mcp_identity); +- +- if (ret) +- return ERR_PTR(ret); +- } +- +- /* Allocate session object */ +- session = kzalloc(sizeof(*session), GFP_KERNEL); +- if (!session) +- return ERR_PTR(-ENOMEM); +- +- mutex_init(&session->close_lock); +- /* Initialise object members */ +- mcp_session_init(&session->mcp_session, is_gp, &mcp_identity); +- INIT_WORK(&session->mcp_session.close_work, session_close_worker); +- session->client = client; +- kref_init(&session->kref); +- INIT_LIST_HEAD(&session->list); +- mutex_init(&session->wsms_lock); +- INIT_LIST_HEAD(&session->wsms); +- MCDRV_DBG("created session %p: client %p", session, session->client); +- return session; +-} +- +-int session_open(struct tbase_session *session, const struct tbase_object *obj, +- const struct tbase_mmu *obj_mmu, uintptr_t tci, size_t len) +-{ +- struct mcp_buffer_map map; +- +- tbase_mmu_buffer(obj_mmu, &map); +- /* Create wsm object for tci */ +- if (tci && len) { +- struct tbase_wsm *wsm; +- struct mcp_buffer_map tci_map; +- int ret = 0; +- +- mutex_lock(&session->wsms_lock); +- wsm = wsm_create(session, tci, len); +- if (IS_ERR(wsm)) +- ret = PTR_ERR(wsm); +- +- mutex_unlock(&session->wsms_lock); +- if (ret) +- return ret; +- +- tbase_mmu_buffer(wsm->mmu, &tci_map); +- ret = mcp_open_session(&session->mcp_session, obj, &map, +- &tci_map); +- if (ret) { +- mutex_lock(&session->wsms_lock); +- wsm_free(wsm); +- mutex_unlock(&session->wsms_lock); +- } +- +- return ret; +- } +- +- if (tci || len) { +- MCDRV_ERROR("Tci pointer and length are incoherent"); +- return -EINVAL; +- } +- +- return mcp_open_session(&session->mcp_session, obj, &map, NULL); +-} +- +-/* +- * Close TA and unreference session object. +- * Object will be freed if reference reaches 0. +- * Session object is assumed to have been removed from main list, which means +- * that session_close cannot be called anymore. +- */ +-int session_close(struct tbase_session *session) +-{ +- int ret = 0; +- +- if (!session) +- return -ENXIO; +- +- mutex_lock(&session->close_lock); +- switch (mcp_close_session(&session->mcp_session)) { +- case 0: +- /* TA is closed, remove from closing list */ +- mutex_lock(&g_ctx.closing_lock); +- list_del(&session->list); +- mutex_unlock(&g_ctx.closing_lock); +- /* Remove the ref we took on creation, exit if session freed */ +- if (session_put(session)) +- return 0; +- +- break; +- case -EBUSY: +- /* +- * (GP) TA needs time to close. The "TA closed" notification +- * will trigger a new call to session_close(). +- * Return OK but do not unref. +- */ +- break; +- default: +- MCDRV_ERROR("Failed to close session %x in SWd", +- session->mcp_session.id); +- ret = -EPERM; +- } +- +- mutex_unlock(&session->close_lock); +- return ret; +-} +- +-/* +- * Free session object and all objects it contains (wsm). +- */ +-static void session_free(struct kref *kref) +-{ +- struct tbase_session *session; +- struct tbase_wsm *wsm, *next; +- +- /* Remove remaining shared buffers (unmapped in SWd by mcp_close) */ +- session = container_of(kref, struct tbase_session, kref); +- list_for_each_entry_safe(wsm, next, &session->wsms, list) { +- MCDRV_DBG("session %p: free wsm %p", session, wsm); +- wsm_free(wsm); +- } +- +- MCDRV_DBG("freed session %p: client %p id %x", +- session, session->client, session->mcp_session.id); +- kfree(session); +-} +- +-/* +- * Unreference session. +- * Free session object if reference reaches 0. +- */ +-int session_put(struct tbase_session *session) +-{ +- return kref_put(&session->kref, session_free); +-} +- +-/* +- * Send a notification to TA +- */ +-int session_notify_swd(struct tbase_session *session) +-{ +- if (!session) { +- MCDRV_ERROR("Session pointer is null"); +- return -EINVAL; +- } +- +- return mcp_notify(&session->mcp_session); +-} +- +-/* +- * Read and clear last notification received from TA +- */ +-int32_t session_exitcode(struct tbase_session *session) +-{ +- return mcp_session_exitcode(&session->mcp_session); +-} +- +-/* +- * Free a WSM object +- */ +-static void wsm_free(struct tbase_wsm *wsm) +-{ +- /* Remove wsm from its parent session's list */ +- list_del(&wsm->list); +- /* Free MMU table */ +- if (!IS_ERR_OR_NULL(wsm->mmu)) +- tbase_mmu_delete(wsm->mmu); +- +- /* Unref cbuf if applicable */ +- if (wsm->cbuf) +- tbase_cbuf_put(wsm->cbuf); +- +- /* Delete wsm object */ +- MCDRV_DBG("freed wsm %p: mmu %p cbuf %p va %lx len %u", +- wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len); +- kfree(wsm); +-} +- +-static struct tbase_wsm *wsm_create(struct tbase_session *session, +- uintptr_t buf, uint32_t len) +-{ +- struct tbase_wsm *wsm; +- struct task_struct *task = NULL; +- uintptr_t va; +- int ret; +- +- /* Allocate structure */ +- wsm = kzalloc(sizeof(*wsm), GFP_KERNEL); +- if (!wsm) { +- ret = -ENOMEM; +- goto err_no_wsm; +- } +- +- /* Add wsm to list so destroy can find it */ +- list_add(&wsm->list, &session->wsms); +- +- /* Check if buffer is contained in a cbuf */ +- wsm->cbuf = tbase_cbuf_get_by_addr(session->client, buf); +- if (wsm->cbuf) { +- uintptr_t offset; +- +- if (client_is_kernel(session->client)) +- offset = buf - tbase_cbuf_addr(wsm->cbuf); +- else +- offset = buf - tbase_cbuf_uaddr(wsm->cbuf); +- +- if ((offset + len) > tbase_cbuf_len(wsm->cbuf)) { +- ret = -EINVAL; +- MCDRV_ERROR("crosses cbuf boundary"); +- goto err; +- } +- /* Provide kernel virtual address */ +- va = tbase_cbuf_addr(wsm->cbuf) + offset; +- } else { +- /* Not a cbuf. va is uva or kva depending on client. */ +- /* Provide "task" if client is user */ +- va = buf; +- if (!client_is_kernel(session->client)) +- task = current; +- } +- +- /* Build MMU table for buffer */ +- wsm->mmu = tbase_mmu_create(task, (void *)va, len); +- if (IS_ERR(wsm->mmu)) { +- ret = PTR_ERR(wsm->mmu); +- goto err; +- } +- +- wsm->va = buf; +- wsm->len = len; +- MCDRV_DBG("created wsm %p: mmu %p cbuf %p va %lx len %u", +- wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len); +- goto end; +- +-err: +- wsm_free(wsm); +-err_no_wsm: +- wsm = ERR_PTR(ret); +-end: +- return wsm; +-} +- +-static inline int wsm_check(struct tbase_session *session, +- struct mc_ioctl_buffer *buf) +-{ +- struct tbase_wsm *wsm; +- +- list_for_each_entry(wsm, &session->wsms, list) { +- if ((buf->va < (wsm->va + wsm->len)) && +- ((buf->va + buf->len) > wsm->va)) { +- MCDRV_ERROR("buffer %lx overlaps with existing wsm", +- wsm->va); +- return -EADDRINUSE; +- } +- } +- +- return 0; +-} +- +-static inline struct tbase_wsm *wsm_find(struct tbase_session *session, +- uintptr_t va) +-{ +- struct tbase_wsm *wsm; +- +- list_for_each_entry(wsm, &session->wsms, list) +- if (wsm->va == va) +- return wsm; +- +- return NULL; +-} +- +-static inline int wsm_info(struct tbase_wsm *wsm, struct kasnprintf_buf *buf) +-{ +- ssize_t ret; +- +- ret = kasnprintf(buf, "\t\twsm %p: mmu %p cbuf %p va %lx len %u\n", +- wsm, wsm->mmu, wsm->cbuf, wsm->va, wsm->len); +- if (ret < 0) +- return ret; +- +- if (wsm->mmu) { +- ret = tbase_mmu_info(wsm->mmu, buf); +- if (ret < 0) +- return ret; +- } +- +- return 0; +-} +- +-/* +- * Share buffers with SWd and add corresponding WSM objects to session. +- */ +-int session_wsms_add(struct tbase_session *session, +- struct mc_ioctl_buffer *bufs) +-{ +- struct mc_ioctl_buffer *buf; +- struct mcp_buffer_map maps[MC_MAP_MAX]; +- struct mcp_buffer_map *map; +- int i, ret = 0; +- uint32_t n_null_buf = 0; +- +- /* Check parameters */ +- if (!session) +- return -ENXIO; +- +- /* Lock the session */ +- mutex_lock(&session->wsms_lock); +- +- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) { +- if (!buf->va) { +- n_null_buf++; +- continue; +- } +- +- /* Avoid mapping overlaps */ +- if (wsm_check(session, buf)) { +- ret = -EADDRINUSE; +- MCDRV_ERROR("maps[%d] va=%llx already map'd", i, +- buf->va); +- goto unlock; +- } +- } +- +- if (n_null_buf >= MC_MAP_MAX) { +- ret = -EINVAL; +- MCDRV_ERROR("va=NULL"); +- goto unlock; +- } +- +- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) { +- struct tbase_wsm *wsm; +- +- if (!buf->va) { +- map->type = WSM_INVALID; +- continue; +- } +- +- wsm = wsm_create(session, buf->va, buf->len); +- if (IS_ERR(wsm)) { +- ret = PTR_ERR(wsm); +- MCDRV_ERROR("maps[%d] va=%llx create failed: %d", i, +- buf->va, ret); +- goto end; +- } +- +- tbase_mmu_buffer(wsm->mmu, map); +- MCDRV_DBG("maps[%d] va=%llx: t:%u a:%llx o:%u l:%u", i, buf->va, +- map->type, map->phys_addr, map->offset, map->length); +- } +- +- /* Map buffers */ +- if (g_ctx.f_multimap) { +- /* Send MCP message to map buffers in SWd */ +- ret = mcp_multimap(session->mcp_session.id, maps); +- if (ret) +- MCDRV_ERROR("multimap failed: %d", ret); +- } else { +- /* Map each buffer */ +- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, +- map++) { +- if (!buf->va) +- continue; +- +- /* Send MCP message to map buffer in SWd */ +- ret = mcp_map(session->mcp_session.id, map); +- if (ret) { +- MCDRV_ERROR("maps[%d] va=%llx map failed: %d", +- i, buf->va, ret); +- break; +- } +- } +- } +- +-end: +- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) { +- struct tbase_wsm *wsm = wsm_find(session, buf->va); +- +- if (!buf->va) +- continue; +- +- if (ret) { +- if (!wsm) +- break; +- +- /* Destroy mapping */ +- wsm_free(wsm); +- } else { +- /* Store mapping */ +- buf->sva = map->secure_va; +- wsm->sva = buf->sva; +- MCDRV_DBG("maps[%d] va=%llx map'd len=%u sva=%llx", +- i, buf->va, buf->len, buf->sva); +- } +- } +- +-unlock: +- /* Unlock the session */ +- mutex_unlock(&session->wsms_lock); +- return ret; +-} +- +-/* +- * Stop sharing buffers and delete corrsponding WSM objects. +- */ +-int session_wsms_remove(struct tbase_session *session, +- const struct mc_ioctl_buffer *bufs) +-{ +- const struct mc_ioctl_buffer *buf; +- struct mcp_buffer_map maps[MC_MAP_MAX]; +- struct mcp_buffer_map *map; +- int i, ret = 0; +- uint32_t n_null_buf = 0; +- +- if (!session) { +- MCDRV_ERROR("session pointer is null"); +- return -EINVAL; +- } +- +- /* Lock the session */ +- mutex_lock(&session->wsms_lock); +- +- /* Find, check and map buffer */ +- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; i++, buf++, map++) { +- struct tbase_wsm *wsm; +- +- if (!buf->va) { +- n_null_buf++; +- map->secure_va = 0; +- continue; +- } +- +- wsm = wsm_find(session, buf->va); +- if (!wsm) { +- ret = -EADDRNOTAVAIL; +- MCDRV_ERROR("maps[%d] va=%llx not found", i, +- buf->va); +- goto out; +- } +- +- /* Check input params consistency */ +- /* TODO: fix the spec, "len" is NOT ignored anymore */ +- if ((wsm->sva != buf->sva) || (wsm->len != buf->len)) { +- MCDRV_ERROR("maps[%d] va=%llx no match: %x != %llx", +- i, buf->va, wsm->sva, buf->sva); +- MCDRV_ERROR("maps[%d] va=%llx no match: %u != %u", +- i, buf->va, wsm->len, buf->len); +- ret = -EINVAL; +- goto out; +- } +- +- tbase_mmu_buffer(wsm->mmu, map); +- map->secure_va = buf->sva; +- MCDRV_DBG("maps[%d] va=%llx: t:%u a:%llx o:%u l:%u s:%llx", i, +- buf->va, map->type, map->phys_addr, map->offset, +- map->length, map->secure_va); +- } +- +- if (n_null_buf >= MC_MAP_MAX) { +- ret = -EINVAL; +- MCDRV_ERROR("va=NULL"); +- goto out; +- } +- +- if (g_ctx.f_multimap) { +- /* Send MCP command to unmap buffers in SWd */ +- ret = mcp_multiunmap(session->mcp_session.id, maps); +- if (ret) +- MCDRV_ERROR("mcp_multiunmap failed: %d", ret); +- } else { +- for (i = 0, buf = bufs, map = maps; i < MC_MAP_MAX; +- i++, buf++, map++) { +- if (!buf->va) +- continue; +- +- /* Send MCP command to unmap buffer in SWd */ +- ret = mcp_unmap(session->mcp_session.id, map); +- if (ret) { +- MCDRV_ERROR("maps[%d] va=%llx unmap failed: %d", +- i, buf->va, ret); +- break; +- } +- } +- } +- +- for (i = 0, buf = bufs; i < MC_MAP_MAX; i++, buf++) { +- struct tbase_wsm *wsm = wsm_find(session, buf->va); +- +- if (!wsm) +- break; +- +- /* Free wsm */ +- wsm_free(wsm); +- MCDRV_DBG("maps[%d] va=%llx unmap'd len=%u sva=%llx", i, +- buf->va, buf->len, buf->sva); +- } +- +-out: +- mutex_unlock(&session->wsms_lock); +- return ret; +-} +- +-/* +- * Sleep until next notification from SWd. +- */ +-int session_waitnotif(struct tbase_session *session, int32_t timeout) +-{ +- return mcp_session_waitnotif(&session->mcp_session, timeout); +-} +- +-int session_info(struct tbase_session *session, struct kasnprintf_buf *buf) +-{ +- struct tbase_wsm *wsm; +- int32_t exit_code = mcp_session_exitcode(&session->mcp_session); +- int ret; +- +- ret = kasnprintf(buf, "\tsession %p: %x rc %d\n", session, +- session->mcp_session.id, exit_code); +- if (ret < 0) +- return ret; +- +- /* WMSs */ +- mutex_lock(&session->wsms_lock); +- if (list_empty(&session->wsms)) +- goto done; +- +- list_for_each_entry(wsm, &session->wsms, list) { +- ret = wsm_info(wsm, buf); +- if (ret < 0) +- goto done; +- } +- +-done: +- mutex_unlock(&session->wsms_lock); +- if (ret < 0) +- return ret; +- +- return 0; +-} +diff --git a/drivers/gud/MobiCoreDriver/session.h b/drivers/gud/MobiCoreDriver/session.h +deleted file mode 100644 +index aec0c09ae9c9a..0000000000000 +--- a/drivers/gud/MobiCoreDriver/session.h ++++ /dev/null +@@ -1,63 +0,0 @@ +-/* +- * Copyright (c) 2013-2015 TRUSTONIC LIMITED +- * 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 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _SESSION_H_ +-#define _SESSION_H_ +- +-#include +- +-#include "mcp.h" +- +-struct tbase_object; +-struct tbase_mmu; +-struct mc_ioctl_buffer; +- +-struct tbase_session { +- /* Session list lock */ +- struct mutex close_lock; +- /* MCP session descriptor (MUST BE FIRST) */ +- struct mcp_session mcp_session; +- /* Owner */ +- struct tbase_client *client; +- /* Number of references kept to this object */ +- struct kref kref; +- /* The list entry to attach to session list of owner */ +- struct list_head list; +- /* Session WSMs lock */ +- struct mutex wsms_lock; +- /* List of WSMs for a session */ +- struct list_head wsms; +-}; +- +-struct tbase_session *session_create(struct tbase_client *client, bool is_gp, +- struct mc_identity *identity); +-int session_open(struct tbase_session *session, const struct tbase_object *obj, +- const struct tbase_mmu *obj_mmu, uintptr_t tci, size_t len); +-int session_close(struct tbase_session *session); +-static inline void session_get(struct tbase_session *session) +-{ +- kref_get(&session->kref); +-} +- +-int session_put(struct tbase_session *session); +-int session_wsms_add(struct tbase_session *session, +- struct mc_ioctl_buffer *bufs); +-int session_wsms_remove(struct tbase_session *session, +- const struct mc_ioctl_buffer *bufs); +-int32_t session_exitcode(struct tbase_session *session); +-int session_notify_swd(struct tbase_session *session); +-int session_waitnotif(struct tbase_session *session, int32_t timeout); +-int session_info(struct tbase_session *session, struct kasnprintf_buf *buf); +- +-#endif /* _SESSION_H_ */ +diff --git a/drivers/gud/setupDrivers.sh b/drivers/gud/setupDrivers.sh +deleted file mode 100644 +index 994e83e8d9517..0000000000000 +--- a/drivers/gud/setupDrivers.sh ++++ /dev/null +@@ -1,19 +0,0 @@ +-#!/bin/bash +-export COMP_PATH_ROOT=$(dirname $(readlink -f $BASH_SOURCE)) #set this to the absolute path of the folder containing this file +- +-# This part has to be set by the customer +-# To be set, absolute path of kernel folder +-export LINUX_PATH= +-# To be set, absolute path! CROSS_COMPILE variable needed by kernel eg /home/user/arm-2009q3/bin/arm-none-linux-gnueabi- +-export CROSS_COMPILE= +-# To be set, build mode debug or release +-export MODE=debug +-# To be set, the absolute path to the Linux Android NDK +-export NDK_PATH= +- +-# Global variables needed by build scripts +-export COMP_PATH_Logwrapper=$COMP_PATH_ROOT/Logwrapper/Out +-export COMP_PATH_MobiCore=$COMP_PATH_ROOT/MobiCore/Out +-export COMP_PATH_MobiCoreDriverMod=$COMP_PATH_ROOT/mobicore_driver/Out +-export COMP_PATH_MobiCoreDriverLib=$COMP_PATH_ROOT/daemon/Out +-export COMP_PATH_AndroidNdkLinux=$NDK_PATH diff --git a/Patches/Linux_CVEs/CVE-2017-9692/0.patch b/Patches/Linux_CVEs/CVE-2017-9692/0.patch new file mode 100644 index 00000000..c00c3baa --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9692/0.patch @@ -0,0 +1,31 @@ +From 7a86f369594a0b6567820b77d441e778e6adb8a7 Mon Sep 17 00:00:00 2001 +From: Rajkumar Subbiah +Date: Mon, 15 May 2017 15:17:14 -0400 +Subject: [PATCH] msm: mdss: Fix potential dereferencing of null pointer + +During atomic commit on a writeback panel, there is a possibility +of deferencing a NULL pointer if the configuration changes before +the commit. This change adds a NULL pointer check to avoid it. + +Bug: 36731152 +Change-Id: I56d0efad40992b6f87c81e5eab93cf0f24f6f524 +Signed-off-by: Rajkumar Subbiah +--- + drivers/video/msm/mdss/mdss_fb.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c +index 86f380e8a845b..8e02cbf782e0f 100644 +--- a/drivers/video/msm/mdss/mdss_fb.c ++++ b/drivers/video/msm/mdss/mdss_fb.c +@@ -3302,6 +3302,10 @@ int mdss_fb_atomic_commit(struct fb_info *info, + MSMFB_ATOMIC_COMMIT, true, false); + if (mfd->panel.type == WRITEBACK_PANEL) { + output_layer = commit_v1->output_layer; ++ if (!output_layer) { ++ pr_err("Output layer is null\n"); ++ goto end; ++ } + wb_change = !mdss_fb_is_wb_config_same(mfd, + commit_v1->output_layer); + if (wb_change) { diff --git a/Patches/Linux_CVEs/CVE-2017-9693/0.patch b/Patches/Linux_CVEs/CVE-2017-9693/0.patch new file mode 100644 index 00000000..c63ea19e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9693/0.patch @@ -0,0 +1,44 @@ +From 41c47c76d3672de1a091b53878e1abad583b413d Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Thu, 25 May 2017 15:16:36 -0700 +Subject: [PATCH] qcacld-2.0: Trim extn capability to max supported in change + station + +extn capabilities can be controlled by user, which can +be sent greater than the max supported value. This results +in stack overflow in change station command. + +Add check to validate extn capability param given by user +and if it exceeds max supported value, set it to max supported +value. + +CRs-Fixed: 2044820 +Change-Id: I531799dd06c41069e85ad969de6182363dbf9f05 +Bug: 36817798 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 3580d2b73494b..0fd39f568de4d 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -14887,9 +14887,16 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy, + StaParams.supported_oper_classes_len = + params->supported_oper_classes_len; + ++ if (params->ext_capab_len > sizeof(StaParams.extn_capability)) { ++ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, ++ "received extn capabilities: %d, reset to max supported", ++ params->ext_capab_len); ++ params->ext_capab_len = sizeof(StaParams.extn_capability); ++ } ++ + if (0 != params->ext_capab_len) + vos_mem_copy(StaParams.extn_capability, params->ext_capab, +- sizeof(StaParams.extn_capability)); ++ params->ext_capab_len); + + if (NULL != params->ht_capa) { + StaParams.htcap_present = 1; diff --git a/Patches/Linux_CVEs/CVE-2017-9694/0.patch b/Patches/Linux_CVEs/CVE-2017-9694/0.patch new file mode 100644 index 00000000..3ce016ee --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9694/0.patch @@ -0,0 +1,35 @@ +From 7f60f02336d5506aeb81c5fec9e213f729fb83e6 Mon Sep 17 00:00:00 2001 +From: Srinivas Girigowda +Date: Thu, 25 May 2017 15:12:16 -0700 +Subject: [PATCH] qcacld-2.0: Add lost AP sample size entry to nla policy + +Incorrect validation of +QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE +results in assigning an unchecked user-controller value. +This can lead to buffer overflow. + +validate + QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE. + +CRs-Fixed: 2045470 +Change-Id: I7c33b6d78054672e9effbe9100c29e5604c250c6 +Bug: 36818198 +Signed-off-by: Srinivas Girigowda +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index d5e63ef797c91..3580d2b73494b 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -852,6 +852,9 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = { .type = NLA_S32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE] = { ++ .type = NLA_U32 ++ }, + }; + + static const struct nla_policy diff --git a/Patches/Linux_CVEs/CVE-2017-9697/0.patch b/Patches/Linux_CVEs/CVE-2017-9697/0.patch new file mode 100644 index 00000000..ec34d811 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9697/0.patch @@ -0,0 +1,55 @@ +From 4b788ca419ec37e4cdb421fef9edc208a491ce30 Mon Sep 17 00:00:00 2001 +From: Mohit Aggarwal +Date: Thu, 25 May 2017 20:21:12 +0530 +Subject: [PATCH] diag: Synchronize command registration table access + +Currently, command registration table is being read +in debugfs without any protection which may lead to +access of stale entries. The patch takes care of the +issue by adding proper protection. + +CRs-Fixed: 2032672 +Bug: 63868628 +Change-Id: I6ae058c16873f9ed52ae6516a1a70fd6d2d0da80 +Signed-off-by: Mohit Aggarwal +--- + drivers/char/diag/diag_debugfs.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c +index f5e4eba1e96bc..b66c8cb8257c2 100644 +--- a/drivers/char/diag/diag_debugfs.c ++++ b/drivers/char/diag/diag_debugfs.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2017, The 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 +@@ -268,8 +268,10 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + struct list_head *temp; + struct diag_cmd_reg_t *item = NULL; + ++ mutex_lock(&driver->cmd_reg_mutex); + if (diag_dbgfs_table_index == driver->cmd_reg_count) { + diag_dbgfs_table_index = 0; ++ mutex_unlock(&driver->cmd_reg_mutex); + return 0; + } + +@@ -278,6 +280,7 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL); + if (ZERO_OR_NULL_PTR(buf)) { + pr_err("diag: %s, Error allocating memory\n", __func__); ++ mutex_unlock(&driver->cmd_reg_mutex); + return -ENOMEM; + } + buf_size = ksize(buf); +@@ -322,6 +325,7 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + break; + } + diag_dbgfs_table_index = i; ++ mutex_unlock(&driver->cmd_reg_mutex); + + *ppos = 0; + ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer); diff --git a/Patches/Linux_CVEs/CVE-2017-9706/0.patch b/Patches/Linux_CVEs/CVE-2017-9706/0.patch new file mode 100644 index 00000000..9735e70c --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9706/0.patch @@ -0,0 +1,35 @@ +From 7489a0a8f68d0f018d0f9df5df157bb20f83b05e Mon Sep 17 00:00:00 2001 +From: Bharath Gopal +Date: Fri, 4 Aug 2017 17:19:24 -0700 +Subject: [PATCH] msm: mdss: Buffer overflow while processing gamut table data + +Modified the size of the gamut table data-structure in order to +avoid a buffer overflow while copying data from user-space. + +Bug: 34170483 +Change-Id: I8c5fa1caff450a2d25d7859bd159ab4a60045e54 +Signed-off-by: Bharath Gopal +--- + drivers/video/msm/mdss/mdss_mdp_pp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c +index bd6d2fbd9c26e..a666f4c61d1ab 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_pp.c ++++ b/drivers/video/msm/mdss/mdss_mdp_pp.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012-2017, The 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 +@@ -389,7 +389,7 @@ struct mdss_pp_res_type { + struct mdp_hist_lut_data enhist_disp_cfg[MDSS_BLOCK_DISP_NUM]; + struct mdp_dither_cfg_data dither_disp_cfg[MDSS_BLOCK_DISP_NUM]; + struct mdp_gamut_cfg_data gamut_disp_cfg[MDSS_BLOCK_DISP_NUM]; +- uint16_t gamut_tbl[MDSS_BLOCK_DISP_NUM][GAMUT_TOTAL_TABLE_SIZE]; ++ uint16_t gamut_tbl[MDSS_BLOCK_DISP_NUM][GAMUT_TOTAL_TABLE_SIZE * 3]; + u32 hist_data[MDSS_BLOCK_DISP_NUM][HIST_V_SIZE]; + struct pp_sts_type pp_disp_sts[MDSS_MAX_MIXER_DISP_NUM]; + /* physical info */ diff --git a/Patches/Linux_CVEs/CVE-2017-9714/0.patch b/Patches/Linux_CVEs/CVE-2017-9714/0.patch new file mode 100644 index 00000000..466dbd15 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9714/0.patch @@ -0,0 +1,62 @@ +From aae237dfbaf8edcf310eeb84b887b20e7e9c0ff3 Mon Sep 17 00:00:00 2001 +From: Kapil Gupta +Date: Tue, 16 May 2017 12:39:54 +0530 +Subject: qcacld-2.0: Drop assoc request if RSNIE/WPAIE parsing fail + +Add changes to drop assoc request and return error if RSNIE or +WPAIE parsing fail during parsing of assoc request. + +CRs-Fixed: 2046578 +Change-Id: I88d779399c2eba5d33c30144bf9600a1f3a00b77 +--- + CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +index 7aa5464..23d2cf3 100644 +--- a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c ++++ b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +@@ -752,10 +752,18 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, + if(pAssocReq->rsn.length) + { + // Unpack the RSN IE +- dot11fUnpackIeRSN(pMac, ++ if (dot11fUnpackIeRSN(pMac, + &pAssocReq->rsn.info[0], + pAssocReq->rsn.length, +- &Dot11fIERSN); ++ &Dot11fIERSN) != DOT11F_PARSE_SUCCESS) ++ { ++ limLog(pMac, LOG1, ++ FL("Invalid RSNIE received")); ++ limSendAssocRspMgmtFrame(pMac, ++ eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS, ++ 1, pHdr->sa, subType, 0,psessionEntry); ++ goto error; ++ } + + /* Check RSN version is supported or not */ + if(SIR_MAC_OUI_VERSION_1 == Dot11fIERSN.version) +@@ -821,10 +829,17 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, + // Unpack the WPA IE + if(pAssocReq->wpa.length) + { +- dot11fUnpackIeWPA(pMac, ++ if (dot11fUnpackIeWPA(pMac, + &pAssocReq->wpa.info[4], //OUI is not taken care + pAssocReq->wpa.length, +- &Dot11fIEWPA); ++ &Dot11fIEWPA) != DOT11F_PARSE_SUCCESS) ++ { ++ limLog(pMac, LOGE, FL("Invalid WPA IE")); ++ limSendAssocRspMgmtFrame(pMac, ++ eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS, ++ 1, pHdr->sa, subType, 0,psessionEntry); ++ goto error; ++ } + /* check the groupwise and pairwise cipher suites */ + if(eSIR_SUCCESS != (status = limCheckRxWPAIeMatch(pMac, Dot11fIEWPA, psessionEntry, pAssocReq->HTCaps.present))) + { +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9714/1.patch b/Patches/Linux_CVEs/CVE-2017-9714/1.patch new file mode 100644 index 00000000..6ff454e6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9714/1.patch @@ -0,0 +1,62 @@ +From 822958b55703d8a3d7f7e2d9b1cd1736c9878a3b Mon Sep 17 00:00:00 2001 +From: Kapil Gupta +Date: Tue, 16 May 2017 12:39:54 +0530 +Subject: [PATCH] qcacld-2.0: Drop assoc request if RSNIE/WPAIE parsing fail + +Add changes to drop assoc request and return error if RSNIE or +WPAIE parsing fail during parsing of assoc request. + +Bug: 63868020 + +CRs-Fixed: 2046578 +Change-Id: I88d779399c2eba5d33c30144bf9600a1f3a00b77 +Signed-off-by: Ecco Park +--- + .../CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c | 23 ++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +index 4e7fbe2341811..5e2bb2dd04f2c 100644 +--- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c ++++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +@@ -711,10 +711,18 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, + if(pAssocReq->rsn.length) + { + // Unpack the RSN IE +- dot11fUnpackIeRSN(pMac, ++ if (dot11fUnpackIeRSN(pMac, + &pAssocReq->rsn.info[0], + pAssocReq->rsn.length, +- &Dot11fIERSN); ++ &Dot11fIERSN) != DOT11F_PARSE_SUCCESS) ++ { ++ limLog(pMac, LOG1, ++ FL("Invalid RSNIE received")); ++ limSendAssocRspMgmtFrame(pMac, ++ eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS, ++ 1, pHdr->sa, subType, 0,psessionEntry); ++ goto error; ++ } + + /* Check RSN version is supported or not */ + if(SIR_MAC_OUI_VERSION_1 == Dot11fIERSN.version) +@@ -780,10 +788,17 @@ limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, + // Unpack the WPA IE + if(pAssocReq->wpa.length) + { +- dot11fUnpackIeWPA(pMac, ++ if (dot11fUnpackIeWPA(pMac, + &pAssocReq->wpa.info[4], //OUI is not taken care + pAssocReq->wpa.length, +- &Dot11fIEWPA); ++ &Dot11fIEWPA) != DOT11F_PARSE_SUCCESS) ++ { ++ limLog(pMac, LOGE, FL("Invalid WPA IE")); ++ limSendAssocRspMgmtFrame(pMac, ++ eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS, ++ 1, pHdr->sa, subType, 0,psessionEntry); ++ goto error; ++ } + /* check the groupwise and pairwise cipher suites */ + if(eSIR_SUCCESS != (status = limCheckRxWPAIeMatch(pMac, Dot11fIEWPA, psessionEntry, pAssocReq->HTCaps.present))) + { diff --git a/Patches/Linux_CVEs/CVE-2017-9715/0.patch b/Patches/Linux_CVEs/CVE-2017-9715/0.patch new file mode 100644 index 00000000..03c5244b --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9715/0.patch @@ -0,0 +1,50 @@ +From 58350a7bcb827c0ac81f0750a62d5c5a8ed3a469 Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Tue, 6 Jun 2017 08:56:33 -0700 +Subject: qcacld-2.0: Avoid extscan bucket spec overread + +Currently in hdd_extscan_start_fill_bucket_channel_spec() the +QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC attribute is parsed without +specifying a policy. This means that no policy is enforced. +Subsequently the values of the nested attributes are retrieved, but +again without any length limits enforced. This could result in a +buffer overread. +To prevent this issue: +* Parse using the existing policy wlan_hdd_extscan_config_policy +* Update the policy to add missing attributes + +Change-Id: I3b20cb28d1beccd2e804b022b531413ad1edb533 +CRs-Fixed: 2057034 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 1f6be81..078b4fd 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -850,6 +850,9 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_SSID_LEN + 1 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = { .type = NLA_U32 }, +@@ -3533,8 +3536,9 @@ static int hdd_extscan_start_fill_bucket_channel_spec( + } + + if (nla_parse(bucket, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, +- nla_data(buckets), nla_len(buckets), NULL)) { ++ QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, ++ nla_data(buckets), nla_len(buckets), ++ wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9715/1.patch b/Patches/Linux_CVEs/CVE-2017-9715/1.patch new file mode 100644 index 00000000..fb016fef --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9715/1.patch @@ -0,0 +1,49 @@ +From ed6814c11abf9f96d4060b2825c50842ef83bdba Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Tue, 6 Jun 2017 08:56:33 -0700 +Subject: [PATCH] qcacld-2.0: Avoid extscan bucket spec overread + +Currently in hdd_extscan_start_fill_bucket_channel_spec() the +QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC attribute is parsed without +specifying a policy. This means that no policy is enforced. +Subsequently the values of the nested attributes are retrieved, but +again without any length limits enforced. This could result in a +buffer overread. +To prevent this issue: +* Parse using the existing policy wlan_hdd_extscan_config_policy +* Update the policy to add missing attributes + +Bug: 36730104 +Change-Id: I3b20cb28d1beccd2e804b022b531413ad1edb533 +CRs-Fixed: 2057034 +Signed-off-by: Ecco Park +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index 5ca269bab9cf6..da139cf225ce2 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -845,6 +845,9 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_SSID_LEN + 1 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = { .type = NLA_U32 }, +@@ -3448,8 +3451,9 @@ static int hdd_extscan_start_fill_bucket_channel_spec( + } + + if (nla_parse(bucket, +- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, +- nla_data(buckets), nla_len(buckets), NULL)) { ++ QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX, ++ nla_data(buckets), nla_len(buckets), ++ wlan_hdd_extscan_config_policy)) { + hddLog(LOGE, FL("nla_parse failed")); + return -EINVAL; + } diff --git a/Patches/Linux_CVEs/CVE-2017-9717/0.patch b/Patches/Linux_CVEs/CVE-2017-9717/0.patch new file mode 100644 index 00000000..606c231e --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9717/0.patch @@ -0,0 +1,31 @@ +From bf7486fb6d82fb9ad02e303b6fdf4061cfc0375d Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Thu, 25 May 2017 15:53:53 +0530 +Subject: qcacld-2.0: Add get valid channels entry to NLA policy + +improper validation of +QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS. + +validate QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS. + +CRs-Fixed: 2051450 +Change-Id: I16e5808492b5b35dc8b646af45d6ac6d65561804 +--- + CORE/HDD/src/wlan_hdd_cfg80211.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c +index 837e407..9d18fd3 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -822,6 +822,7 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + { + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = { .type = NLA_U8 }, +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9717/1.patch b/Patches/Linux_CVEs/CVE-2017-9717/1.patch new file mode 100644 index 00000000..fcbe2bd6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9717/1.patch @@ -0,0 +1,31 @@ +From 68898d364c0f67100186663af55e0b9fd38de7a9 Mon Sep 17 00:00:00 2001 +From: SaidiReddy Yenuga +Date: Thu, 25 May 2017 15:53:53 +0530 +Subject: [PATCH] qcacld-2.0: Add get valid channels entry to NLA policy + +improper validation of +QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS. + +validate QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS. + +Bug: 36817053 + +CRs-Fixed: 2051450 +Change-Id: I16e5808492b5b35dc8b646af45d6ac6d65561804 +Signed-off-by: Ecco Park +--- + drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +index c7d271f91ceb9..b788566363d87 100644 +--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c ++++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c +@@ -815,6 +815,7 @@ wlan_hdd_extscan_config_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_ + { + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = { .type = NLA_U32 }, ++ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = { .type = NLA_U8 }, diff --git a/Patches/Linux_CVEs/CVE-2017-9720/0.patch b/Patches/Linux_CVEs/CVE-2017-9720/0.patch new file mode 100644 index 00000000..ef6036d0 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9720/0.patch @@ -0,0 +1,30 @@ +From c74dbab508c7c07d8e2cf8230cc78bff4b710272 Mon Sep 17 00:00:00 2001 +From: Fei Zhang +Date: Wed, 17 May 2017 15:33:02 +0800 +Subject: msm:camera: correct stats query out of boundary + +fix one potential out of boundary query of stats info. + +Bug: 36264696 +Change-Id: I13e4bf8802fcce529f9268c272e4727619d5ad8f +Signed-off-by: Fei Zhang +--- + drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +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 a0eed95..82da3e0 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 +@@ -803,7 +803,7 @@ int msm_isp_update_stats_stream(struct vfe_device *vfe_dev, void *arg) + update_info = &update_cmd->update_info[i]; + /*check array reference bounds*/ + if (STATS_IDX(update_info->stream_handle) +- > vfe_dev->hw_info->stats_hw_info->num_stats_type) { ++ >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { + pr_err("%s: stats idx %d out of bound!", __func__, + STATS_IDX(update_info->stream_handle)); + return -EINVAL; +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9724/0.patch b/Patches/Linux_CVEs/CVE-2017-9724/0.patch new file mode 100644 index 00000000..e613bef7 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9724/0.patch @@ -0,0 +1,69 @@ +From 5328a92fa26eabe2ba259b1d813f9de488efc9ec Mon Sep 17 00:00:00 2001 +From: "Se Wang (Patrick) Oh" +Date: Mon, 29 Jun 2015 11:43:39 -0700 +Subject: ion: Fix unprotected userspace access + +After enabling KASan, unprotected userspace access causes +a PTE translation fault as it can covers only kernel memory +region. Following is the crash error for the reference. + +Unable to handle kernel paging request at virtual address dfffff901ff64b84 +pgd = ffffffc083266000 +[dfffff901ff64b84] *pgd=0000000000000000, *pud=0000000000000000 +Internal error: Oops: 96000004 [#1] PREEMPT SMP +Modules linked in: +CPU: 1 PID: 8527 Comm: iveaudiolatency Tainted: G W 3.18.0-g5a4a5d5-07255-g8e80921-dirty #21 +Hardware name: Qualcomm Technologies, Inc. MSM 8996 v2 + PMI8994 MTP (DT) +task: ffffffc02bfeb600 ti: ffffffc083378000 task.ti: ffffffc083378000 +PC is at compat_msm_ion_ioctl+0x23c/0x614 +LR is at compat_msm_ion_ioctl+0x1d8/0x614 +pc : [] lr : [] pstate: 80000145 +sp : ffffffc08337faf0 +x29: ffffffc08337faf0 x28: 0000000000000000 +x27: ffffffc083378000 x26: 00000000ffb25c20 +x25: 00000000e2fa6000 x24: 0000000000000000 +x23: 00000000ffb25c18 x22: 0000000000000000 +x21: ffffffc08fcaa640 x20: 00000000c0144d00 +x19: 00000000ffb25c74 x18: 0000000000000000 +x17: 0000000000000000 x16: ffffffc000385a88 +x15: 0000000000000000 x14: 00000000f73517c9 +x13: 00000000ffb25c30 x12: 0000000000000001 +x11: 00000000ffffffff x10: ffffff881066ff3a +x9 : 1ffffff81066ff3a x8 : dfffff9000000000 +x7 : 0000000000000036 x6 : ffffffc08337f9d4 +x5 : 0000000000000003 x4 : 00000000ffb25c30 +x3 : ffffffc0012bd334 x2 : 0000000000000001 +x1 : 000000001ff64b84 x0 : dfffff9000000000 + +Process iveaudiolatency (pid: 8527, stack limit = 0xffffffc083378058) +Call trace: +[] compat_msm_ion_ioctl+0x23c/0x614 +[] ion_ioctl+0x4dc/0x680 +[] compat_ion_ioctl+0xb98/0xbc0 +[] compat_SyS_ioctl+0x288/0x2048 +Code: 910022fa d2dff200 d343ff41 f2fbffe0 (38e06820) +---[ end trace 490ef1c3bde7b96c ]--- +coresight-tmc 3028000.tmc: TMC aborted + +Change-Id: I7595bbf5f311182d40f7158654df56dc8bcf672a +Signed-off-by: Se Wang (Patrick) Oh +--- + drivers/staging/android/ion/msm/compat_msm_ion.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/android/ion/msm/compat_msm_ion.c b/drivers/staging/android/ion/msm/compat_msm_ion.c +index c34b3a7..ddb9fc7 100644 +--- a/drivers/staging/android/ion/msm/compat_msm_ion.c ++++ b/drivers/staging/android/ion/msm/compat_msm_ion.c +@@ -58,7 +58,7 @@ static int compat_get_ion_flush_data( + err |= put_user(i, &data->fd); + err |= get_user(u, &data32->vaddr); + /* upper bits won't get set, zero them */ +- data->vaddr = NULL; ++ err |= put_user(NULL, &data->vaddr); + err |= put_user(u, (compat_uptr_t *)&data->vaddr); + err |= get_user(l, &data32->offset); + err |= put_user(l, &data->offset); +-- +cgit v1.1 + diff --git a/Patches/Linux_CVEs/CVE-2017-9725/0.patch b/Patches/Linux_CVEs/CVE-2017-9725/0.patch new file mode 100644 index 00000000..d34ee8d6 --- /dev/null +++ b/Patches/Linux_CVEs/CVE-2017-9725/0.patch @@ -0,0 +1,79 @@ +From 5479a3c164c8762b5bf91c5fae452882366adb6a Mon Sep 17 00:00:00 2001 +From: Maggie White +Date: Wed, 5 Jul 2017 16:47:15 -0700 +Subject: mm: Fix incorrect type conversion for size during dma allocation + +This was found during userspace fuzzing test when a large size +allocation is made from ion + +[] show_stack+0x10/0x1c +[] dump_stack+0x74/0xc8 +[] kasan_report_error+0x2b0/0x408 +[] kasan_report+0x34/0x40 +[] __asan_storeN+0x15c/0x168 +[] memset+0x20/0x44 +[] __dma_alloc_coherent+0x114/0x18c +[] __dma_alloc_noncoherent+0xbc/0x19c +[] ion_cma_allocate+0x178/0x2f0 +[] ion_secure_cma_allocate+0xdc/0x190 +[] ion_alloc+0x264/0xb88 +[] ion_ioctl+0x1f4/0x480 +[] do_vfs_ioctl+0x67c/0x764 +[] SyS_ioctl+0x58/0x8c + +Bug: 38195738 +Signed-off-by: Rohit Vaswani +Signed-off-by: Maggie White +Change-Id: I6b1a0a3eaec10500cd4e73290efad4023bc83da5 +--- + drivers/base/dma-contiguous.c | 4 ++-- + include/linux/dma-contiguous.h | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c +index f6e779e..9313bfc1 100644 +--- a/drivers/base/dma-contiguous.c ++++ b/drivers/base/dma-contiguous.c +@@ -589,7 +589,7 @@ static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count) + * global one. Requires architecture specific get_dev_cma_area() helper + * function. + */ +-unsigned long dma_alloc_from_contiguous(struct device *dev, int count, ++unsigned long dma_alloc_from_contiguous(struct device *dev, size_t count, + unsigned int align) + { + unsigned long mask, pfn = 0, pageno, start = 0; +@@ -604,7 +604,7 @@ unsigned long dma_alloc_from_contiguous(struct device *dev, int count, + if (align > CONFIG_CMA_ALIGNMENT) + align = CONFIG_CMA_ALIGNMENT; + +- pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma, ++ pr_debug("%s(cma %p, count %zu, align %d)\n", __func__, (void *)cma, + count, align); + + if (!count) +diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h +index 9e6fee9..d8d124e 100644 +--- a/include/linux/dma-contiguous.h ++++ b/include/linux/dma-contiguous.h +@@ -117,7 +117,7 @@ static inline int dma_declare_contiguous_reserved(struct device *dev, + return ret; + } + +-unsigned long dma_alloc_from_contiguous(struct device *dev, int count, ++unsigned long dma_alloc_from_contiguous(struct device *dev, size_t count, + unsigned int order); + bool dma_release_from_contiguous(struct device *dev, unsigned long pfn, + int count); +@@ -136,7 +136,7 @@ int dma_declare_contiguous(struct device *dev, phys_addr_t size, + } + + static inline +-unsigned long dma_alloc_from_contiguous(struct device *dev, int count, ++unsigned long dma_alloc_from_contiguous(struct device *dev, size_t count, + unsigned int order) + { + return 0; +-- +cgit v1.1 + diff --git a/Scripts/LineageOS-14.1/00init.sh b/Scripts/LineageOS-14.1/00init.sh new file mode 100644 index 00000000..b04b48dc --- /dev/null +++ b/Scripts/LineageOS-14.1/00init.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +#Sets settings used by all other scripts + +base="/mnt/Drive-1/Development/Other/Android_ROMs/Build/LineageOS-14.1/"; +export base; + +patches="/mnt/Drive-1/Development/Other/Android_ROMs/Patches/LineageOS-14.1/"; +export patches; + +cvePatches="/mnt/Drive-1/Development/Other/Android_ROMs/Patches/Linux_CVEs/"; +export cvePatches; + +scripts="/mnt/Drive-1/Development/Other/Android_ROMs/Scripts/LineageOS-14.1/"; +export scripts; + +cveScripts=$scripts"CVE_Patchers/"; +export cveScripts; + +ANDROID_HOME="/home/$USER/Android/Sdk"; +export ANDROID_HOME; diff --git a/Scripts/Generic_Deblob.sh b/Scripts/LineageOS-14.1/Deblob.sh similarity index 99% rename from Scripts/Generic_Deblob.sh rename to Scripts/LineageOS-14.1/Deblob.sh index 49eabe8f..f02f51f0 100755 --- a/Scripts/Generic_Deblob.sh +++ b/Scripts/LineageOS-14.1/Deblob.sh @@ -10,9 +10,6 @@ # #Functioning as Expected: bacon, clark, mako, marlin, sailfish, thor -base="/mnt/Drive-1/Development/Other/Android_ROMs/Build/LineageOS-14.1/"; -export base; - echo "Deblobbing..." # diff --git a/Scripts/LAOS-14.1_Optimize.sh b/Scripts/LineageOS-14.1/Optimize.sh similarity index 96% rename from Scripts/LAOS-14.1_Optimize.sh rename to Scripts/LineageOS-14.1/Optimize.sh index 579dea8e..417f27c4 100644 --- a/Scripts/LAOS-14.1_Optimize.sh +++ b/Scripts/LineageOS-14.1/Optimize.sh @@ -3,8 +3,6 @@ #Attempts to increase performance and battery life -base="/mnt/Drive-1/Development/Other/Android_ROMs/Build/LineageOS-14.1/" - echo "Optimizing..." cd $base"frameworks/base" diff --git a/Scripts/LAOS-14.1_Patches.sh b/Scripts/LineageOS-14.1/Patch.sh similarity index 95% rename from Scripts/LAOS-14.1_Patches.sh rename to Scripts/LineageOS-14.1/Patch.sh index 62589392..e5a2108e 100755 --- a/Scripts/LAOS-14.1_Patches.sh +++ b/Scripts/LineageOS-14.1/Patch.sh @@ -4,8 +4,11 @@ #Delete Everything #repo forall -c 'git add -A && git reset --hard' && rm -rf packages/apps/{FDroid,GmsCore,Silence} out +#Initialize some variables +#sh ../../Scripts/LineageOS-14.1/00init.sh + #Prepare a build -#repo sync -j20 --force-sync && sh ../../Scripts/LAOS-14.1_Patches.sh && source ../../Scripts/LAOS-14.1_Optimize.sh && source ../../Scripts/LAOS-14.1_Rebrand.sh && source ../../Scripts/LAOS-14.1_Theme.sh && source ../../Scripts/Generic_Deblob.sh && source build/envsetup.sh && export ANDROID_HOME="/home/$USER/Android/Sdk" && export ANDROID_JACK_VM_ARGS="-Xmx6144m -Xms512m -Dfile.encoding=UTF-8 -XX:+TieredCompilation" && export JACK_SERVER_VM_ARGUMENTS="${ANDROID_JACK_VM_ARGS}" && GRADLE_OPTS=-Xmx2048m && export KBUILD_BUILD_USER=emy && export KBUILD_BUILD_HOST=dosbm +#repo sync -j20 --force-sync && && sh $scripts/Patch.sh && source $scripts/Optimize.sh && source $scripts/Rebrand.sh && source $scripts/Theme.sh && source $scripts/Generic_Deblob.sh && source build/envsetup.sh && export ANDROID_HOME="/home/$USER/Android/Sdk" && export ANDROID_JACK_VM_ARGS="-Xmx6144m -Xms512m -Dfile.encoding=UTF-8 -XX:+TieredCompilation" && export JACK_SERVER_VM_ARGUMENTS="${ANDROID_JACK_VM_ARGS}" && GRADLE_OPTS=-Xmx2048m && export KBUILD_BUILD_USER=emy && export KBUILD_BUILD_HOST=dosbm #Build! #brunch lineage_mako-user && export OTA_PACKAGE_SIGNING_KEY=../../Signing_Keys/releasekey && export SIGNING_KEY_DIR=../../Signing_Keys && brunch lineage_clark-user && brunch lineage_bacon-user && brunch lineage_thor-userdebug && brunch lineage_angler-user && brunch lineage_bullhead-user && brunch lineage_ether-user && brunch lineage_flounder-user && brunch lineage_flo-user && brunch lineage_FP2-user && brunch lineage_hammerhead-user && brunch lineage_marlin-user && brunch lineage_sailfish-user && brunch lineage_n5110-user && brunch lineage_osprey-user && brunch lineage_shamu-user && brunch lineage_Z00T-user @@ -16,11 +19,6 @@ # #START OF PREPRATION # -#Set some variables for use later on -base="/mnt/Drive-1/Development/Other/Android_ROMs/Build/LineageOS-14.1/" -patches="/mnt/Drive-1/Development/Other/Android_ROMs/Patches/LineageOS-14.1/" -ANDROID_HOME="/home/$USER/Android/Sdk" - #Download some (non-executable) out-of-tree files for use later on mkdir /tmp/ar cd /tmp/ar @@ -235,7 +233,7 @@ patch -p1 < $patches"android_kernel_oneplus_msm8974/0001-OverUnderClock-EXTREME. enter "device/lge/mako" disableDexPreOpt #bootloops -#patch -p1 < $patches"android_device_lge_mako/0001-Enable_LTE.patch" #Enable LTE support (Requires LTE hybrid modem to be flashed) XXX: Doesn't seem to work under 7.x +patch -p1 < $patches"android_device_lge_mako/0001-Enable_LTE.patch" #Enable LTE support (Requires LTE hybrid modem to be flashed) XXX: Doesn't seem to work under 7.x enter "kernel/lge/hammerhead" patch -p1 < $patches"android_kernel_lge_hammerhead/0001-OverUnderClock.patch" #2.26Ghz -> 2.95Ghz =+2.76Ghz diff --git a/Scripts/LineageOS-14.1/Patch_CVE.sh b/Scripts/LineageOS-14.1/Patch_CVE.sh new file mode 100644 index 00000000..a4bc802c --- /dev/null +++ b/Scripts/LineageOS-14.1/Patch_CVE.sh @@ -0,0 +1,10 @@ +#!/bin/bash +#Copyright (c) 2015-2017 Spot Communications, Inc. + +#Attempts to patch kernels to be more secure + +echo "Patching CVEs..." + + +cd $base +echo "Patched CVEs!" diff --git a/Scripts/LAOS-14.1_Rebrand.sh b/Scripts/LineageOS-14.1/Rebrand.sh similarity index 94% rename from Scripts/LAOS-14.1_Rebrand.sh rename to Scripts/LineageOS-14.1/Rebrand.sh index 4a952bf4..ce9eb2c1 100644 --- a/Scripts/LAOS-14.1_Rebrand.sh +++ b/Scripts/LineageOS-14.1/Rebrand.sh @@ -3,8 +3,6 @@ #Updates select user facing strings -base="/mnt/Drive-1/Development/Other/Android_ROMs/Build/LineageOS-14.1/" - echo "Rebranding..." cd $base"build" diff --git a/Scripts/LAOS-14.1_Theme.sh b/Scripts/LineageOS-14.1/Theme.sh similarity index 97% rename from Scripts/LAOS-14.1_Theme.sh rename to Scripts/LineageOS-14.1/Theme.sh index b6cd5eb3..39c562b3 100644 --- a/Scripts/LAOS-14.1_Theme.sh +++ b/Scripts/LineageOS-14.1/Theme.sh @@ -3,8 +3,6 @@ #Replaces teal accents with orange/yellow ones -base="/mnt/Drive-1/Development/Other/Android_ROMs/Build/LineageOS-14.1/" - echo "Applying theme..." export themeOverride50="FFCA28" #Amber 400