|
@@ -37,54 +37,6 @@ void __init init_vdso_image(const struct vdso_image *image)
|
|
|
|
|
|
struct linux_binprm;
|
|
|
|
|
|
-/*
|
|
|
- * Put the vdso above the (randomized) stack with another randomized
|
|
|
- * offset. This way there is no hole in the middle of address space.
|
|
|
- * To save memory make sure it is still in the same PTE as the stack
|
|
|
- * top. This doesn't give that many random bits.
|
|
|
- *
|
|
|
- * Note that this algorithm is imperfect: the distribution of the vdso
|
|
|
- * start address within a PMD is biased toward the end.
|
|
|
- *
|
|
|
- * Only used for the 64-bit and x32 vdsos.
|
|
|
- */
|
|
|
-static unsigned long vdso_addr(unsigned long start, unsigned len)
|
|
|
-{
|
|
|
-#ifdef CONFIG_X86_32
|
|
|
- return 0;
|
|
|
-#else
|
|
|
- unsigned long addr, end;
|
|
|
- unsigned offset;
|
|
|
-
|
|
|
- /*
|
|
|
- * Round up the start address. It can start out unaligned as a result
|
|
|
- * of stack start randomization.
|
|
|
- */
|
|
|
- start = PAGE_ALIGN(start);
|
|
|
-
|
|
|
- /* Round the lowest possible end address up to a PMD boundary. */
|
|
|
- end = (start + len + PMD_SIZE - 1) & PMD_MASK;
|
|
|
- if (end >= TASK_SIZE_MAX)
|
|
|
- end = TASK_SIZE_MAX;
|
|
|
- end -= len;
|
|
|
-
|
|
|
- if (end > start) {
|
|
|
- offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
|
|
|
- addr = start + (offset << PAGE_SHIFT);
|
|
|
- } else {
|
|
|
- addr = start;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Forcibly align the final address in case we have a hardware
|
|
|
- * issue that requires alignment for performance reasons.
|
|
|
- */
|
|
|
- addr = align_vdso_addr(addr);
|
|
|
-
|
|
|
- return addr;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
static int vdso_fault(const struct vm_special_mapping *sm,
|
|
|
struct vm_area_struct *vma, struct vm_fault *vmf)
|
|
|
{
|
|
@@ -249,12 +201,58 @@ up_fail:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_X86_64
|
|
|
+/*
|
|
|
+ * Put the vdso above the (randomized) stack with another randomized
|
|
|
+ * offset. This way there is no hole in the middle of address space.
|
|
|
+ * To save memory make sure it is still in the same PTE as the stack
|
|
|
+ * top. This doesn't give that many random bits.
|
|
|
+ *
|
|
|
+ * Note that this algorithm is imperfect: the distribution of the vdso
|
|
|
+ * start address within a PMD is biased toward the end.
|
|
|
+ *
|
|
|
+ * Only used for the 64-bit and x32 vdsos.
|
|
|
+ */
|
|
|
+static unsigned long vdso_addr(unsigned long start, unsigned len)
|
|
|
+{
|
|
|
+ unsigned long addr, end;
|
|
|
+ unsigned offset;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Round up the start address. It can start out unaligned as a result
|
|
|
+ * of stack start randomization.
|
|
|
+ */
|
|
|
+ start = PAGE_ALIGN(start);
|
|
|
+
|
|
|
+ /* Round the lowest possible end address up to a PMD boundary. */
|
|
|
+ end = (start + len + PMD_SIZE - 1) & PMD_MASK;
|
|
|
+ if (end >= TASK_SIZE_MAX)
|
|
|
+ end = TASK_SIZE_MAX;
|
|
|
+ end -= len;
|
|
|
+
|
|
|
+ if (end > start) {
|
|
|
+ offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
|
|
|
+ addr = start + (offset << PAGE_SHIFT);
|
|
|
+ } else {
|
|
|
+ addr = start;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Forcibly align the final address in case we have a hardware
|
|
|
+ * issue that requires alignment for performance reasons.
|
|
|
+ */
|
|
|
+ addr = align_vdso_addr(addr);
|
|
|
+
|
|
|
+ return addr;
|
|
|
+}
|
|
|
+
|
|
|
static int map_vdso_randomized(const struct vdso_image *image)
|
|
|
{
|
|
|
- unsigned long addr = vdso_addr(current->mm->start_stack,
|
|
|
- image->size - image->sym_vvar_start);
|
|
|
+ unsigned long addr = vdso_addr(current->mm->start_stack, image->size-image->sym_vvar_start);
|
|
|
+
|
|
|
return map_vdso(image, addr);
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
int map_vdso_once(const struct vdso_image *image, unsigned long addr)
|
|
|
{
|