kern_execve using vm_page_zero_invalid but not vm_page_set_validclean to load /sbin/init ?
Mark Millard
marklmi at yahoo.com
Mon Jun 10 06:16:12 UTC 2019
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 = 0; error == -1 && execsw[i]; ++i) {
if (execsw[i]->ex_imgact == NULL ||
execsw[i]->ex_imgact == img_first) {
continue;
}
error = (*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) = {
.ex_imgact = __CONCAT(exec_, __elfN(imgact)),
.ex_name = __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 = i = 0; i <= PAGE_SIZE / DEV_BSIZE; ++i) {
if (i == (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 = 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 = 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
01 .tdata .tbss .init_array .fini_array .ctors .dtors .jcr .data.rel.ro .data .got .sbss .bss
02 .note.tag
03 .tdata .tbss
04
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
===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)
More information about the freebsd-ppc
mailing list