hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/binfmt_flat.c
....@@ -42,6 +42,11 @@
4242 #include <asm/unaligned.h>
4343 #include <asm/cacheflush.h>
4444 #include <asm/page.h>
45
+#include <asm/flat.h>
46
+
47
+#ifndef flat_get_relocate_addr
48
+#define flat_get_relocate_addr(rel) (rel)
49
+#endif
4550
4651 /****************************************************************************/
4752
....@@ -62,6 +67,12 @@
6267
6368 #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
6469 #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
70
+
71
+#ifdef CONFIG_BINFMT_SHARED_FLAT
72
+#define MAX_SHARED_LIBS (4)
73
+#else
74
+#define MAX_SHARED_LIBS (1)
75
+#endif
6576
6677 struct lib_info {
6778 struct {
....@@ -120,41 +131,47 @@
120131
121132 sp -= bprm->envc + 1;
122133 sp -= bprm->argc + 1;
123
- sp -= flat_argvp_envp_on_stack() ? 2 : 0;
134
+ if (IS_ENABLED(CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK))
135
+ sp -= 2; /* argvp + envp */
124136 sp -= 1; /* &argc */
125137
126138 current->mm->start_stack = (unsigned long)sp & -FLAT_STACK_ALIGN;
127139 sp = (unsigned long __user *)current->mm->start_stack;
128140
129
- __put_user(bprm->argc, sp++);
130
- if (flat_argvp_envp_on_stack()) {
141
+ if (put_user(bprm->argc, sp++))
142
+ return -EFAULT;
143
+ if (IS_ENABLED(CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK)) {
131144 unsigned long argv, envp;
132145 argv = (unsigned long)(sp + 2);
133146 envp = (unsigned long)(sp + 2 + bprm->argc + 1);
134
- __put_user(argv, sp++);
135
- __put_user(envp, sp++);
147
+ if (put_user(argv, sp++) || put_user(envp, sp++))
148
+ return -EFAULT;
136149 }
137150
138151 current->mm->arg_start = (unsigned long)p;
139152 for (i = bprm->argc; i > 0; i--) {
140
- __put_user((unsigned long)p, sp++);
153
+ if (put_user((unsigned long)p, sp++))
154
+ return -EFAULT;
141155 len = strnlen_user(p, MAX_ARG_STRLEN);
142156 if (!len || len > MAX_ARG_STRLEN)
143157 return -EINVAL;
144158 p += len;
145159 }
146
- __put_user(0, sp++);
160
+ if (put_user(0, sp++))
161
+ return -EFAULT;
147162 current->mm->arg_end = (unsigned long)p;
148163
149164 current->mm->env_start = (unsigned long) p;
150165 for (i = bprm->envc; i > 0; i--) {
151
- __put_user((unsigned long)p, sp++);
166
+ if (put_user((unsigned long)p, sp++))
167
+ return -EFAULT;
152168 len = strnlen_user(p, MAX_ARG_STRLEN);
153169 if (!len || len > MAX_ARG_STRLEN)
154170 return -EINVAL;
155171 p += len;
156172 }
157
- __put_user(0, sp++);
173
+ if (put_user(0, sp++))
174
+ return -EFAULT;
158175 current->mm->env_end = (unsigned long)p;
159176
160177 return 0;
....@@ -345,7 +362,7 @@
345362 start_code = p->lib_list[id].start_code;
346363 text_len = p->lib_list[id].text_len;
347364
348
- if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
365
+ if (r > start_brk - start_data + text_len) {
349366 pr_err("reloc outside program 0x%lx (0 - 0x%lx/0x%lx)",
350367 r, start_brk-start_data+text_len, text_len);
351368 goto failed;
....@@ -368,6 +385,7 @@
368385
369386 /****************************************************************************/
370387
388
+#ifdef CONFIG_BINFMT_FLAT_OLD
371389 static void old_reloc(unsigned long rl)
372390 {
373391 static const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
....@@ -405,8 +423,33 @@
405423
406424 pr_debug("Relocation became %lx\n", val);
407425 }
426
+#endif /* CONFIG_BINFMT_FLAT_OLD */
408427
409428 /****************************************************************************/
429
+
430
+static inline u32 __user *skip_got_header(u32 __user *rp)
431
+{
432
+ if (IS_ENABLED(CONFIG_RISCV)) {
433
+ /*
434
+ * RISC-V has a 16 byte GOT PLT header for elf64-riscv
435
+ * and 8 byte GOT PLT header for elf32-riscv.
436
+ * Skip the whole GOT PLT header, since it is reserved
437
+ * for the dynamic linker (ld.so).
438
+ */
439
+ u32 rp_val0, rp_val1;
440
+
441
+ if (get_user(rp_val0, rp))
442
+ return rp;
443
+ if (get_user(rp_val1, rp + 1))
444
+ return rp;
445
+
446
+ if (rp_val0 == 0xffffffff && rp_val1 == 0xffffffff)
447
+ rp += 4;
448
+ else if (rp_val0 == 0xffffffff)
449
+ rp += 2;
450
+ }
451
+ return rp;
452
+}
410453
411454 static int load_flat_file(struct linux_binprm *bprm,
412455 struct lib_info *libinfo, int id, unsigned long *extra_stack)
....@@ -415,8 +458,8 @@
415458 unsigned long textpos, datapos, realdatastart;
416459 u32 text_len, data_len, bss_len, stack_len, full_data, flags;
417460 unsigned long len, memp, memp_size, extra, rlim;
418
- u32 __user *reloc, *rp;
419
- struct inode *inode;
461
+ __be32 __user *reloc;
462
+ u32 __user *rp;
420463 int i, rev, relocs;
421464 loff_t fpos;
422465 unsigned long start_code, end_code;
....@@ -424,7 +467,6 @@
424467 int ret;
425468
426469 hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
427
- inode = file_inode(bprm->file);
428470
429471 text_len = ntohl(hdr->data_start);
430472 data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start);
....@@ -454,6 +496,7 @@
454496 if (flags & FLAT_FLAG_KTRACE)
455497 pr_info("Loading file: %s\n", bprm->filename);
456498
499
+#ifdef CONFIG_BINFMT_FLAT_OLD
457500 if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
458501 pr_err("bad flat file version 0x%x (supported 0x%lx and 0x%lx)\n",
459502 rev, FLAT_VERSION, OLD_FLAT_VERSION);
....@@ -470,6 +513,23 @@
470513 }
471514
472515 /*
516
+ * fix up the flags for the older format, there were all kinds
517
+ * of endian hacks, this only works for the simple cases
518
+ */
519
+ if (rev == OLD_FLAT_VERSION &&
520
+ (flags || IS_ENABLED(CONFIG_BINFMT_FLAT_OLD_ALWAYS_RAM)))
521
+ flags = FLAT_FLAG_RAM;
522
+
523
+#else /* CONFIG_BINFMT_FLAT_OLD */
524
+ if (rev != FLAT_VERSION) {
525
+ pr_err("bad flat file version 0x%x (supported 0x%lx)\n",
526
+ rev, FLAT_VERSION);
527
+ ret = -ENOEXEC;
528
+ goto err;
529
+ }
530
+#endif /* !CONFIG_BINFMT_FLAT_OLD */
531
+
532
+ /*
473533 * Make sure the header params are sane.
474534 * 28 bits (256 MB) is way more than reasonable in this case.
475535 * If some top bits are set we have probable binary corruption.
....@@ -479,13 +539,6 @@
479539 ret = -ENOEXEC;
480540 goto err;
481541 }
482
-
483
- /*
484
- * fix up the flags for the older format, there were all kinds
485
- * of endian hacks, this only works for the simple cases
486
- */
487
- if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
488
- flags = FLAT_FLAG_RAM;
489542
490543 #ifndef CONFIG_BINFMT_ZFLAT
491544 if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
....@@ -510,7 +563,7 @@
510563
511564 /* Flush all traces of the currently running executable */
512565 if (id == 0) {
513
- ret = flush_old_exec(bprm);
566
+ ret = begin_new_exec(bprm);
514567 if (ret)
515568 goto err;
516569
....@@ -587,7 +640,7 @@
587640 goto err;
588641 }
589642
590
- reloc = (u32 __user *)
643
+ reloc = (__be32 __user *)
591644 (datapos + (ntohl(hdr->reloc_start) - text_len));
592645 memp = realdatastart;
593646 memp_size = len;
....@@ -612,7 +665,7 @@
612665 MAX_SHARED_LIBS * sizeof(u32),
613666 FLAT_DATA_ALIGN);
614667
615
- reloc = (u32 __user *)
668
+ reloc = (__be32 __user *)
616669 (datapos + (ntohl(hdr->reloc_start) - text_len));
617670 memp = textpos;
618671 memp_size = len;
....@@ -745,7 +798,8 @@
745798 * image.
746799 */
747800 if (flags & FLAT_FLAG_GOTPIC) {
748
- for (rp = (u32 __user *)datapos; ; rp++) {
801
+ rp = skip_got_header((u32 __user *) datapos);
802
+ for (; ; rp++) {
749803 u32 addr, rp_val;
750804 if (get_user(rp_val, rp))
751805 return -EFAULT;
....@@ -775,20 +829,18 @@
775829 * __start to address 4 so that is okay).
776830 */
777831 if (rev > OLD_FLAT_VERSION) {
778
- u32 __maybe_unused persistent = 0;
779832 for (i = 0; i < relocs; i++) {
780833 u32 addr, relval;
834
+ __be32 tmp;
781835
782836 /*
783837 * Get the address of the pointer to be
784838 * relocated (of course, the address has to be
785839 * relocated first).
786840 */
787
- if (get_user(relval, reloc + i))
841
+ if (get_user(tmp, reloc + i))
788842 return -EFAULT;
789
- relval = ntohl(relval);
790
- if (flat_set_persistent(relval, &persistent))
791
- continue;
843
+ relval = ntohl(tmp);
792844 addr = flat_get_relocate_addr(relval);
793845 rp = (u32 __user *)calc_reloc(addr, libinfo, id, 1);
794846 if (rp == (u32 __user *)RELOC_FAILED) {
....@@ -797,8 +849,7 @@
797849 }
798850
799851 /* Get the pointer's value. */
800
- ret = flat_get_addr_from_rp(rp, relval, flags,
801
- &addr, &persistent);
852
+ ret = flat_get_addr_from_rp(rp, relval, flags, &addr);
802853 if (unlikely(ret))
803854 goto err;
804855
....@@ -807,8 +858,13 @@
807858 * Do the relocation. PIC relocs in the data section are
808859 * already in target order
809860 */
810
- if ((flags & FLAT_FLAG_GOTPIC) == 0)
811
- addr = ntohl(addr);
861
+ if ((flags & FLAT_FLAG_GOTPIC) == 0) {
862
+ /*
863
+ * Meh, the same value can have a different
864
+ * byte order based on a flag..
865
+ */
866
+ addr = ntohl((__force __be32)addr);
867
+ }
812868 addr = calc_reloc(addr, libinfo, id, 0);
813869 if (addr == RELOC_FAILED) {
814870 ret = -ENOEXEC;
....@@ -821,17 +877,18 @@
821877 goto err;
822878 }
823879 }
880
+#ifdef CONFIG_BINFMT_FLAT_OLD
824881 } else {
825882 for (i = 0; i < relocs; i++) {
826
- u32 relval;
883
+ __be32 relval;
827884 if (get_user(relval, reloc + i))
828885 return -EFAULT;
829
- relval = ntohl(relval);
830
- old_reloc(relval);
886
+ old_reloc(ntohl(relval));
831887 }
888
+#endif /* CONFIG_BINFMT_FLAT_OLD */
832889 }
833890
834
- flush_icache_range(start_code, end_code);
891
+ flush_icache_user_range(start_code, end_code);
835892
836893 /* zero the BSS, BRK and stack areas */
837894 if (clear_user((void __user *)(datapos + data_len), bss_len +
....@@ -940,8 +997,6 @@
940997 }
941998 }
942999
943
- install_exec_creds(bprm);
944
-
9451000 set_binfmt(&flat_format);
9461001
9471002 #ifdef CONFIG_MMU
....@@ -975,7 +1030,8 @@
9751030 unsigned long __user *sp;
9761031 current->mm->start_stack -= sizeof(unsigned long);
9771032 sp = (unsigned long __user *)current->mm->start_stack;
978
- __put_user(start_addr, sp);
1033
+ if (put_user(start_addr, sp))
1034
+ return -EFAULT;
9791035 start_addr = libinfo.lib_list[i].entry;
9801036 }
9811037 }