|
@@ -2018,7 +2018,11 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
- down_write(&mm->mmap_sem);
|
|
|
+ /*
|
|
|
+ * arg_lock protects concurent updates but we still need mmap_sem for
|
|
|
+ * read to exclude races with sys_brk.
|
|
|
+ */
|
|
|
+ down_read(&mm->mmap_sem);
|
|
|
|
|
|
/*
|
|
|
* We don't validate if these members are pointing to
|
|
@@ -2032,6 +2036,7 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
|
|
|
* to any problem in kernel itself
|
|
|
*/
|
|
|
|
|
|
+ spin_lock(&mm->arg_lock);
|
|
|
mm->start_code = prctl_map.start_code;
|
|
|
mm->end_code = prctl_map.end_code;
|
|
|
mm->start_data = prctl_map.start_data;
|
|
@@ -2043,6 +2048,7 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
|
|
|
mm->arg_end = prctl_map.arg_end;
|
|
|
mm->env_start = prctl_map.env_start;
|
|
|
mm->env_end = prctl_map.env_end;
|
|
|
+ spin_unlock(&mm->arg_lock);
|
|
|
|
|
|
/*
|
|
|
* Note this update of @saved_auxv is lockless thus
|
|
@@ -2055,7 +2061,7 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
|
|
|
if (prctl_map.auxv_size)
|
|
|
memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv));
|
|
|
|
|
|
- up_write(&mm->mmap_sem);
|
|
|
+ up_read(&mm->mmap_sem);
|
|
|
return 0;
|
|
|
}
|
|
|
#endif /* CONFIG_CHECKPOINT_RESTORE */
|