Skip to content

Commit 2722ae9

Browse files
committed
Merge branch 'coredump-vma-snapshot-fix-for-v5.18' of https://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace into for-next/execve
- Fix missing mmap_lock in file_files_note (Eric W. Biederman)
2 parents 9e1a3ce + f833116 commit 2722ae9

6 files changed

Lines changed: 97 additions & 84 deletions

File tree

fs/binfmt_elf.c

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,17 +1641,16 @@ static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
16411641
* long file_ofs
16421642
* followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...
16431643
*/
1644-
static int fill_files_note(struct memelfnote *note)
1644+
static int fill_files_note(struct memelfnote *note, struct coredump_params *cprm)
16451645
{
1646-
struct mm_struct *mm = current->mm;
1647-
struct vm_area_struct *vma;
16481646
unsigned count, size, names_ofs, remaining, n;
16491647
user_long_t *data;
16501648
user_long_t *start_end_ofs;
16511649
char *name_base, *name_curpos;
1650+
int i;
16521651

16531652
/* *Estimated* file count and total data size needed */
1654-
count = mm->map_count;
1653+
count = cprm->vma_count;
16551654
if (count > UINT_MAX / 64)
16561655
return -EINVAL;
16571656
size = count * 64;
@@ -1673,11 +1672,12 @@ static int fill_files_note(struct memelfnote *note)
16731672
name_base = name_curpos = ((char *)data) + names_ofs;
16741673
remaining = size - names_ofs;
16751674
count = 0;
1676-
for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
1675+
for (i = 0; i < cprm->vma_count; i++) {
1676+
struct core_vma_metadata *m = &cprm->vma_meta[i];
16771677
struct file *file;
16781678
const char *filename;
16791679

1680-
file = vma->vm_file;
1680+
file = m->file;
16811681
if (!file)
16821682
continue;
16831683
filename = file_path(file, name_curpos, remaining);
@@ -1697,9 +1697,9 @@ static int fill_files_note(struct memelfnote *note)
16971697
memmove(name_curpos, filename, n);
16981698
name_curpos += n;
16991699

1700-
*start_end_ofs++ = vma->vm_start;
1701-
*start_end_ofs++ = vma->vm_end;
1702-
*start_end_ofs++ = vma->vm_pgoff;
1700+
*start_end_ofs++ = m->start;
1701+
*start_end_ofs++ = m->end;
1702+
*start_end_ofs++ = m->pgoff;
17031703
count++;
17041704
}
17051705

@@ -1710,7 +1710,7 @@ static int fill_files_note(struct memelfnote *note)
17101710
* Count usually is less than mm->map_count,
17111711
* we need to move filenames down.
17121712
*/
1713-
n = mm->map_count - count;
1713+
n = cprm->vma_count - count;
17141714
if (n != 0) {
17151715
unsigned shift_bytes = n * 3 * sizeof(data[0]);
17161716
memmove(name_base - shift_bytes, name_base,
@@ -1822,7 +1822,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
18221822

18231823
static int fill_note_info(struct elfhdr *elf, int phdrs,
18241824
struct elf_note_info *info,
1825-
const kernel_siginfo_t *siginfo, struct pt_regs *regs)
1825+
struct coredump_params *cprm)
18261826
{
18271827
struct task_struct *dump_task = current;
18281828
const struct user_regset_view *view = task_user_regset_view(dump_task);
@@ -1894,7 +1894,7 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
18941894
* Now fill in each thread's information.
18951895
*/
18961896
for (t = info->thread; t != NULL; t = t->next)
1897-
if (!fill_thread_core_info(t, view, siginfo->si_signo, &info->size))
1897+
if (!fill_thread_core_info(t, view, cprm->siginfo->si_signo, &info->size))
18981898
return 0;
18991899

19001900
/*
@@ -1903,13 +1903,13 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
19031903
fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm);
19041904
info->size += notesize(&info->psinfo);
19051905

1906-
fill_siginfo_note(&info->signote, &info->csigdata, siginfo);
1906+
fill_siginfo_note(&info->signote, &info->csigdata, cprm->siginfo);
19071907
info->size += notesize(&info->signote);
19081908

19091909
fill_auxv_note(&info->auxv, current->mm);
19101910
info->size += notesize(&info->auxv);
19111911

1912-
if (fill_files_note(&info->files) == 0)
1912+
if (fill_files_note(&info->files, cprm) == 0)
19131913
info->size += notesize(&info->files);
19141914

19151915
return 1;
@@ -2051,7 +2051,7 @@ static int elf_note_info_init(struct elf_note_info *info)
20512051

20522052
static int fill_note_info(struct elfhdr *elf, int phdrs,
20532053
struct elf_note_info *info,
2054-
const kernel_siginfo_t *siginfo, struct pt_regs *regs)
2054+
struct coredump_params *cprm)
20552055
{
20562056
struct core_thread *ct;
20572057
struct elf_thread_status *ets;
@@ -2072,13 +2072,13 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
20722072
list_for_each_entry(ets, &info->thread_list, list) {
20732073
int sz;
20742074

2075-
sz = elf_dump_thread_status(siginfo->si_signo, ets);
2075+
sz = elf_dump_thread_status(cprm->siginfo->si_signo, ets);
20762076
info->thread_status_size += sz;
20772077
}
20782078
/* now collect the dump for the current */
20792079
memset(info->prstatus, 0, sizeof(*info->prstatus));
2080-
fill_prstatus(&info->prstatus->common, current, siginfo->si_signo);
2081-
elf_core_copy_regs(&info->prstatus->pr_reg, regs);
2080+
fill_prstatus(&info->prstatus->common, current, cprm->siginfo->si_signo);
2081+
elf_core_copy_regs(&info->prstatus->pr_reg, cprm->regs);
20822082

20832083
/* Set up header */
20842084
fill_elf_header(elf, phdrs, ELF_ARCH, ELF_CORE_EFLAGS);
@@ -2094,18 +2094,18 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
20942094
fill_note(info->notes + 1, "CORE", NT_PRPSINFO,
20952095
sizeof(*info->psinfo), info->psinfo);
20962096

2097-
fill_siginfo_note(info->notes + 2, &info->csigdata, siginfo);
2097+
fill_siginfo_note(info->notes + 2, &info->csigdata, cprm->siginfo);
20982098
fill_auxv_note(info->notes + 3, current->mm);
20992099
info->numnote = 4;
21002100

2101-
if (fill_files_note(info->notes + info->numnote) == 0) {
2101+
if (fill_files_note(info->notes + info->numnote, cprm) == 0) {
21022102
info->notes_files = info->notes + info->numnote;
21032103
info->numnote++;
21042104
}
21052105

21062106
/* Try to dump the FPU. */
2107-
info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs,
2108-
info->fpu);
2107+
info->prstatus->pr_fpvalid =
2108+
elf_core_copy_task_fpregs(current, cprm->regs, info->fpu);
21092109
if (info->prstatus->pr_fpvalid)
21102110
fill_note(info->notes + info->numnote++,
21112111
"CORE", NT_PRFPREG, sizeof(*info->fpu), info->fpu);
@@ -2191,25 +2191,20 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
21912191
static int elf_core_dump(struct coredump_params *cprm)
21922192
{
21932193
int has_dumped = 0;
2194-
int vma_count, segs, i;
2195-
size_t vma_data_size;
2194+
int segs, i;
21962195
struct elfhdr elf;
21972196
loff_t offset = 0, dataoff;
21982197
struct elf_note_info info = { };
21992198
struct elf_phdr *phdr4note = NULL;
22002199
struct elf_shdr *shdr4extnum = NULL;
22012200
Elf_Half e_phnum;
22022201
elf_addr_t e_shoff;
2203-
struct core_vma_metadata *vma_meta;
2204-
2205-
if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size))
2206-
return 0;
22072202

22082203
/*
22092204
* The number of segs are recored into ELF header as 16bit value.
22102205
* Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
22112206
*/
2212-
segs = vma_count + elf_core_extra_phdrs();
2207+
segs = cprm->vma_count + elf_core_extra_phdrs();
22132208

22142209
/* for notes section */
22152210
segs++;
@@ -2223,7 +2218,7 @@ static int elf_core_dump(struct coredump_params *cprm)
22232218
* Collect all the non-memory information about the process for the
22242219
* notes. This also sets up the file header.
22252220
*/
2226-
if (!fill_note_info(&elf, e_phnum, &info, cprm->siginfo, cprm->regs))
2221+
if (!fill_note_info(&elf, e_phnum, &info, cprm))
22272222
goto end_coredump;
22282223

22292224
has_dumped = 1;
@@ -2248,7 +2243,7 @@ static int elf_core_dump(struct coredump_params *cprm)
22482243

22492244
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
22502245

2251-
offset += vma_data_size;
2246+
offset += cprm->vma_data_size;
22522247
offset += elf_core_extra_data_size();
22532248
e_shoff = offset;
22542249

@@ -2268,8 +2263,8 @@ static int elf_core_dump(struct coredump_params *cprm)
22682263
goto end_coredump;
22692264

22702265
/* Write program headers for segments dump */
2271-
for (i = 0; i < vma_count; i++) {
2272-
struct core_vma_metadata *meta = vma_meta + i;
2266+
for (i = 0; i < cprm->vma_count; i++) {
2267+
struct core_vma_metadata *meta = cprm->vma_meta + i;
22732268
struct elf_phdr phdr;
22742269

22752270
phdr.p_type = PT_LOAD;
@@ -2306,8 +2301,8 @@ static int elf_core_dump(struct coredump_params *cprm)
23062301
/* Align to page */
23072302
dump_skip_to(cprm, dataoff);
23082303

2309-
for (i = 0; i < vma_count; i++) {
2310-
struct core_vma_metadata *meta = vma_meta + i;
2304+
for (i = 0; i < cprm->vma_count; i++) {
2305+
struct core_vma_metadata *meta = cprm->vma_meta + i;
23112306

23122307
if (!dump_user_range(cprm, meta->start, meta->dump_size))
23132308
goto end_coredump;
@@ -2324,7 +2319,6 @@ static int elf_core_dump(struct coredump_params *cprm)
23242319
end_coredump:
23252320
free_note_info(&info);
23262321
kfree(shdr4extnum);
2327-
kvfree(vma_meta);
23282322
kfree(phdr4note);
23292323
return has_dumped;
23302324
}

fs/binfmt_elf_fdpic.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,7 +1465,7 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm,
14651465
static int elf_fdpic_core_dump(struct coredump_params *cprm)
14661466
{
14671467
int has_dumped = 0;
1468-
int vma_count, segs;
1468+
int segs;
14691469
int i;
14701470
struct elfhdr *elf = NULL;
14711471
loff_t offset = 0, dataoff;
@@ -1480,8 +1480,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
14801480
elf_addr_t e_shoff;
14811481
struct core_thread *ct;
14821482
struct elf_thread_status *tmp;
1483-
struct core_vma_metadata *vma_meta = NULL;
1484-
size_t vma_data_size;
14851483

14861484
/* alloc memory for large data structures: too large to be on stack */
14871485
elf = kmalloc(sizeof(*elf), GFP_KERNEL);
@@ -1491,9 +1489,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
14911489
if (!psinfo)
14921490
goto end_coredump;
14931491

1494-
if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size))
1495-
goto end_coredump;
1496-
14971492
for (ct = current->signal->core_state->dumper.next;
14981493
ct; ct = ct->next) {
14991494
tmp = elf_dump_thread_status(cprm->siginfo->si_signo,
@@ -1513,7 +1508,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
15131508
tmp->next = thread_list;
15141509
thread_list = tmp;
15151510

1516-
segs = vma_count + elf_core_extra_phdrs();
1511+
segs = cprm->vma_count + elf_core_extra_phdrs();
15171512

15181513
/* for notes section */
15191514
segs++;
@@ -1558,7 +1553,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
15581553
/* Page-align dumped data */
15591554
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
15601555

1561-
offset += vma_data_size;
1556+
offset += cprm->vma_data_size;
15621557
offset += elf_core_extra_data_size();
15631558
e_shoff = offset;
15641559

@@ -1578,8 +1573,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
15781573
goto end_coredump;
15791574

15801575
/* write program headers for segments dump */
1581-
for (i = 0; i < vma_count; i++) {
1582-
struct core_vma_metadata *meta = vma_meta + i;
1576+
for (i = 0; i < cprm->vma_count; i++) {
1577+
struct core_vma_metadata *meta = cprm->vma_meta + i;
15831578
struct elf_phdr phdr;
15841579
size_t sz;
15851580

@@ -1628,7 +1623,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
16281623

16291624
dump_skip_to(cprm, dataoff);
16301625

1631-
if (!elf_fdpic_dump_segments(cprm, vma_meta, vma_count))
1626+
if (!elf_fdpic_dump_segments(cprm, cprm->vma_meta, cprm->vma_count))
16321627
goto end_coredump;
16331628

16341629
if (!elf_core_write_extra_data(cprm))
@@ -1652,7 +1647,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
16521647
thread_list = thread_list->next;
16531648
kfree(tmp);
16541649
}
1655-
kvfree(vma_meta);
16561650
kfree(phdr4note);
16571651
kfree(elf);
16581652
kfree(psinfo);

fs/binfmt_flat.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <linux/flat.h>
3838
#include <linux/uaccess.h>
3939
#include <linux/vmalloc.h>
40+
#include <linux/coredump.h>
4041

4142
#include <asm/byteorder.h>
4243
#include <asm/unaligned.h>
@@ -97,7 +98,9 @@ static int load_flat_shared_library(int id, struct lib_info *p);
9798
#endif
9899

99100
static int load_flat_binary(struct linux_binprm *);
101+
#ifdef CONFIG_COREDUMP
100102
static int flat_core_dump(struct coredump_params *cprm);
103+
#endif
101104

102105
static struct linux_binfmt flat_format = {
103106
.module = THIS_MODULE,
@@ -114,12 +117,14 @@ static struct linux_binfmt flat_format = {
114117
* Currently only a stub-function.
115118
*/
116119

120+
#ifdef CONFIG_COREDUMP
117121
static int flat_core_dump(struct coredump_params *cprm)
118122
{
119123
pr_warn("Process %s:%d received signr %d and should have core dumped\n",
120124
current->comm, current->pid, cprm->siginfo->si_signo);
121125
return 1;
122126
}
127+
#endif
123128

124129
/****************************************************************************/
125130
/*

0 commit comments

Comments
 (0)