Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 363287
b: refs/heads/master
c: e5834d6
h: refs/heads/master
i:
  363285: 9879f71
  363283: 6fb8cc6
  363279: d0bc413
v: v3
  • Loading branch information
Shankar Brahadeeswaran authored and Greg Kroah-Hartman committed Mar 5, 2013
1 parent 81928bc commit 1e30c38
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 573632c2eaf87429a89490173f34682bb71f6883
refs/heads/master: e5834d620d61d01444c41958f1816d688a96433c
45 changes: 32 additions & 13 deletions trunk/drivers/staging/android/ashmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,20 +414,29 @@ static int set_prot_mask(struct ashmem_area *asma, unsigned long prot)
static int set_name(struct ashmem_area *asma, void __user *name)
{
int ret = 0;
char local_name[ASHMEM_NAME_LEN];

mutex_lock(&ashmem_mutex);
/*
* Holding the ashmem_mutex while doing a copy_from_user might cause
* an data abort which would try to access mmap_sem. If another
* thread has invoked ashmem_mmap then it will be holding the
* semaphore and will be waiting for ashmem_mutex, there by leading to
* deadlock. We'll release the mutex and take the name to a local
* variable that does not need protection and later copy the local
* variable to the structure member with lock held.
*/
if (copy_from_user(local_name, name, ASHMEM_NAME_LEN))
return -EFAULT;

mutex_lock(&ashmem_mutex);
/* cannot change an existing mapping's name */
if (unlikely(asma->file)) {
ret = -EINVAL;
goto out;
}

if (unlikely(copy_from_user(asma->name + ASHMEM_NAME_PREFIX_LEN,
name, ASHMEM_NAME_LEN)))
ret = -EFAULT;
memcpy(asma->name + ASHMEM_NAME_PREFIX_LEN,
local_name, ASHMEM_NAME_LEN);
asma->name[ASHMEM_FULL_NAME_LEN-1] = '\0';

out:
mutex_unlock(&ashmem_mutex);

Expand All @@ -437,26 +446,36 @@ static int set_name(struct ashmem_area *asma, void __user *name)
static int get_name(struct ashmem_area *asma, void __user *name)
{
int ret = 0;
size_t len;
/*
* Have a local variable to which we'll copy the content
* from asma with the lock held. Later we can copy this to the user
* space safely without holding any locks. So even if we proceed to
* wait for mmap_sem, it won't lead to deadlock.
*/
char local_name[ASHMEM_NAME_LEN];

mutex_lock(&ashmem_mutex);
if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') {
size_t len;

/*
* Copying only `len', instead of ASHMEM_NAME_LEN, bytes
* prevents us from revealing one user's stack to another.
*/
len = strlen(asma->name + ASHMEM_NAME_PREFIX_LEN) + 1;
if (unlikely(copy_to_user(name,
asma->name + ASHMEM_NAME_PREFIX_LEN, len)))
ret = -EFAULT;
memcpy(local_name, asma->name + ASHMEM_NAME_PREFIX_LEN, len);
} else {
if (unlikely(copy_to_user(name, ASHMEM_NAME_DEF,
sizeof(ASHMEM_NAME_DEF))))
ret = -EFAULT;
len = sizeof(ASHMEM_NAME_DEF);
memcpy(local_name, ASHMEM_NAME_DEF, len);
}
mutex_unlock(&ashmem_mutex);

/*
* Now we are just copying from the stack variable to userland
* No lock held
*/
if (unlikely(copy_to_user(name, local_name, len)))
ret = -EFAULT;
return ret;
}

Expand Down

0 comments on commit 1e30c38

Please sign in to comment.