mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2025-01-02 19:31:01 -05:00
152 lines
12 KiB
Plaintext
152 lines
12 KiB
Plaintext
|
<!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&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 <ndesaulniers@google.com></td><td>Fri Feb 10 10:54:56 2017 -0800</td></tr><tr><th class="Metadata-title">committer</th><td>John Dias <joaodias@google.com></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 <drosen@google.com>
|
||
|
</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->user_ref_count++ == 0) {</span>
|
||
|
<span class="Diff-insert">+ kref_get(&handle->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->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->client;</span>
|
||
|
<span class="Diff-insert">+ struct ion_handle *ret;</span>
|
||
|
<span class="Diff-insert">+</span>
|
||
|
<span class="Diff-insert">+ mutex_lock(&client->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(&client->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->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->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, "%s: invalid handle passed to free.\n", __func__);</span>
|
||
|
<span class="Diff-insert">+ return;</span>
|
||
|
<span class="Diff-insert">+ }</span>
|
||
|
<span class="Diff-insert">+ if (!handle->user_ref_count > 0) {</span>
|
||
|
<span class="Diff-insert">+ WARN(1, "%s: User does not have access!\n", __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->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->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(&client->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(&client->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->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->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 & _IOC_READ) {</span>
|
||
|
<span class="Diff-change"> if (copy_to_user((void __user *)arg, &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(&client->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(&client->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>
|