kernel/module/version.c

Source file repositories/reference/linux-study-clean/kernel/module/version.c

File Facts

System
Linux kernel
Corpus path
kernel/module/version.c
Extension
.c
Size
3721 bytes
Lines
147
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: exported/initcall integration point
Status
integration 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

for_each_modversion_info_ext(version_ext, info) {
			if (strcmp(version_ext.name, symname) != 0)
				continue;
			if (*version_ext.crc == *crc)
				return 1;
			pr_debug("Found checksum %X vs module %X\n",
				 *crc, *version_ext.crc);
			goto bad_version;
		}
		pr_warn_once("%s: no extended symbol version for %s\n",
			     info->name, symname);
		return 1;
	}

	/* No versions at all?  modprobe --force does this. */
	if (versindex == 0)
		return try_to_force_load(mod, symname) == 0;

	versions = (void *)sechdrs[versindex].sh_addr;
	num_versions = sechdrs[versindex].sh_size
		/ sizeof(struct modversion_info);

	for (i = 0; i < num_versions; i++) {
		u32 crcval;

		if (strcmp(versions[i].name, symname) != 0)
			continue;

		crcval = *crc;
		if (versions[i].crc == crcval)
			return 1;
		pr_debug("Found checksum %X vs module %lX\n",
			 crcval, versions[i].crc);
		goto bad_version;
	}

	/* Broken toolchain. Warn once, then let it go.. */
	pr_warn_once("%s: no symbol version for %s\n", info->name, symname);
	return 1;

bad_version:
	pr_warn("%s: disagrees about version of symbol %s\n", info->name, symname);
	return 0;
}

int check_modstruct_version(const struct load_info *info,
			    struct module *mod)
{
	struct find_symbol_arg fsa = {
		.name	= "module_layout",
		.gplok	= true,
	};
	bool have_symbol;

	/*
	 * Since this should be found in kernel (which can't be removed), no
	 * locking is necessary. Regardless use a RCU read section to keep
	 * lockdep happy.
	 */
	scoped_guard(rcu)
		have_symbol = find_symbol(&fsa);
	BUG_ON(!have_symbol);

	return check_version(info, "module_layout", mod, fsa.crc);
}

/* First part is kernel version, which we ignore if module has crcs. */
int same_magic(const char *amagic, const char *bmagic,
	       bool has_crcs)
{
	if (has_crcs) {
		amagic += strcspn(amagic, " ");
		bmagic += strcspn(bmagic, " ");
	}
	return strcmp(amagic, bmagic) == 0;
}

void modversion_ext_start(const struct load_info *info,
			  struct modversion_info_ext *start)
{
	unsigned int crc_idx = info->index.vers_ext_crc;
	unsigned int name_idx = info->index.vers_ext_name;
	Elf_Shdr *sechdrs = info->sechdrs;

	/*
	 * Both of these fields are needed for this to be useful
	 * Any future fields should be initialized to NULL if absent.
	 */
	if (crc_idx == 0 || name_idx == 0) {
		start->remaining = 0;

Annotation

Implementation Notes