fs/proc/kcore.c

Source file repositories/reference/linux-study-clean/fs/proc/kcore.c

File Facts

System
Linux kernel
Corpus path
fs/proc/kcore.c
Extension
.c
Size
17850 bytes
Lines
743
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (copy_to_iter((char *)&ehdr + *fpos, tsz, iter) != tsz) {
			ret = -EFAULT;
			goto out;
		}

		buflen -= tsz;
		*fpos += tsz;
	}

	/* ELF program headers. */
	if (buflen && *fpos < phdrs_offset + kcore_phdrs_len) {
		struct elf_phdr *phdrs, *phdr;

		phdrs = kzalloc(kcore_phdrs_len, GFP_KERNEL);
		if (!phdrs) {
			ret = -ENOMEM;
			goto out;
		}

		phdrs[0].p_type = PT_NOTE;
		phdrs[0].p_offset = notes_offset;
		phdrs[0].p_filesz = kcore_notes_len;

		phdr = &phdrs[1];
		list_for_each_entry(m, &kclist_head, list) {
			phdr->p_type = PT_LOAD;
			phdr->p_flags = PF_R | PF_W | PF_X;
			phdr->p_offset = kc_vaddr_to_offset(m->addr)
					 + kcore_data_offset;
			phdr->p_vaddr = (size_t)m->addr;
			if (m->type == KCORE_RAM)
				phdr->p_paddr = __pa(m->addr);
			else if (m->type == KCORE_TEXT)
				phdr->p_paddr = __pa_symbol(m->addr);
			else
				phdr->p_paddr = (elf_addr_t)-1;
			phdr->p_filesz = phdr->p_memsz = m->size;
			phdr->p_align = PAGE_SIZE;
			phdr++;
		}

		tsz = min_t(size_t, buflen,
			    phdrs_offset + kcore_phdrs_len - *fpos);
		if (copy_to_iter((char *)phdrs + *fpos - phdrs_offset, tsz,
				 iter) != tsz) {
			kfree(phdrs);
			ret = -EFAULT;
			goto out;
		}
		kfree(phdrs);

		buflen -= tsz;
		*fpos += tsz;
	}

	/* ELF note segment. */
	if (buflen && *fpos < notes_offset + kcore_notes_len) {
		struct elf_prstatus prstatus = {};
		struct elf_prpsinfo prpsinfo = {
			.pr_sname = 'R',
			.pr_fname = "vmlinux",
		};
		char *notes;
		size_t i = 0;

		strscpy(prpsinfo.pr_psargs, saved_command_line,
			sizeof(prpsinfo.pr_psargs));

		notes = kzalloc(kcore_notes_len, GFP_KERNEL);
		if (!notes) {
			ret = -ENOMEM;
			goto out;
		}

		append_kcore_note(notes, &i, NN_PRSTATUS, NT_PRSTATUS, &prstatus,
				  sizeof(prstatus));
		append_kcore_note(notes, &i, NN_PRPSINFO, NT_PRPSINFO, &prpsinfo,
				  sizeof(prpsinfo));
		append_kcore_note(notes, &i, NN_TASKSTRUCT, NT_TASKSTRUCT, current,
				  arch_task_struct_size);
		/*
		 * vmcoreinfo_size is mostly constant after init time, but it
		 * can be changed by crash_save_vmcoreinfo(). Racing here with a
		 * panic on another CPU before the machine goes down is insanely
		 * unlikely, but it's better to not leave potential buffer
		 * overflows lying around, regardless.
		 */
		append_kcore_note(notes, &i, VMCOREINFO_NOTE_NAME, 0,
				  vmcoreinfo_data,
				  min(vmcoreinfo_size, kcore_notes_len - i));

Annotation

Implementation Notes