mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-26 16:51:48 +00:00
153 lines
5.2 KiB
Diff
153 lines
5.2 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index 578a82554923..a127b9ef9ebc 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 4
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 25
|
|
+SUBLEVEL = 26
|
|
EXTRAVERSION =
|
|
NAME = Blurry Fish Butt
|
|
|
|
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
|
|
index 0a291cdfaf77..efa6073ffa7e 100644
|
|
--- a/arch/x86/boot/compressed/Makefile
|
|
+++ b/arch/x86/boot/compressed/Makefile
|
|
@@ -22,7 +22,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
|
|
vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
|
|
|
|
KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
|
|
-KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
|
|
+KBUILD_CFLAGS += -fno-strict-aliasing $(call cc-option, -fPIE, -fPIC)
|
|
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
|
|
cflags-$(CONFIG_X86_32) := -march=i386
|
|
cflags-$(CONFIG_X86_64) := -mcmodel=small
|
|
@@ -35,6 +35,18 @@ KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
|
|
GCOV_PROFILE := n
|
|
|
|
LDFLAGS := -m elf_$(UTS_MACHINE)
|
|
+ifeq ($(CONFIG_RELOCATABLE),y)
|
|
+# If kernel is relocatable, build compressed kernel as PIE.
|
|
+ifeq ($(CONFIG_X86_32),y)
|
|
+LDFLAGS += $(call ld-option, -pie) $(call ld-option, --no-dynamic-linker)
|
|
+else
|
|
+# To build 64-bit compressed kernel as PIE, we disable relocation
|
|
+# overflow check to avoid relocation overflow error with a new linker
|
|
+# command-line option, -z noreloc-overflow.
|
|
+LDFLAGS += $(shell $(LD) --help 2>&1 | grep -q "\-z noreloc-overflow" \
|
|
+ && echo "-z noreloc-overflow -pie --no-dynamic-linker")
|
|
+endif
|
|
+endif
|
|
LDFLAGS_vmlinux := -T
|
|
|
|
hostprogs-y := mkpiggy
|
|
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
|
|
index 8ef964ddc18e..0256064da8da 100644
|
|
--- a/arch/x86/boot/compressed/head_32.S
|
|
+++ b/arch/x86/boot/compressed/head_32.S
|
|
@@ -31,6 +31,34 @@
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/bootparam.h>
|
|
|
|
+/*
|
|
+ * The 32-bit x86 assembler in binutils 2.26 will generate R_386_GOT32X
|
|
+ * relocation to get the symbol address in PIC. When the compressed x86
|
|
+ * kernel isn't built as PIC, the linker optimizes R_386_GOT32X
|
|
+ * relocations to their fixed symbol addresses. However, when the
|
|
+ * compressed x86 kernel is loaded at a different address, it leads
|
|
+ * to the following load failure:
|
|
+ *
|
|
+ * Failed to allocate space for phdrs
|
|
+ *
|
|
+ * during the decompression stage.
|
|
+ *
|
|
+ * If the compressed x86 kernel is relocatable at run-time, it should be
|
|
+ * compiled with -fPIE, instead of -fPIC, if possible and should be built as
|
|
+ * Position Independent Executable (PIE) so that linker won't optimize
|
|
+ * R_386_GOT32X relocation to its fixed symbol address. Older
|
|
+ * linkers generate R_386_32 relocations against locally defined symbols,
|
|
+ * _bss, _ebss, _got and _egot, in PIE. It isn't wrong, just less
|
|
+ * optimal than R_386_RELATIVE. But the x86 kernel fails to properly handle
|
|
+ * R_386_32 relocations when relocating the kernel. To generate
|
|
+ * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
|
|
+ * hidden:
|
|
+ */
|
|
+ .hidden _bss
|
|
+ .hidden _ebss
|
|
+ .hidden _got
|
|
+ .hidden _egot
|
|
+
|
|
__HEAD
|
|
ENTRY(startup_32)
|
|
#ifdef CONFIG_EFI_STUB
|
|
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
|
|
index b0c0d16ef58d..86558a199139 100644
|
|
--- a/arch/x86/boot/compressed/head_64.S
|
|
+++ b/arch/x86/boot/compressed/head_64.S
|
|
@@ -33,6 +33,14 @@
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/bootparam.h>
|
|
|
|
+/*
|
|
+ * Locally defined symbols should be marked hidden:
|
|
+ */
|
|
+ .hidden _bss
|
|
+ .hidden _ebss
|
|
+ .hidden _got
|
|
+ .hidden _egot
|
|
+
|
|
__HEAD
|
|
.code32
|
|
ENTRY(startup_32)
|
|
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
|
index cfebb742ee18..f0ffa01c90d9 100644
|
|
--- a/include/linux/mm.h
|
|
+++ b/include/linux/mm.h
|
|
@@ -2112,6 +2112,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
|
|
#define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */
|
|
#define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */
|
|
#define FOLL_MLOCK 0x1000 /* lock present pages */
|
|
+#define FOLL_COW 0x4000 /* internal GUP flag */
|
|
|
|
typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
|
|
void *data);
|
|
diff --git a/mm/gup.c b/mm/gup.c
|
|
index deafa2c91b36..4b0b7e7d1136 100644
|
|
--- a/mm/gup.c
|
|
+++ b/mm/gup.c
|
|
@@ -58,6 +58,16 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address,
|
|
return -EEXIST;
|
|
}
|
|
|
|
+/*
|
|
+ * FOLL_FORCE can write to even unwritable pte's, but only
|
|
+ * after we've gone through a COW cycle and they are dirty.
|
|
+ */
|
|
+static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
|
|
+{
|
|
+ return pte_write(pte) ||
|
|
+ ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
|
|
+}
|
|
+
|
|
static struct page *follow_page_pte(struct vm_area_struct *vma,
|
|
unsigned long address, pmd_t *pmd, unsigned int flags)
|
|
{
|
|
@@ -92,7 +102,7 @@ retry:
|
|
}
|
|
if ((flags & FOLL_NUMA) && pte_protnone(pte))
|
|
goto no_page;
|
|
- if ((flags & FOLL_WRITE) && !pte_write(pte)) {
|
|
+ if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) {
|
|
pte_unmap_unlock(ptep, ptl);
|
|
return NULL;
|
|
}
|
|
@@ -352,7 +362,7 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
|
|
* reCOWed by userspace write).
|
|
*/
|
|
if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE))
|
|
- *flags &= ~FOLL_WRITE;
|
|
+ *flags |= FOLL_COW;
|
|
return 0;
|
|
}
|
|
|