hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/fs/binfmt_elf_fdpic.c
....@@ -1,13 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* binfmt_elf_fdpic.c: FDPIC ELF binary format
23 *
34 * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved.
45 * Written by David Howells (dhowells@redhat.com)
56 * Derived from binfmt_elf.c
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License
9
- * as published by the Free Software Foundation; either version
10
- * 2 of the License, or (at your option) any later version.
117 */
128
139 #include <linux/module.h>
....@@ -39,10 +35,10 @@
3935 #include <linux/elfcore.h>
4036 #include <linux/coredump.h>
4137 #include <linux/dax.h>
38
+#include <linux/regset.h>
4239
4340 #include <linux/uaccess.h>
4441 #include <asm/param.h>
45
-#include <asm/pgalloc.h>
4642
4743 typedef char *elf_caddr_t;
4844
....@@ -342,17 +338,16 @@
342338 interp_params.flags |= ELF_FDPIC_FLAG_CONSTDISP;
343339
344340 /* flush all traces of the currently running executable */
345
- retval = flush_old_exec(bprm);
341
+ retval = begin_new_exec(bprm);
346342 if (retval)
347343 goto error;
348344
349345 /* there's now no turning back... the old userspace image is dead,
350346 * defunct, deceased, etc.
351347 */
348
+ SET_PERSONALITY(exec_params.hdr);
352349 if (elf_check_fdpic(&exec_params.hdr))
353
- set_personality(PER_LINUX_FDPIC);
354
- else
355
- set_personality(PER_LINUX);
350
+ current->personality |= PER_LINUX_FDPIC;
356351 if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
357352 current->personality |= READ_IMPLIES_EXEC;
358353
....@@ -438,9 +433,9 @@
438433 current->mm->start_stack = current->mm->start_brk + stack_size;
439434 #endif
440435
441
- install_exec_creds(bprm);
442
- if (create_elf_fdpic_tables(bprm, current->mm,
443
- &exec_params, &interp_params) < 0)
436
+ retval = create_elf_fdpic_tables(bprm, current->mm, &exec_params,
437
+ &interp_params);
438
+ if (retval < 0)
444439 goto error;
445440
446441 kdebug("- start_code %lx", current->mm->start_code);
....@@ -541,7 +536,7 @@
541536 platform_len = strlen(k_platform) + 1;
542537 sp -= platform_len;
543538 u_platform = (char __user *) sp;
544
- if (__copy_to_user(u_platform, k_platform, platform_len) != 0)
539
+ if (copy_to_user(u_platform, k_platform, platform_len) != 0)
545540 return -EFAULT;
546541 }
547542
....@@ -556,7 +551,7 @@
556551 platform_len = strlen(k_base_platform) + 1;
557552 sp -= platform_len;
558553 u_base_platform = (char __user *) sp;
559
- if (__copy_to_user(u_base_platform, k_base_platform, platform_len) != 0)
554
+ if (copy_to_user(u_base_platform, k_base_platform, platform_len) != 0)
560555 return -EFAULT;
561556 }
562557
....@@ -593,7 +588,7 @@
593588 nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0) +
594589 (k_base_platform ? 1 : 0) + AT_VECTOR_SIZE_ARCH;
595590
596
- if (bprm->interp_flags & BINPRM_FLAGS_EXECFD)
591
+ if (bprm->have_execfd)
597592 nitems++;
598593
599594 csp = sp;
....@@ -608,11 +603,13 @@
608603 /* put the ELF interpreter info on the stack */
609604 #define NEW_AUX_ENT(id, val) \
610605 do { \
611
- struct { unsigned long _id, _val; } __user *ent; \
606
+ struct { unsigned long _id, _val; } __user *ent, v; \
612607 \
613608 ent = (void __user *) csp; \
614
- __put_user((id), &ent[nr]._id); \
615
- __put_user((val), &ent[nr]._val); \
609
+ v._id = (id); \
610
+ v._val = (val); \
611
+ if (copy_to_user(ent + nr, &v, sizeof(v))) \
612
+ return -EFAULT; \
616613 nr++; \
617614 } while (0)
618615
....@@ -633,10 +630,10 @@
633630 (elf_addr_t) (unsigned long) u_base_platform);
634631 }
635632
636
- if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
633
+ if (bprm->have_execfd) {
637634 nr = 0;
638635 csp -= 2 * sizeof(unsigned long);
639
- NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
636
+ NEW_AUX_ENT(AT_EXECFD, bprm->execfd);
640637 }
641638
642639 nr = 0;
....@@ -679,7 +676,8 @@
679676
680677 /* stack argc */
681678 csp -= sizeof(unsigned long);
682
- __put_user(bprm->argc, (unsigned long __user *) csp);
679
+ if (put_user(bprm->argc, (unsigned long __user *) csp))
680
+ return -EFAULT;
683681
684682 BUG_ON(csp != sp);
685683
....@@ -693,25 +691,29 @@
693691
694692 p = (char __user *) current->mm->arg_start;
695693 for (loop = bprm->argc; loop > 0; loop--) {
696
- __put_user((elf_caddr_t) p, argv++);
694
+ if (put_user((elf_caddr_t) p, argv++))
695
+ return -EFAULT;
697696 len = strnlen_user(p, MAX_ARG_STRLEN);
698697 if (!len || len > MAX_ARG_STRLEN)
699698 return -EINVAL;
700699 p += len;
701700 }
702
- __put_user(NULL, argv);
701
+ if (put_user(NULL, argv))
702
+ return -EFAULT;
703703 current->mm->arg_end = (unsigned long) p;
704704
705705 /* fill in the envv[] array */
706706 current->mm->env_start = (unsigned long) p;
707707 for (loop = bprm->envc; loop > 0; loop--) {
708
- __put_user((elf_caddr_t)(unsigned long) p, envp++);
708
+ if (put_user((elf_caddr_t)(unsigned long) p, envp++))
709
+ return -EFAULT;
709710 len = strnlen_user(p, MAX_ARG_STRLEN);
710711 if (!len || len > MAX_ARG_STRLEN)
711712 return -EINVAL;
712713 p += len;
713714 }
714
- __put_user(NULL, envp);
715
+ if (put_user(NULL, envp))
716
+ return -EFAULT;
715717 current->mm->env_end = (unsigned long) p;
716718
717719 mm->start_stack = (unsigned long) sp;
....@@ -853,8 +855,8 @@
853855
854856 tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
855857 dyn = (Elf32_Dyn __user *)params->dynamic_addr;
856
- __get_user(d_tag, &dyn[tmp - 1].d_tag);
857
- if (d_tag != 0)
858
+ if (get_user(d_tag, &dyn[tmp - 1].d_tag) ||
859
+ d_tag != 0)
858860 goto dynamic_error;
859861 break;
860862 }
....@@ -1187,75 +1189,31 @@
11871189 */
11881190 #ifdef CONFIG_ELF_CORE
11891191
1190
-/*
1191
- * Decide whether a segment is worth dumping; default is yes to be
1192
- * sure (missing info is worse than too much; etc).
1193
- * Personally I'd include everything, and use the coredump limit...
1194
- *
1195
- * I think we should skip something. But I am not sure how. H.J.
1196
- */
1197
-static int maydump(struct vm_area_struct *vma, unsigned long mm_flags)
1192
+struct elf_prstatus_fdpic
11981193 {
1199
- int dump_ok;
1200
-
1201
- /* Do not dump I/O mapped devices or special mappings */
1202
- if (vma->vm_flags & VM_IO) {
1203
- kdcore("%08lx: %08lx: no (IO)", vma->vm_start, vma->vm_flags);
1204
- return 0;
1205
- }
1206
-
1207
- /* If we may not read the contents, don't allow us to dump
1208
- * them either. "dump_write()" can't handle it anyway.
1194
+ struct elf_siginfo pr_info; /* Info associated with signal */
1195
+ short pr_cursig; /* Current signal */
1196
+ unsigned long pr_sigpend; /* Set of pending signals */
1197
+ unsigned long pr_sighold; /* Set of held signals */
1198
+ pid_t pr_pid;
1199
+ pid_t pr_ppid;
1200
+ pid_t pr_pgrp;
1201
+ pid_t pr_sid;
1202
+ struct __kernel_old_timeval pr_utime; /* User time */
1203
+ struct __kernel_old_timeval pr_stime; /* System time */
1204
+ struct __kernel_old_timeval pr_cutime; /* Cumulative user time */
1205
+ struct __kernel_old_timeval pr_cstime; /* Cumulative system time */
1206
+ elf_gregset_t pr_reg; /* GP registers */
1207
+ /* When using FDPIC, the loadmap addresses need to be communicated
1208
+ * to GDB in order for GDB to do the necessary relocations. The
1209
+ * fields (below) used to communicate this information are placed
1210
+ * immediately after ``pr_reg'', so that the loadmap addresses may
1211
+ * be viewed as part of the register set if so desired.
12091212 */
1210
- if (!(vma->vm_flags & VM_READ)) {
1211
- kdcore("%08lx: %08lx: no (!read)", vma->vm_start, vma->vm_flags);
1212
- return 0;
1213
- }
1214
-
1215
- /* support for DAX */
1216
- if (vma_is_dax(vma)) {
1217
- if (vma->vm_flags & VM_SHARED) {
1218
- dump_ok = test_bit(MMF_DUMP_DAX_SHARED, &mm_flags);
1219
- kdcore("%08lx: %08lx: %s (DAX shared)", vma->vm_start,
1220
- vma->vm_flags, dump_ok ? "yes" : "no");
1221
- } else {
1222
- dump_ok = test_bit(MMF_DUMP_DAX_PRIVATE, &mm_flags);
1223
- kdcore("%08lx: %08lx: %s (DAX private)", vma->vm_start,
1224
- vma->vm_flags, dump_ok ? "yes" : "no");
1225
- }
1226
- return dump_ok;
1227
- }
1228
-
1229
- /* By default, dump shared memory if mapped from an anonymous file. */
1230
- if (vma->vm_flags & VM_SHARED) {
1231
- if (file_inode(vma->vm_file)->i_nlink == 0) {
1232
- dump_ok = test_bit(MMF_DUMP_ANON_SHARED, &mm_flags);
1233
- kdcore("%08lx: %08lx: %s (share)", vma->vm_start,
1234
- vma->vm_flags, dump_ok ? "yes" : "no");
1235
- return dump_ok;
1236
- }
1237
-
1238
- dump_ok = test_bit(MMF_DUMP_MAPPED_SHARED, &mm_flags);
1239
- kdcore("%08lx: %08lx: %s (share)", vma->vm_start,
1240
- vma->vm_flags, dump_ok ? "yes" : "no");
1241
- return dump_ok;
1242
- }
1243
-
1244
-#ifdef CONFIG_MMU
1245
- /* By default, if it hasn't been written to, don't write it out */
1246
- if (!vma->anon_vma) {
1247
- dump_ok = test_bit(MMF_DUMP_MAPPED_PRIVATE, &mm_flags);
1248
- kdcore("%08lx: %08lx: %s (!anon)", vma->vm_start,
1249
- vma->vm_flags, dump_ok ? "yes" : "no");
1250
- return dump_ok;
1251
- }
1252
-#endif
1253
-
1254
- dump_ok = test_bit(MMF_DUMP_ANON_PRIVATE, &mm_flags);
1255
- kdcore("%08lx: %08lx: %s", vma->vm_start, vma->vm_flags,
1256
- dump_ok ? "yes" : "no");
1257
- return dump_ok;
1258
-}
1213
+ unsigned long pr_exec_fdpic_loadmap;
1214
+ unsigned long pr_interp_fdpic_loadmap;
1215
+ int pr_fpvalid; /* True if math co-processor being used. */
1216
+};
12591217
12601218 /* An ELF note in memory */
12611219 struct memelfnote
....@@ -1343,7 +1301,7 @@
13431301 * fill up all the fields in prstatus from the given task struct, except
13441302 * registers which need to be filled up separately.
13451303 */
1346
-static void fill_prstatus(struct elf_prstatus *prstatus,
1304
+static void fill_prstatus(struct elf_prstatus_fdpic *prstatus,
13471305 struct task_struct *p, long signr)
13481306 {
13491307 prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
....@@ -1363,17 +1321,17 @@
13631321 * group-wide total, not its individual thread total.
13641322 */
13651323 thread_group_cputime(p, &cputime);
1366
- prstatus->pr_utime = ns_to_timeval(cputime.utime);
1367
- prstatus->pr_stime = ns_to_timeval(cputime.stime);
1324
+ prstatus->pr_utime = ns_to_kernel_old_timeval(cputime.utime);
1325
+ prstatus->pr_stime = ns_to_kernel_old_timeval(cputime.stime);
13681326 } else {
13691327 u64 utime, stime;
13701328
13711329 task_cputime(p, &utime, &stime);
1372
- prstatus->pr_utime = ns_to_timeval(utime);
1373
- prstatus->pr_stime = ns_to_timeval(stime);
1330
+ prstatus->pr_utime = ns_to_kernel_old_timeval(utime);
1331
+ prstatus->pr_stime = ns_to_kernel_old_timeval(stime);
13741332 }
1375
- prstatus->pr_cutime = ns_to_timeval(p->signal->cutime);
1376
- prstatus->pr_cstime = ns_to_timeval(p->signal->cstime);
1333
+ prstatus->pr_cutime = ns_to_kernel_old_timeval(p->signal->cutime);
1334
+ prstatus->pr_cstime = ns_to_kernel_old_timeval(p->signal->cstime);
13771335
13781336 prstatus->pr_exec_fdpic_loadmap = p->mm->context.exec_fdpic_loadmap;
13791337 prstatus->pr_interp_fdpic_loadmap = p->mm->context.interp_fdpic_loadmap;
....@@ -1425,14 +1383,10 @@
14251383 /* Here is the structure in which status of each thread is captured. */
14261384 struct elf_thread_status
14271385 {
1428
- struct list_head list;
1429
- struct elf_prstatus prstatus; /* NT_PRSTATUS */
1386
+ struct elf_thread_status *next;
1387
+ struct elf_prstatus_fdpic prstatus; /* NT_PRSTATUS */
14301388 elf_fpregset_t fpu; /* NT_PRFPREG */
1431
- struct task_struct *thread;
1432
-#ifdef ELF_CORE_COPY_XFPREGS
1433
- elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
1434
-#endif
1435
- struct memelfnote notes[3];
1389
+ struct memelfnote notes[2];
14361390 int num_notes;
14371391 };
14381392
....@@ -1441,38 +1395,44 @@
14411395 * we need to keep a linked list of every thread's pr_status and then create
14421396 * a single section for them in the final core file.
14431397 */
1444
-static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
1398
+static struct elf_thread_status *elf_dump_thread_status(long signr, struct task_struct *p, int *sz)
14451399 {
1446
- struct task_struct *p = t->thread;
1447
- int sz = 0;
1400
+ const struct user_regset_view *view = task_user_regset_view(p);
1401
+ struct elf_thread_status *t;
1402
+ int i, ret;
14481403
1449
- t->num_notes = 0;
1404
+ t = kzalloc(sizeof(struct elf_thread_status), GFP_KERNEL);
1405
+ if (!t)
1406
+ return t;
14501407
14511408 fill_prstatus(&t->prstatus, p, signr);
1452
- elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
1409
+ regset_get(p, &view->regsets[0],
1410
+ sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg);
14531411
14541412 fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus),
14551413 &t->prstatus);
14561414 t->num_notes++;
1457
- sz += notesize(&t->notes[0]);
1415
+ *sz += notesize(&t->notes[0]);
14581416
1459
- t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu);
1417
+ for (i = 1; i < view->n; ++i) {
1418
+ const struct user_regset *regset = &view->regsets[i];
1419
+ if (regset->core_note_type != NT_PRFPREG)
1420
+ continue;
1421
+ if (regset->active && regset->active(p, regset) <= 0)
1422
+ continue;
1423
+ ret = regset_get(p, regset, sizeof(t->fpu), &t->fpu);
1424
+ if (ret >= 0)
1425
+ t->prstatus.pr_fpvalid = 1;
1426
+ break;
1427
+ }
1428
+
14601429 if (t->prstatus.pr_fpvalid) {
14611430 fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu),
14621431 &t->fpu);
14631432 t->num_notes++;
1464
- sz += notesize(&t->notes[1]);
1433
+ *sz += notesize(&t->notes[1]);
14651434 }
1466
-
1467
-#ifdef ELF_CORE_COPY_XFPREGS
1468
- if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
1469
- fill_note(&t->notes[2], "LINUX", ELF_CORE_XFPREG_TYPE,
1470
- sizeof(t->xfpu), &t->xfpu);
1471
- t->num_notes++;
1472
- sz += notesize(&t->notes[2]);
1473
- }
1474
-#endif
1475
- return sz;
1435
+ return t;
14761436 }
14771437
14781438 static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
....@@ -1494,52 +1454,19 @@
14941454 /*
14951455 * dump the segments for an MMU process
14961456 */
1497
-static bool elf_fdpic_dump_segments(struct coredump_params *cprm)
1457
+static bool elf_fdpic_dump_segments(struct coredump_params *cprm,
1458
+ struct core_vma_metadata *vma_meta,
1459
+ int vma_count)
14981460 {
1499
- struct vm_area_struct *vma;
1461
+ int i;
15001462
1501
- for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
1502
-#ifdef CONFIG_MMU
1503
- unsigned long addr;
1504
-#endif
1463
+ for (i = 0; i < vma_count; i++) {
1464
+ struct core_vma_metadata *meta = vma_meta + i;
15051465
1506
- if (!maydump(vma, cprm->mm_flags))
1507
- continue;
1508
-
1509
-#ifdef CONFIG_MMU
1510
- for (addr = vma->vm_start; addr < vma->vm_end;
1511
- addr += PAGE_SIZE) {
1512
- bool res;
1513
- struct page *page = get_dump_page(addr);
1514
- if (page) {
1515
- void *kaddr = kmap(page);
1516
- res = dump_emit(cprm, kaddr, PAGE_SIZE);
1517
- kunmap(page);
1518
- put_page(page);
1519
- } else {
1520
- res = dump_skip(cprm, PAGE_SIZE);
1521
- }
1522
- if (!res)
1523
- return false;
1524
- }
1525
-#else
1526
- if (!dump_emit(cprm, (void *) vma->vm_start,
1527
- vma->vm_end - vma->vm_start))
1466
+ if (!dump_user_range(cprm, meta->start, meta->dump_size))
15281467 return false;
1529
-#endif
15301468 }
15311469 return true;
1532
-}
1533
-
1534
-static size_t elf_core_vma_data_size(unsigned long mm_flags)
1535
-{
1536
- struct vm_area_struct *vma;
1537
- size_t size = 0;
1538
-
1539
- for (vma = current->mm->mmap; vma; vma = vma->vm_next)
1540
- if (maydump(vma, mm_flags))
1541
- size += vma->vm_end - vma->vm_start;
1542
- return size;
15431470 }
15441471
15451472 /*
....@@ -1551,24 +1478,14 @@
15511478 */
15521479 static int elf_fdpic_core_dump(struct coredump_params *cprm)
15531480 {
1554
-#define NUM_NOTES 6
15551481 int has_dumped = 0;
1556
- mm_segment_t fs;
1557
- int segs;
1482
+ int vma_count, segs;
15581483 int i;
1559
- struct vm_area_struct *vma;
15601484 struct elfhdr *elf = NULL;
15611485 loff_t offset = 0, dataoff;
1562
- int numnote;
1563
- struct memelfnote *notes = NULL;
1564
- struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
1486
+ struct memelfnote psinfo_note, auxv_note;
15651487 struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */
1566
- LIST_HEAD(thread_list);
1567
- struct list_head *t;
1568
- elf_fpregset_t *fpu = NULL;
1569
-#ifdef ELF_CORE_COPY_XFPREGS
1570
- elf_fpxregset_t *xfpu = NULL;
1571
-#endif
1488
+ struct elf_thread_status *thread_list = NULL;
15721489 int thread_status_size = 0;
15731490 elf_addr_t *auxv;
15741491 struct elf_phdr *phdr4note = NULL;
....@@ -1577,67 +1494,40 @@
15771494 elf_addr_t e_shoff;
15781495 struct core_thread *ct;
15791496 struct elf_thread_status *tmp;
1580
-
1581
- /*
1582
- * We no longer stop all VM operations.
1583
- *
1584
- * This is because those proceses that could possibly change map_count
1585
- * or the mmap / vma pages are now blocked in do_exit on current
1586
- * finishing this core dump.
1587
- *
1588
- * Only ptrace can touch these memory addresses, but it doesn't change
1589
- * the map_count or the pages allocated. So no possibility of crashing
1590
- * exists while dumping the mm->vm_next areas to the core file.
1591
- */
1497
+ struct core_vma_metadata *vma_meta = NULL;
1498
+ size_t vma_data_size;
15921499
15931500 /* alloc memory for large data structures: too large to be on stack */
15941501 elf = kmalloc(sizeof(*elf), GFP_KERNEL);
15951502 if (!elf)
1596
- goto cleanup;
1597
- prstatus = kzalloc(sizeof(*prstatus), GFP_KERNEL);
1598
- if (!prstatus)
1599
- goto cleanup;
1503
+ goto end_coredump;
16001504 psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
16011505 if (!psinfo)
1602
- goto cleanup;
1603
- notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote),
1604
- GFP_KERNEL);
1605
- if (!notes)
1606
- goto cleanup;
1607
- fpu = kmalloc(sizeof(*fpu), GFP_KERNEL);
1608
- if (!fpu)
1609
- goto cleanup;
1610
-#ifdef ELF_CORE_COPY_XFPREGS
1611
- xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL);
1612
- if (!xfpu)
1613
- goto cleanup;
1614
-#endif
1506
+ goto end_coredump;
1507
+
1508
+ if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size))
1509
+ goto end_coredump;
16151510
16161511 for (ct = current->mm->core_state->dumper.next;
16171512 ct; ct = ct->next) {
1618
- tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
1513
+ tmp = elf_dump_thread_status(cprm->siginfo->si_signo,
1514
+ ct->task, &thread_status_size);
16191515 if (!tmp)
1620
- goto cleanup;
1516
+ goto end_coredump;
16211517
1622
- tmp->thread = ct->task;
1623
- list_add(&tmp->list, &thread_list);
1624
- }
1625
-
1626
- list_for_each(t, &thread_list) {
1627
- struct elf_thread_status *tmp;
1628
- int sz;
1629
-
1630
- tmp = list_entry(t, struct elf_thread_status, list);
1631
- sz = elf_dump_thread_status(cprm->siginfo->si_signo, tmp);
1632
- thread_status_size += sz;
1518
+ tmp->next = thread_list;
1519
+ thread_list = tmp;
16331520 }
16341521
16351522 /* now collect the dump for the current */
1636
- fill_prstatus(prstatus, current, cprm->siginfo->si_signo);
1637
- elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);
1523
+ tmp = elf_dump_thread_status(cprm->siginfo->si_signo,
1524
+ current, &thread_status_size);
1525
+ if (!tmp)
1526
+ goto end_coredump;
1527
+ tmp->next = thread_list;
1528
+ thread_list = tmp;
16381529
1639
- segs = current->mm->map_count;
1640
- segs += elf_core_extra_phdrs();
1530
+ segs = vma_count + elf_core_extra_phdrs();
16411531
16421532 /* for notes section */
16431533 segs++;
....@@ -1656,59 +1546,33 @@
16561546 * with info from their /proc.
16571547 */
16581548
1659
- fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus);
16601549 fill_psinfo(psinfo, current->group_leader, current->mm);
1661
- fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
1662
-
1663
- numnote = 2;
1550
+ fill_note(&psinfo_note, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
1551
+ thread_status_size += notesize(&psinfo_note);
16641552
16651553 auxv = (elf_addr_t *) current->mm->saved_auxv;
1666
-
16671554 i = 0;
16681555 do
16691556 i += 2;
16701557 while (auxv[i - 2] != AT_NULL);
1671
- fill_note(&notes[numnote++], "CORE", NT_AUXV,
1672
- i * sizeof(elf_addr_t), auxv);
1558
+ fill_note(&auxv_note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv);
1559
+ thread_status_size += notesize(&auxv_note);
16731560
1674
- /* Try to dump the FPU. */
1675
- if ((prstatus->pr_fpvalid =
1676
- elf_core_copy_task_fpregs(current, cprm->regs, fpu)))
1677
- fill_note(notes + numnote++,
1678
- "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
1679
-#ifdef ELF_CORE_COPY_XFPREGS
1680
- if (elf_core_copy_task_xfpregs(current, xfpu))
1681
- fill_note(notes + numnote++,
1682
- "LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu);
1683
-#endif
1684
-
1685
- fs = get_fs();
1686
- set_fs(KERNEL_DS);
1687
-
1688
- offset += sizeof(*elf); /* Elf header */
1561
+ offset = sizeof(*elf); /* Elf header */
16891562 offset += segs * sizeof(struct elf_phdr); /* Program headers */
16901563
16911564 /* Write notes phdr entry */
1692
- {
1693
- int sz = 0;
1565
+ phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
1566
+ if (!phdr4note)
1567
+ goto end_coredump;
16941568
1695
- for (i = 0; i < numnote; i++)
1696
- sz += notesize(notes + i);
1697
-
1698
- sz += thread_status_size;
1699
-
1700
- phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
1701
- if (!phdr4note)
1702
- goto end_coredump;
1703
-
1704
- fill_elf_note_phdr(phdr4note, sz, offset);
1705
- offset += sz;
1706
- }
1569
+ fill_elf_note_phdr(phdr4note, thread_status_size, offset);
1570
+ offset += thread_status_size;
17071571
17081572 /* Page-align dumped data */
17091573 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
17101574
1711
- offset += elf_core_vma_data_size(cprm->mm_flags);
1575
+ offset += vma_data_size;
17121576 offset += elf_core_extra_data_size();
17131577 e_shoff = offset;
17141578
....@@ -1728,23 +1592,26 @@
17281592 goto end_coredump;
17291593
17301594 /* write program headers for segments dump */
1731
- for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
1595
+ for (i = 0; i < vma_count; i++) {
1596
+ struct core_vma_metadata *meta = vma_meta + i;
17321597 struct elf_phdr phdr;
17331598 size_t sz;
17341599
1735
- sz = vma->vm_end - vma->vm_start;
1600
+ sz = meta->end - meta->start;
17361601
17371602 phdr.p_type = PT_LOAD;
17381603 phdr.p_offset = offset;
1739
- phdr.p_vaddr = vma->vm_start;
1604
+ phdr.p_vaddr = meta->start;
17401605 phdr.p_paddr = 0;
1741
- phdr.p_filesz = maydump(vma, cprm->mm_flags) ? sz : 0;
1606
+ phdr.p_filesz = meta->dump_size;
17421607 phdr.p_memsz = sz;
17431608 offset += phdr.p_filesz;
1744
- phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
1745
- if (vma->vm_flags & VM_WRITE)
1609
+ phdr.p_flags = 0;
1610
+ if (meta->flags & VM_READ)
1611
+ phdr.p_flags |= PF_R;
1612
+ if (meta->flags & VM_WRITE)
17461613 phdr.p_flags |= PF_W;
1747
- if (vma->vm_flags & VM_EXEC)
1614
+ if (meta->flags & VM_EXEC)
17481615 phdr.p_flags |= PF_X;
17491616 phdr.p_align = ELF_EXEC_PAGESIZE;
17501617
....@@ -1756,15 +1623,18 @@
17561623 goto end_coredump;
17571624
17581625 /* write out the notes section */
1759
- for (i = 0; i < numnote; i++)
1760
- if (!writenote(notes + i, cprm))
1626
+ if (!writenote(thread_list->notes, cprm))
1627
+ goto end_coredump;
1628
+ if (!writenote(&psinfo_note, cprm))
1629
+ goto end_coredump;
1630
+ if (!writenote(&auxv_note, cprm))
1631
+ goto end_coredump;
1632
+ for (i = 1; i < thread_list->num_notes; i++)
1633
+ if (!writenote(thread_list->notes + i, cprm))
17611634 goto end_coredump;
17621635
17631636 /* write out the thread status notes section */
1764
- list_for_each(t, &thread_list) {
1765
- struct elf_thread_status *tmp =
1766
- list_entry(t, struct elf_thread_status, list);
1767
-
1637
+ for (tmp = thread_list->next; tmp; tmp = tmp->next) {
17681638 for (i = 0; i < tmp->num_notes; i++)
17691639 if (!writenote(&tmp->notes[i], cprm))
17701640 goto end_coredump;
....@@ -1773,7 +1643,7 @@
17731643 if (!dump_skip(cprm, dataoff - cprm->pos))
17741644 goto end_coredump;
17751645
1776
- if (!elf_fdpic_dump_segments(cprm))
1646
+ if (!elf_fdpic_dump_segments(cprm, vma_meta, vma_count))
17771647 goto end_coredump;
17781648
17791649 if (!elf_core_write_extra_data(cprm))
....@@ -1792,26 +1662,17 @@
17921662 }
17931663
17941664 end_coredump:
1795
- set_fs(fs);
1796
-
1797
-cleanup:
1798
- while (!list_empty(&thread_list)) {
1799
- struct list_head *tmp = thread_list.next;
1800
- list_del(tmp);
1801
- kfree(list_entry(tmp, struct elf_thread_status, list));
1665
+ while (thread_list) {
1666
+ tmp = thread_list;
1667
+ thread_list = thread_list->next;
1668
+ kfree(tmp);
18021669 }
1670
+ kvfree(vma_meta);
18031671 kfree(phdr4note);
18041672 kfree(elf);
1805
- kfree(prstatus);
18061673 kfree(psinfo);
1807
- kfree(notes);
1808
- kfree(fpu);
18091674 kfree(shdr4extnum);
1810
-#ifdef ELF_CORE_COPY_XFPREGS
1811
- kfree(xfpu);
1812
-#endif
18131675 return has_dumped;
1814
-#undef NUM_NOTES
18151676 }
18161677
18171678 #endif /* CONFIG_ELF_CORE */