DivestOS/Patches/Linux_CVEs-New/CVE-2017-0564/3.10/1.patch.base64

152 lines
12 KiB
Plaintext
Raw Normal View History

2017-10-29 14:23:02 -04:00
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>Diff - 51e09571eef7a6a36c238130575fc11b291afff3^! - kernel/msm.git - Git at Google</title><link rel="stylesheet" type="text/css" href="/+static/base.HLL9TqKl0YYybSzmT_wTdw.cache.css"><!-- default customHeadTagPart --></head><body class="Site"><header class="Site-header"><div class="Header"><a class="Header-image" href="/"><img src="//www.gstatic.com/images/branding/lockups/2x/lockup_git_color_108x24dp.png" width="108" height="24" alt="Google Git"></a><div class="Header-menu"> <a class="Header-menuItem" href="https://accounts.google.com/AccountChooser?service=gerritcodereview&amp;continue=https://android.googlesource.com/login/kernel/msm.git/%2B/51e09571eef7a6a36c238130575fc11b291afff3%255E%2521/">Sign in</a> </div></div></header><div class="Site-content"><div class="Container "><div class="Breadcrumbs"><a class="Breadcrumbs-crumb" href="/?format=HTML">android</a> / <a class="Breadcrumbs-crumb" href="/kernel/">kernel</a> / <a class="Breadcrumbs-crumb" href="/kernel/msm.git/">msm.git</a> / <a class="Breadcrumbs-crumb" href="/kernel/msm.git/+/51e09571eef7a6a36c238130575fc11b291afff3%5E%21/">51e09571eef7a6a36c238130575fc11b291afff3^!</a> / <span class="Breadcrumbs-crumb">.</span></div><div class="u-monospace Metadata"><table><tr><th class="Metadata-title">commit</th><td>51e09571eef7a6a36c238130575fc11b291afff3</td><td><span>[<a href="/kernel/msm.git/+log/51e09571eef7a6a36c238130575fc11b291afff3/">log</a>]</span> <span>[<a href="/kernel/msm.git/+archive/51e09571eef7a6a36c238130575fc11b291afff3/.tar.gz">tgz</a>]</span></td></tr><tr><th class="Metadata-title">author</th><td>Nick Desaulniers &lt;ndesaulniers@google.com&gt;</td><td>Fri Feb 10 10:54:56 2017 -0800</td></tr><tr><th class="Metadata-title">committer</th><td>John Dias &lt;joaodias@google.com&gt;</td><td>Wed Feb 15 20:53:36 2017 +0000</td></tr><tr><th class="Metadata-title">tree</th><td><a href="/kernel/msm.git/+/51e09571eef7a6a36c238130575fc11b291afff3/">d8ba7e3a5de3bd46ca42b0fa541e087dc5a20426</a></td></tr><tr><th class="Metadata-title">parent</th><td><a href="/kernel/msm.git/+/51e09571eef7a6a36c238130575fc11b291afff3%5E">3f41af6608b7ed506d3982b57cf34c70ff098f09</a> <span>[<a href="/kernel/msm.git/+/51e09571eef7a6a36c238130575fc11b291afff3%5E%21/">diff</a>]</span></td></tr></table></div><pre class="u-pre u-monospace MetadataMessage">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: <a href="https://android-review.googlesource.com/#/q/Ibc36bc4405788ed0fea7337b541cad3be2b934c0">Ibc36bc4405788ed0fea7337b541cad3be2b934c0</a>
Signed-off-by: Daniel Rosenberg &lt;drosen@google.com&gt;
</pre><pre class="u-pre u-monospace Diff"><a name="F0" class="Diff-fileIndex"></a>diff --git <a href="/kernel/msm.git/+/3f41af6608b7ed506d3982b57cf34c70ff098f09/drivers/staging/android/ion/ion.c">a/drivers/staging/android/ion/ion.c</a> <a href="/kernel/msm.git/+/51e09571eef7a6a36c238130575fc11b291afff3/drivers/staging/android/ion/ion.c">b/drivers/staging/android/ion/ion.c</a>
index ee1c2f3..e99ea9a 100755
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
</pre><pre class="u-pre u-monospace Diff-unified"><span class="Diff-hunk">@@ -116,6 +116,7 @@
</span><span class="Diff-change"> */</span>
<span class="Diff-change"> struct ion_handle {</span>
<span class="Diff-change"> struct kref ref;</span>
<span class="Diff-insert">+ unsigned int user_ref_count;</span>
<span class="Diff-change"> struct ion_client *client;</span>
<span class="Diff-change"> struct ion_buffer *buffer;</span>
<span class="Diff-change"> struct rb_node node;</span>
<span class="Diff-hunk">@@ -429,6 +430,50 @@
</span><span class="Diff-change"> return ret;</span>
<span class="Diff-change"> }</span>
<span class="Diff-change"> </span>
<span class="Diff-insert">+/* Must hold the client lock */</span>
<span class="Diff-insert">+static void user_ion_handle_get(struct ion_handle *handle)</span>
<span class="Diff-insert">+{</span>
<span class="Diff-insert">+ if (handle-&gt;user_ref_count++ == 0) {</span>
<span class="Diff-insert">+ kref_get(&amp;handle-&gt;ref);</span>
<span class="Diff-insert">+ }</span>
<span class="Diff-insert">+}</span>
<span class="Diff-insert">+</span>
<span class="Diff-insert">+/* Must hold the client lock */</span>
<span class="Diff-insert">+static struct ion_handle* user_ion_handle_get_check_overflow(struct ion_handle *handle)</span>
<span class="Diff-insert">+{</span>
<span class="Diff-insert">+ if (handle-&gt;user_ref_count + 1 == 0)</span>
<span class="Diff-insert">+ return ERR_PTR(-EOVERFLOW);</span>
<span class="Diff-insert">+ user_ion_handle_get(handle);</span>
<span class="Diff-insert">+ return handle;</span>
<span class="Diff-insert">+}</span>
<span class="Diff-insert">+</span>
<span class="Diff-insert">+/* passes a kref to the user ref count.</span>
<span class="Diff-insert">+ * We know we're holding a kref to the object before and</span>
<span class="Diff-insert">+ * after this call, so no need to reverify handle. */</span>
<span class="Diff-insert">+static struct ion_handle* pass_to_user(struct ion_handle *handle)</span>
<span class="Diff-insert">+{</span>
<span class="Diff-insert">+ struct ion_client *client = handle-&gt;client;</span>
<span class="Diff-insert">+ struct ion_handle *ret;</span>
<span class="Diff-insert">+</span>
<span class="Diff-insert">+ mutex_lock(&amp;client-&gt;lock);</span>
<span class="Diff-insert">+ ret = user_ion_handle_get_check_overflow(handle);</span>
<span class="Diff-insert">+ ion_handle_put_nolock(handle);</span>
<span class="Diff-insert">+ mutex_unlock(&amp;client-&gt;lock);</span>
<span class="Diff-insert">+ return ret;</span>
<span class="Diff-insert">+}</span>
<span class="Diff-insert">+</span>
<span class="Diff-insert">+/* Must hold the client lock */</span>
<span class="Diff-insert">+static int user_ion_handle_put_nolock(struct ion_handle *handle)</span>
<span class="Diff-insert">+{</span>
<span class="Diff-insert">+ int ret;</span>
<span class="Diff-insert">+</span>
<span class="Diff-insert">+ if (--handle-&gt;user_ref_count == 0) {</span>
<span class="Diff-insert">+ ret = ion_handle_put_nolock(handle);</span>
<span class="Diff-insert">+ }</span>
<span class="Diff-insert">+</span>
<span class="Diff-insert">+ return ret;</span>
<span class="Diff-insert">+}</span>
<span class="Diff-insert">+</span>
<span class="Diff-change"> static struct ion_handle *ion_handle_lookup(struct ion_client *client,</span>
<span class="Diff-change"> struct ion_buffer *buffer)</span>
<span class="Diff-change"> {</span>
<span class="Diff-hunk">@@ -645,6 +690,24 @@
</span><span class="Diff-change"> ion_handle_put_nolock(handle);</span>
<span class="Diff-change"> }</span>
<span class="Diff-change"> </span>
<span class="Diff-insert">+static void user_ion_free_nolock(struct ion_client *client, struct ion_handle *handle)</span>
<span class="Diff-insert">+{</span>
<span class="Diff-insert">+ bool valid_handle;</span>
<span class="Diff-insert">+</span>
<span class="Diff-insert">+ BUG_ON(client != handle-&gt;client);</span>
<span class="Diff-insert">+</span>
<span class="Diff-insert">+ valid_handle = ion_handle_validate(client, handle);</span>
<span class="Diff-insert">+ if (!valid_handle) {</span>
<span class="Diff-insert">+ WARN(1, &quot;%s: invalid handle passed to free.\n&quot;, __func__);</span>
<span class="Diff-insert">+ return;</span>
<span class="Diff-insert">+ }</span>
<span class="Diff-insert">+ if (!handle-&gt;user_ref_count &gt; 0) {</span>
<span class="Diff-insert">+ WARN(1, &quot;%s: User does not have access!\n&quot;, __func__);</span>
<span class="Diff-insert">+ return;</span>
<span class="Diff-insert">+ }</span>
<span class="Diff-insert">+ user_ion_handle_put_nolock(handle);</span>
<span class="Diff-insert">+}</span>
<span class="Diff-insert">+</span>
<span class="Diff-change"> void ion_free(struct ion_client *client, struct ion_handle *handle)</span>
<span class="Diff-change"> {</span>
<span class="Diff-change"> BUG_ON(client != handle-&gt;client);</span>
<span class="Diff-hunk">@@ -1439,7 +1502,7 @@
</span><span class="Diff-change"> data.allocation.flags, true);</span>
<span class="Diff-change"> if (IS_ERR(handle))</span>
<span class="Diff-change"> return PTR_ERR(handle);</span>
<span class="Diff-delete">-</span>
<span class="Diff-insert">+ pass_to_user(handle);</span>
<span class="Diff-change"> data.allocation.handle = handle-&gt;id;</span>
<span class="Diff-change"> </span>
<span class="Diff-change"> cleanup_handle = handle;</span>
<span class="Diff-hunk">@@ -1455,7 +1518,7 @@
</span><span class="Diff-change"> mutex_unlock(&amp;client-&gt;lock);</span>
<span class="Diff-change"> return PTR_ERR(handle);</span>
<span class="Diff-change"> }</span>
<span class="Diff-delete">- ion_free_nolock(client, handle);</span>
<span class="Diff-insert">+ user_ion_free_nolock(client, handle);</span>
<span class="Diff-change"> ion_handle_put_nolock(handle);</span>
<span class="Diff-change"> mutex_unlock(&amp;client-&gt;lock);</span>
<span class="Diff-change"> break;</span>
<span class="Diff-hunk">@@ -1478,10 +1541,15 @@
</span><span class="Diff-change"> {</span>
<span class="Diff-change"> struct ion_handle *handle;</span>
<span class="Diff-change"> handle = ion_import_dma_buf(client, data.fd.fd);</span>
<span class="Diff-delete">- if (IS_ERR(handle))</span>
<span class="Diff-insert">+ if (IS_ERR(handle)) {</span>
<span class="Diff-change"> ret = PTR_ERR(handle);</span>
<span class="Diff-delete">- else</span>
<span class="Diff-delete">- data.handle.handle = handle-&gt;id;</span>
<span class="Diff-insert">+ } else {</span>
<span class="Diff-insert">+ handle = pass_to_user(handle);</span>
<span class="Diff-insert">+ if (IS_ERR(handle))</span>
<span class="Diff-insert">+ ret = PTR_ERR(handle);</span>
<span class="Diff-insert">+ else</span>
<span class="Diff-insert">+ data.handle.handle = handle-&gt;id;</span>
<span class="Diff-insert">+ }</span>
<span class="Diff-change"> break;</span>
<span class="Diff-change"> }</span>
<span class="Diff-change"> case ION_IOC_SYNC:</span>
<span class="Diff-hunk">@@ -1518,8 +1586,10 @@
</span><span class="Diff-change"> if (dir &amp; _IOC_READ) {</span>
<span class="Diff-change"> if (copy_to_user((void __user *)arg, &amp;data, _IOC_SIZE(cmd))) {</span>
<span class="Diff-change"> if (cleanup_handle) {</span>
<span class="Diff-delete">- ion_free(client, cleanup_handle);</span>
<span class="Diff-delete">- ion_handle_put(cleanup_handle);</span>
<span class="Diff-insert">+ mutex_lock(&amp;client-&gt;lock);</span>
<span class="Diff-insert">+ user_ion_free_nolock(client, cleanup_handle);</span>
<span class="Diff-insert">+ ion_handle_put_nolock(cleanup_handle);</span>
<span class="Diff-insert">+ mutex_unlock(&amp;client-&gt;lock);</span>
<span class="Diff-change"> }</span>
<span class="Diff-change"> return -EFAULT;</span>
<span class="Diff-change"> }</span>
</pre></div> <!-- Container --></div> <!-- Site-content --><!-- default customFooter --><footer class="Site-footer"><div class="Footer"><span class="Footer-poweredBy">Powered by <a href="https://gerrit.googlesource.com/gitiles/">Gitiles</a></span><span class="Footer-formats"><a class="u-monospace Footer-formatsItem" href="?format=TEXT">txt</a> <a class="u-monospace Footer-formatsItem" href="?format=JSON">json</a></span></div></footer></body></html>