Commit daa22f5a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'modules-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux

Pull modules updates from Luis Chamberlain:
 "Summary of the changes worth highlighting from most interesting to
  boring below:

   - Christoph Hellwig's symbol_get() fix to Nvidia's efforts to
     circumvent the protection he put in place in year 2020 to prevent
     proprietary modules from using GPL only symbols, and also ensuring
     proprietary modules which export symbols grandfather their taint.

     That was done through year 2020 commit 262e6ae7 ("modules:
     inherit TAINT_PROPRIETARY_MODULE"). Christoph's new fix is done by
     clarifing __symbol_get() was only ever intended to prevent module
     reference loops by Linux kernel modules and so making it only find
     symbols exported via EXPORT_SYMBOL_GPL(). The circumvention tactic
     used by Nvidia was to use symbol_get() to purposely swift through
     proprietary module symbols and completely bypass our traditional
     EXPORT_SYMBOL*() annotations and community agreed upon
     restrictions.

     A small set of preamble patches fix up a few symbols which just
     needed adjusting for this on two modules, the rtc ds1685 and the
     networking enetc module. Two other modules just needed some build
     fixing and removal of use of __symbol_get() as they can't ever be
     modular, as was done by Arnd on the ARM pxa module and Christoph
     did on the mmc au1xmmc driver.

     This is a good reminder to us that symbol_get() is just a hack to
     address things which should be fixed through Kconfig at build time
     as was done in the later patches, and so ultimately it should just
     go.

   - Extremely late minor fix for old module layout 055f23b7
     ("module: check for exit sections in layout_sections() instead of
     module_init_section()") by James Morse for arm64. Note that this
     layout thing is old, it is *not* Song Liu's commit ac3b4328
     ("module: replace module_layout with module_memory"). The issue
     however is very odd to run into and so there was no hurry to get
     this in fast.

   - Although the fix did not go through the modules tree I'd like to
     highlight the fix by Peter Zijlstra in commit 54097309
     ("x86/static_call: Fix __static_call_fixup()") now merged in your
     tree which came out of what was originally suspected to be a
     fallout of the the newer module layout changes by Song Liu commit
     ac3b4328 ("module: replace module_layout with module_memory")
     instead of module_init_section()"). Thanks to the report by
     Christian Bricart and the debugging by Song Liu & Peter that turned
     to be noted as a kernel regression in place since v5.19 through
     commit ee88d363 ("x86,static_call: Use alternative RET
     encoding").

     I highlight this to reflect and clarify that we haven't seen more
     fallout from ac3b4328 ("module: replace module_layout with
     module_memory").

   - RISC-V toolchain got mapping symbol support which prefix symbols
     with "$" to help with alignment considerations for disassembly.

     This is used to differentiate between incompatible instruction
     encodings when disassembling. RISC-V just matches what ARM/AARCH64
     did for alignment considerations and Palmer Dabbelt extended
     is_mapping_symbol() to accept these symbols for RISC-V. We already
     had support for this for all architectures but it also checked for
     the second character, the RISC-V check Dabbelt added was just for
     the "$". After a bit of testing and fallout on linux-next and based
     on feedback from Masahiro Yamada it was decided to simplify the
     check and treat the first char "$" as unique for all architectures,
     and so we no make is_mapping_symbol() for all archs if the symbol
     starts with "$".

     The most relevant commit for this for RISC-V on binutils was:

       https://sourceware.org/pipermail/binutils/2021-July/117350.html

   - A late fix by Andrea Righi (today) to make module zstd
     decompression use vmalloc() instead of kmalloc() to account for
     large compressed modules. I suspect we'll see similar things for
     other decompression algorithms soon.

   - samples/hw_breakpoint minor fixes by Rong Tao, Arnd Bergmann and
     Chen Jiahao"

* tag 'modules-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux:
  module/decompress: use vmalloc() for zstd decompression workspace
  kallsyms: Add more debug output for selftest
  ARM: module: Use module_init_layout_section() to spot init sections
  arm64: module: Use module_init_layout_section() to spot init sections
  module: Expose module_init_layout_section()
  modules: only allow symbol_get of EXPORT_SYMBOL_GPL modules
  rtc: ds1685: use EXPORT_SYMBOL_GPL for ds1685_rtc_poweroff
  net: enetc: use EXPORT_SYMBOL_GPL for enetc_phc_index
  mmc: au1xmmc: force non-modular build and remove symbol_get usage
  ARM: pxa: remove use of symbol_get()
  samples/hw_breakpoint: mark sample_hbp as static
  samples/hw_breakpoint: fix building without module unloading
  samples/hw_breakpoint: Fix kernel BUG 'invalid opcode: 0000'
  modpost, kallsyms: Treat add '$'-prefixed symbols as mapping symbols
  kernel: params: Remove unnecessary ‘0’ values from err
  module: Ignore RISC-V mapping symbols too
parents d68b4b6f a419beac
......@@ -251,7 +251,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
/* sort by type and symbol index */
sort(rels, numrels, sizeof(Elf32_Rel), cmp_rel, NULL);
if (strncmp(secstrings + dstsec->sh_name, ".init", 5) != 0)
if (!module_init_layout_section(secstrings + dstsec->sh_name))
core_plts += count_plts(syms, dstsec->sh_addr, rels,
numrels, s->sh_info);
else
......
......@@ -216,8 +216,6 @@ void sharpsl_battery_kick(void)
{
schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
}
EXPORT_SYMBOL(sharpsl_battery_kick);
static void sharpsl_battery_thread(struct work_struct *private_)
{
......
......@@ -9,7 +9,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h> /* symbol_get ; symbol_put */
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/gpio_keys.h>
......@@ -518,17 +517,6 @@ static struct gpiod_lookup_table spitz_ads7846_gpio_table = {
},
};
static void spitz_bl_kick_battery(void)
{
void (*kick_batt)(void);
kick_batt = symbol_get(sharpsl_battery_kick);
if (kick_batt) {
kick_batt();
symbol_put(sharpsl_battery_kick);
}
}
static struct gpiod_lookup_table spitz_lcdcon_gpio_table = {
.dev_id = "spi2.1",
.table = {
......@@ -556,7 +544,7 @@ static struct corgi_lcd_platform_data spitz_lcdcon_info = {
.max_intensity = 0x2f,
.default_intensity = 0x1f,
.limit_mask = 0x0b,
.kick_battery = spitz_bl_kick_battery,
.kick_battery = sharpsl_battery_kick,
};
static struct spi_board_info spitz_spi_devices[] = {
......
......@@ -339,7 +339,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
if (nents)
sort(rels, nents, sizeof(Elf64_Rela), cmp_rela, NULL);
if (!str_has_prefix(secstrings + dstsec->sh_name, ".init"))
if (!module_init_layout_section(secstrings + dstsec->sh_name))
core_plts += count_plts(syms, rels, numrels,
sechdrs[i].sh_info, dstsec);
else
......
......@@ -14,7 +14,6 @@
#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
......@@ -167,12 +166,7 @@ static struct platform_device db1x00_audio_dev = {
static irqreturn_t db1100_mmc_cd(int irq, void *ptr)
{
void (*mmc_cd)(struct mmc_host *, unsigned long);
/* link against CONFIG_MMC=m */
mmc_cd = symbol_get(mmc_detect_change);
mmc_cd(ptr, msecs_to_jiffies(500));
symbol_put(mmc_detect_change);
mmc_detect_change(ptr, msecs_to_jiffies(500));
return IRQ_HANDLED;
}
......
......@@ -10,7 +10,6 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/leds.h>
......@@ -340,14 +339,7 @@ static irqreturn_t db1200_mmc_cd(int irq, void *ptr)
static irqreturn_t db1200_mmc_cdfn(int irq, void *ptr)
{
void (*mmc_cd)(struct mmc_host *, unsigned long);
/* link against CONFIG_MMC=m */
mmc_cd = symbol_get(mmc_detect_change);
if (mmc_cd) {
mmc_cd(ptr, msecs_to_jiffies(200));
symbol_put(mmc_detect_change);
}
mmc_detect_change(ptr, msecs_to_jiffies(200));
msleep(100); /* debounce */
if (irq == DB1200_SD0_INSERT_INT)
......@@ -431,14 +423,7 @@ static irqreturn_t pb1200_mmc1_cd(int irq, void *ptr)
static irqreturn_t pb1200_mmc1_cdfn(int irq, void *ptr)
{
void (*mmc_cd)(struct mmc_host *, unsigned long);
/* link against CONFIG_MMC=m */
mmc_cd = symbol_get(mmc_detect_change);
if (mmc_cd) {
mmc_cd(ptr, msecs_to_jiffies(200));
symbol_put(mmc_detect_change);
}
mmc_detect_change(ptr, msecs_to_jiffies(200));
msleep(100); /* debounce */
if (irq == PB1200_SD1_INSERT_INT)
......
......@@ -17,7 +17,6 @@
#include <linux/interrupt.h>
#include <linux/ata_platform.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/platnand.h>
#include <linux/platform_device.h>
......@@ -459,14 +458,7 @@ static irqreturn_t db1300_mmc_cd(int irq, void *ptr)
static irqreturn_t db1300_mmc_cdfn(int irq, void *ptr)
{
void (*mmc_cd)(struct mmc_host *, unsigned long);
/* link against CONFIG_MMC=m. We can only be called once MMC core has
* initialized the controller, so symbol_get() should always succeed.
*/
mmc_cd = symbol_get(mmc_detect_change);
mmc_cd(ptr, msecs_to_jiffies(200));
symbol_put(mmc_detect_change);
mmc_detect_change(ptr, msecs_to_jiffies(200));
msleep(100); /* debounce */
if (irq == DB1300_SD1_INSERT_INT)
......
......@@ -526,11 +526,12 @@ config MMC_ALCOR
of Alcor Micro PCI-E card reader
config MMC_AU1X
tristate "Alchemy AU1XX0 MMC Card Interface support"
bool "Alchemy AU1XX0 MMC Card Interface support"
depends on MIPS_ALCHEMY
depends on MMC=y
help
This selects the AMD Alchemy(R) Multimedia card interface.
If you have a Alchemy platform with a MMC slot, say Y or M here.
If you have a Alchemy platform with a MMC slot, say Y here.
If unsure, say N.
......
......@@ -8,7 +8,7 @@
#include "enetc.h"
int enetc_phc_index = -1;
EXPORT_SYMBOL(enetc_phc_index);
EXPORT_SYMBOL_GPL(enetc_phc_index);
static struct ptp_clock_info enetc_ptp_caps = {
.owner = THIS_MODULE,
......
......@@ -1432,7 +1432,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev)
unreachable();
}
}
EXPORT_SYMBOL(ds1685_rtc_poweroff);
EXPORT_SYMBOL_GPL(ds1685_rtc_poweroff);
/* ----------------------------------------------------------------------- */
......
......@@ -9,9 +9,7 @@ static inline int is_mapping_symbol(const char *str)
return true;
if (str[0] == 'L' && str[1] == '0')
return true;
return str[0] == '$' &&
(str[1] == 'a' || str[1] == 'd' || str[1] == 't' || str[1] == 'x')
&& (str[2] == '\0' || str[2] == '.');
return str[0] == '$';
}
#endif /* _LINUX_MODULE_SYMBOL_H */
......@@ -42,6 +42,11 @@ bool module_init_section(const char *name);
*/
bool module_exit_section(const char *name);
/* Describes whether within_module_init() will consider this an init section
* or not. This behaviour changes with CONFIG_MODULE_UNLOAD.
*/
bool module_init_layout_section(const char *sname);
/*
* Apply the given relocation to the (simplified) ELF. Return -error
* or 0.
......
......@@ -341,6 +341,7 @@ static int test_kallsyms_basic_function(void)
ret = lookup_symbol_name(addr, namebuf);
if (unlikely(ret)) {
namebuf[0] = 0;
pr_info("%d: lookup_symbol_name(%lx) failed\n", i, addr);
goto failed;
}
......@@ -367,8 +368,11 @@ static int test_kallsyms_basic_function(void)
if (stat->addr != stat2->addr ||
stat->real_cnt != stat2->real_cnt ||
memcmp(stat->addrs, stat2->addrs,
stat->save_cnt * sizeof(stat->addrs[0])))
stat->save_cnt * sizeof(stat->addrs[0]))) {
pr_info("%s: mismatch between kallsyms_on_each_symbol() and kallsyms_on_each_match_symbol()\n",
namebuf);
goto failed;
}
/*
* The average of random increments is 128, that is, one of
......@@ -379,15 +383,23 @@ static int test_kallsyms_basic_function(void)
}
/* Need to be found at least once */
if (!stat->real_cnt)
if (!stat->real_cnt) {
pr_info("%s: Never found\n", namebuf);
goto failed;
}
/*
* kallsyms_lookup_name() returns the address of the first
* symbol found and cannot be NULL.
*/
if (!lookup_addr || lookup_addr != stat->addrs[0])
if (!lookup_addr) {
pr_info("%s: NULL lookup_addr?!\n", namebuf);
goto failed;
}
if (lookup_addr != stat->addrs[0]) {
pr_info("%s: lookup_addr != stat->addrs[0]\n", namebuf);
goto failed;
}
/*
* If the addresses of all matching symbols are recorded, the
......@@ -399,8 +411,10 @@ static int test_kallsyms_basic_function(void)
break;
}
if (j == stat->save_cnt)
if (j == stat->save_cnt) {
pr_info("%s: j == save_cnt?!\n", namebuf);
goto failed;
}
}
}
......
......@@ -241,7 +241,7 @@ static ssize_t module_zstd_decompress(struct load_info *info,
}
wksp_size = zstd_dstream_workspace_bound(header.windowSize);
wksp = kmalloc(wksp_size, GFP_KERNEL);
wksp = vmalloc(wksp_size);
if (!wksp) {
retval = -ENOMEM;
goto out;
......@@ -284,7 +284,7 @@ static ssize_t module_zstd_decompress(struct load_info *info,
retval = new_size;
out:
kfree(wksp);
vfree(wksp);
return retval;
}
#else
......
......@@ -1295,12 +1295,20 @@ void *__symbol_get(const char *symbol)
};
preempt_disable();
if (!find_symbol(&fsa) || strong_try_module_get(fsa.owner)) {
preempt_enable();
return NULL;
if (!find_symbol(&fsa))
goto fail;
if (fsa.license != GPL_ONLY) {
pr_warn("failing symbol_get of non-GPLONLY symbol %s.\n",
symbol);
goto fail;
}
if (strong_try_module_get(fsa.owner))
goto fail;
preempt_enable();
return (void *)kernel_symbol_value(fsa.sym);
fail:
preempt_enable();
return NULL;
}
EXPORT_SYMBOL_GPL(__symbol_get);
......@@ -1484,7 +1492,7 @@ long module_get_offset_and_type(struct module *mod, enum mod_mem_type type,
return offset | mask;
}
static bool module_init_layout_section(const char *sname)
bool module_init_layout_section(const char *sname)
{
#ifndef CONFIG_MODULE_UNLOAD
if (module_exit_section(sname))
......
......@@ -331,7 +331,7 @@ EXPORT_SYMBOL(param_ops_bool);
int param_set_bool_enable_only(const char *val, const struct kernel_param *kp)
{
int err = 0;
int err;
bool new_value;
bool orig_value = *(bool *)kp->arg;
struct kernel_param dummy_kp = *kp;
......
......@@ -21,7 +21,7 @@
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
struct perf_event * __percpu *sample_hbp;
static struct perf_event * __percpu *sample_hbp;
static char ksym_name[KSYM_NAME_LEN] = "jiffies";
module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
......@@ -70,7 +70,9 @@ static int __init hw_break_module_init(void)
static void __exit hw_break_module_exit(void)
{
unregister_wide_hw_breakpoint(sample_hbp);
symbol_put(ksym_name);
#ifdef CONFIG_MODULE_UNLOAD
__symbol_put(ksym_name);
#endif
printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment