Date: Sun, 9 Jun 2019 23:15:57 -0700 From: Mark Millard <marklmi@yahoo.com> To: FreeBSD Hackers <freebsd-hackers@freebsd.org>, freeBSD PowerPC ML <freebsd-ppc@freebsd.org> Subject: kern_execve using vm_page_zero_invalid but not vm_page_set_validclean to load /sbin/init ? Message-ID: <1464D960-A1D6-404A-BB10-E615E2D14C1D@yahoo.com>
next in thread | raw e-mail | index | archive | help
This leads up to questioning if .sbss and .bss in /sbin/init are always correctly zeroed. But I may have missed something in the sequencing. (The code is not familiar material.) If I've tracked it down right: sys/kern/kern_exec.c uses kern_execve top deal with starting up /sbin/init. kern_execve uses do_execve. do_execve uses: /* * Each of the items is a pointer to a `const struct execsw', hence the * double pointer here. */ static const struct execsw **execsw; . . . /* * Loop through the list of image activators, calling each = one. * An activator returns -1 if there is no match, 0 on = success, * and an error otherwise. */ for (i =3D 0; error =3D=3D -1 && execsw[i]; ++i) { if (execsw[i]->ex_imgact =3D=3D NULL || execsw[i]->ex_imgact =3D=3D img_first) { continue; } error =3D (*execsw[i]->ex_imgact)(imgp); } /usr/src/sys/kern/imgact_elf.c has: /* * Tell kern_execve.c about it, with a little help from the linker. */ static struct execsw __elfN(execsw) =3D { .ex_imgact =3D __CONCAT(exec_, __elfN(imgact)), .ex_name =3D __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) }; EXEC_SET(__CONCAT(elf, __ELF_WORD_SIZE), __elfN(execsw)); __CONCAT(exec_, __elfN(imgact)) uses __elfN(load_sections) . __elfN(load_sections) uses __elfN(load_section). __elfN(load_section) uses vm_imgact_map_page to set up for its copyout. This appears to be how the FileSiz (not including .sbss or .bss) vs. MemSiz (including .sbss and .bss) is handled (attempted?). vm_imgact_map_page uses vm_imgact_hold_page. vm_imgact_hold_page uses vm_pager_get_pages. vm_pager_get_pages uses vm_page_zero_invalid to "Zero out partially filled data". But vm_page_zero_invalid does not zero every "invalid" byte but works in terms of units of DEV_BSIZE : void vm_page_zero_invalid(vm_page_t m, boolean_t setvalid) { int b; int i; VM_OBJECT_ASSERT_WLOCKED(m->object); /* * Scan the valid bits looking for invalid sections that * must be zeroed. Invalid sub-DEV_BSIZE'd areas ( where the * valid bit may be set ) have already been zeroed by * vm_page_set_validclean(). */ for (b =3D i =3D 0; i <=3D PAGE_SIZE / DEV_BSIZE; ++i) { if (i =3D=3D (PAGE_SIZE / DEV_BSIZE) || (m->valid & ((vm_page_bits_t)1 << i))) { if (i > b) { pmap_zero_page_area(m, b << DEV_BSHIFT, (i - b) << = DEV_BSHIFT); } b =3D i + 1; } } /* * setvalid is TRUE when we can safely set the zero'd areas * as being valid. We can do this if there are no cache = consistancy * issues. e.g. it is ok to do with UFS, but not ok to do with = NFS. */ if (setvalid) m->valid =3D VM_PAGE_BITS_ALL; } The comment indicates that areas of "sub-DEV_BSIZE" should have been handled previously by vm_page_set_validclean . But no part of the sequence appears to use vm_page_set_validclean . So, if, say, char**environ ends up at the start of .sbss consistently, does environ always end up zeroed independently of FileSz for the PT_LOAD that spans them? The following is not necessarily an example of problematical figures but is just for showing an example structure of what FileSiz covers vs. MemSiz for PT_LOAD's that involve .sbss and .bss : Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg = Align LOAD 0x000000 0x01800000 0x01800000 0x1222dc 0x1222dc R E = 0x10000 LOAD 0x123000 0x01933000 0x01933000 0x0618c 0x32e88 RWE = 0x10000 NOTE 0x0000d4 0x018000d4 0x018000d4 0x00048 0x00048 R 0x4 TLS 0x123000 0x01933000 0x01933000 0x00b10 0x00b1d R 0x10 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 Section to Segment mapping: Segment Sections... 00 .note.tag .init .text .fini .rodata .eh_frame=20 01 .tdata .tbss .init_array .fini_array .ctors .dtors .jcr = .data.rel.ro .data .got .sbss .bss=20 02 .note.tag=20 03 .tdata .tbss=20 04 =20 There are 24 section headers, starting at offset 0x14eb20: Section Headers: [Nr] Name Type Addr Off Size ES Flg = Lk Inf Al [ 0] NULL 00000000 000000 000000 00 = 0 0 0 [ 1] .note.tag NOTE 018000d4 0000d4 000048 00 A = 0 0 4 [ 2] .init PROGBITS 0180011c 00011c 000034 00 AX = 0 0 4 [ 3] .text PROGBITS 01800150 000150 111e14 00 AX = 0 0 16 [ 4] .fini PROGBITS 01911f64 111f64 000030 00 AX = 0 0 4 [ 5] .rodata PROGBITS 01911fc0 111fc0 010318 00 A = 0 0 64 [ 6] .eh_frame PROGBITS 019222d8 1222d8 000004 00 A = 0 0 4 [ 7] .tdata PROGBITS 01933000 123000 000b10 00 WAT = 0 0 16 [ 8] .tbss NOBITS 01933b10 123b10 00000d 00 WAT = 0 0 4 [ 9] .init_array INIT_ARRAY 01933b10 123b10 000008 04 WA = 0 0 4 [10] .fini_array FINI_ARRAY 01933b18 123b18 000004 04 WA = 0 0 4 [11] .ctors PROGBITS 01933b1c 123b1c 000008 00 WA = 0 0 4 [12] .dtors PROGBITS 01933b24 123b24 000008 00 WA = 0 0 4 [13] .jcr PROGBITS 01933b2c 123b2c 000004 00 WA = 0 0 4 [14] .data.rel.ro PROGBITS 01933b30 123b30 002ee4 00 WA = 0 0 4 [15] .data PROGBITS 01936a18 126a18 002763 00 WA = 0 0 8 [16] .got PROGBITS 0193917c 12917c 000010 04 WAX = 0 0 4 [17] .sbss NOBITS 0193918c 12918c 0000b0 00 WA = 0 0 4 [18] .bss NOBITS 01939240 12918c 02cc48 00 WA = 0 0 64 [19] .comment PROGBITS 00000000 12918c 0073d4 01 MS = 0 0 1 [20] .gnu_debuglink PROGBITS 00000000 130560 000010 00 = 0 0 4 [21] .symtab SYMTAB 00000000 130570 00fc40 10 = 22 1681 4 [22] .strtab STRTAB 00000000 1401b0 00e8b3 00 = 0 0 1 [23] .shstrtab STRTAB 00000000 14ea63 0000bc 00 = 0 0 1 . . . 2652: 000000000193918c 4 OBJECT GLOBAL DEFAULT 17 environ =3D=3D=3D Mark Millard marklmi at yahoo.com ( dsl-only.net went away in early 2018-Mar)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1464D960-A1D6-404A-BB10-E615E2D14C1D>