Merge 4e3c09e954 ("Merge tag 'v6.5-rc1-modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux") into android-mainline

Steps on the way to 6.5-rc1

Change-Id: I3b8dbac125725a81ce179004f1c820e86985ebc3
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2023-08-03 13:21:41 +00:00
8 changed files with 154 additions and 176 deletions
+3 -14
View File
@@ -65,6 +65,9 @@ static inline void *dereference_symbol_descriptor(void *ptr)
return ptr;
}
/* How and when do we show kallsyms values? */
extern bool kallsyms_show_value(const struct cred *cred);
#ifdef CONFIG_KALLSYMS
unsigned long kallsyms_sym_address(int idx);
int kallsyms_on_each_symbol(int (*fn)(void *, const char *, unsigned long),
@@ -93,10 +96,6 @@ extern int sprint_backtrace(char *buffer, unsigned long address);
extern int sprint_backtrace_build_id(char *buffer, unsigned long address);
int lookup_symbol_name(unsigned long addr, char *symname);
int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
/* How and when do we show kallsyms values? */
extern bool kallsyms_show_value(const struct cred *cred);
#else /* !CONFIG_KALLSYMS */
@@ -155,16 +154,6 @@ static inline int lookup_symbol_name(unsigned long addr, char *symname)
return -ERANGE;
}
static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name)
{
return -ERANGE;
}
static inline bool kallsyms_show_value(const struct cred *cred)
{
return false;
}
static inline int kallsyms_on_each_symbol(int (*fn)(void *, const char *, unsigned long),
void *data)
{
-9
View File
@@ -971,15 +971,6 @@ static inline int lookup_module_symbol_name(unsigned long addr, char *symname)
return -ERANGE;
}
static inline int lookup_module_symbol_attrs(unsigned long addr,
unsigned long *size,
unsigned long *offset,
char *modname,
char *name)
{
return -ERANGE;
}
static inline int module_get_kallsym(unsigned int symnum, unsigned long *value,
char *type, char *name,
char *module_name, int *exported)
+1 -1
View File
@@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o \
extable.o params.o \
kthread.o sys_ni.o nsproxy.o \
notifier.o ksysfs.o cred.o reboot.o \
async.o range.o smpboot.o ucount.o regset.o
async.o range.o smpboot.o ucount.o regset.o ksyms_common.o
obj-$(CONFIG_USERMODE_DRIVER) += usermode_driver.o
obj-$(CONFIG_MULTIUSER) += groups.o
+1 -90
View File
@@ -484,34 +484,6 @@ found:
return 0;
}
int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
unsigned long *offset, char *modname, char *name)
{
int res;
name[0] = '\0';
name[KSYM_NAME_LEN - 1] = '\0';
if (is_ksym_addr(addr)) {
unsigned long pos;
pos = get_symbol_pos(addr, size, offset);
/* Grab name */
kallsyms_expand_symbol(get_symbol_offset(pos),
name, KSYM_NAME_LEN);
modname[0] = '\0';
goto found;
}
/* See if it's in a module. */
res = lookup_module_symbol_attrs(addr, size, offset, modname, name);
if (res)
return res;
found:
cleanup_symbol_name(name);
return 0;
}
/* Look up a kernel symbol and return it in a text buffer. */
static int __sprint_symbol(char *buffer, unsigned long address,
int symbol_offset, int add_offset, int add_buildid)
@@ -646,7 +618,6 @@ int sprint_backtrace_build_id(char *buffer, unsigned long address)
/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
struct kallsym_iter {
loff_t pos;
loff_t pos_arch_end;
loff_t pos_mod_end;
loff_t pos_ftrace_mod_end;
loff_t pos_bpf_end;
@@ -659,29 +630,9 @@ struct kallsym_iter {
int show_value;
};
int __weak arch_get_kallsym(unsigned int symnum, unsigned long *value,
char *type, char *name)
{
return -EINVAL;
}
static int get_ksymbol_arch(struct kallsym_iter *iter)
{
int ret = arch_get_kallsym(iter->pos - kallsyms_num_syms,
&iter->value, &iter->type,
iter->name);
if (ret < 0) {
iter->pos_arch_end = iter->pos;
return 0;
}
return 1;
}
static int get_ksymbol_mod(struct kallsym_iter *iter)
{
int ret = module_get_kallsym(iter->pos - iter->pos_arch_end,
int ret = module_get_kallsym(iter->pos - kallsyms_num_syms,
&iter->value, &iter->type,
iter->name, iter->module_name,
&iter->exported);
@@ -764,7 +715,6 @@ static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
iter->nameoff = get_symbol_offset(new_pos);
iter->pos = new_pos;
if (new_pos == 0) {
iter->pos_arch_end = 0;
iter->pos_mod_end = 0;
iter->pos_ftrace_mod_end = 0;
iter->pos_bpf_end = 0;
@@ -780,10 +730,6 @@ static int update_iter_mod(struct kallsym_iter *iter, loff_t pos)
{
iter->pos = pos;
if ((!iter->pos_arch_end || iter->pos_arch_end > pos) &&
get_ksymbol_arch(iter))
return 1;
if ((!iter->pos_mod_end || iter->pos_mod_end > pos) &&
get_ksymbol_mod(iter))
return 1;
@@ -961,41 +907,6 @@ late_initcall(bpf_ksym_iter_register);
#endif /* CONFIG_BPF_SYSCALL */
static inline int kallsyms_for_perf(void)
{
#ifdef CONFIG_PERF_EVENTS
extern int sysctl_perf_event_paranoid;
if (sysctl_perf_event_paranoid <= 1)
return 1;
#endif
return 0;
}
/*
* We show kallsyms information even to normal users if we've enabled
* kernel profiling and are explicitly not paranoid (so kptr_restrict
* is clear, and sysctl_perf_event_paranoid isn't set).
*
* Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
* block even that).
*/
bool kallsyms_show_value(const struct cred *cred)
{
switch (kptr_restrict) {
case 0:
if (kallsyms_for_perf())
return true;
fallthrough;
case 1:
if (security_capable(cred, &init_user_ns, CAP_SYSLOG,
CAP_OPT_NOAUDIT) == 0)
return true;
fallthrough;
default:
return false;
}
}
static int kallsyms_open(struct inode *inode, struct file *file)
{
/*
+43
View File
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* ksyms_common.c: A split of kernel/kallsyms.c
* Contains a few generic function definations independent of config KALLSYMS.
*/
#include <linux/kallsyms.h>
#include <linux/security.h>
static inline int kallsyms_for_perf(void)
{
#ifdef CONFIG_PERF_EVENTS
extern int sysctl_perf_event_paranoid;
if (sysctl_perf_event_paranoid <= 1)
return 1;
#endif
return 0;
}
/*
* We show kallsyms information even to normal users if we've enabled
* kernel profiling and are explicitly not paranoid (so kptr_restrict
* is clear, and sysctl_perf_event_paranoid isn't set).
*
* Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
* block even that).
*/
bool kallsyms_show_value(const struct cred *cred)
{
switch (kptr_restrict) {
case 0:
if (kallsyms_for_perf())
return true;
fallthrough;
case 1:
if (security_capable(cred, &init_user_ns, CAP_SYSLOG,
CAP_OPT_NOAUDIT) == 0)
return true;
fallthrough;
default:
return false;
}
}
-28
View File
@@ -381,34 +381,6 @@ out:
return -ERANGE;
}
int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size,
unsigned long *offset, char *modname, char *name)
{
struct module *mod;
preempt_disable();
list_for_each_entry_rcu(mod, &modules, list) {
if (mod->state == MODULE_STATE_UNFORMED)
continue;
if (within_module(addr, mod)) {
const char *sym;
sym = find_kallsyms_symbol(mod, addr, size, offset);
if (!sym)
goto out;
if (modname)
strscpy(modname, mod->name, MODULE_NAME_LEN);
if (name)
strscpy(name, sym, KSYM_NAME_LEN);
preempt_enable();
return 0;
}
}
out:
preempt_enable();
return -ERANGE;
}
int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
char *name, char *module_name, int *exported)
{
+105 -31
View File
@@ -821,10 +821,8 @@ static struct module_attribute modinfo_refcnt =
void __module_get(struct module *module)
{
if (module) {
preempt_disable();
atomic_inc(&module->refcnt);
trace_module_get(module, _RET_IP_);
preempt_enable();
}
}
EXPORT_SYMBOL(__module_get);
@@ -834,15 +832,12 @@ bool try_module_get(struct module *module)
bool ret = true;
if (module) {
preempt_disable();
/* Note: here, we can fail to get a reference */
if (likely(module_is_live(module) &&
atomic_inc_not_zero(&module->refcnt) != 0))
trace_module_get(module, _RET_IP_);
else
ret = false;
preempt_enable();
}
return ret;
}
@@ -853,11 +848,9 @@ void module_put(struct module *module)
int ret;
if (module) {
preempt_disable();
ret = atomic_dec_if_positive(&module->refcnt);
WARN_ON(ret < 0); /* Failed to put refcount */
trace_module_put(module, _RET_IP_);
preempt_enable();
}
}
EXPORT_SYMBOL(module_put);
@@ -3090,12 +3083,111 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
return load_module(&info, uargs, 0);
}
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
struct idempotent {
const void *cookie;
struct hlist_node entry;
struct completion complete;
int ret;
};
#define IDEM_HASH_BITS 8
static struct hlist_head idem_hash[1 << IDEM_HASH_BITS];
static DEFINE_SPINLOCK(idem_lock);
static bool idempotent(struct idempotent *u, const void *cookie)
{
int hash = hash_ptr(cookie, IDEM_HASH_BITS);
struct hlist_head *head = idem_hash + hash;
struct idempotent *existing;
bool first;
u->ret = 0;
u->cookie = cookie;
init_completion(&u->complete);
spin_lock(&idem_lock);
first = true;
hlist_for_each_entry(existing, head, entry) {
if (existing->cookie != cookie)
continue;
first = false;
break;
}
hlist_add_head(&u->entry, idem_hash + hash);
spin_unlock(&idem_lock);
return !first;
}
/*
* We were the first one with 'cookie' on the list, and we ended
* up completing the operation. We now need to walk the list,
* remove everybody - which includes ourselves - fill in the return
* value, and then complete the operation.
*/
static void idempotent_complete(struct idempotent *u, int ret)
{
const void *cookie = u->cookie;
int hash = hash_ptr(cookie, IDEM_HASH_BITS);
struct hlist_head *head = idem_hash + hash;
struct hlist_node *next;
struct idempotent *pos;
spin_lock(&idem_lock);
hlist_for_each_entry_safe(pos, next, head, entry) {
if (pos->cookie != cookie)
continue;
hlist_del(&pos->entry);
pos->ret = ret;
complete(&pos->complete);
}
spin_unlock(&idem_lock);
}
static int init_module_from_file(struct file *f, const char __user * uargs, int flags)
{
struct idempotent idem;
struct load_info info = { };
void *buf = NULL;
int len;
int len, ret;
if (!f || !(f->f_mode & FMODE_READ))
return -EBADF;
if (idempotent(&idem, file_inode(f))) {
wait_for_completion(&idem.complete);
return idem.ret;
}
len = kernel_read_file(f, 0, &buf, INT_MAX, NULL, READING_MODULE);
if (len < 0) {
mod_stat_inc(&failed_kreads);
mod_stat_add_long(len, &invalid_kread_bytes);
return len;
}
if (flags & MODULE_INIT_COMPRESSED_FILE) {
int err = module_decompress(&info, buf, len);
vfree(buf); /* compressed data is no longer needed */
if (err) {
mod_stat_inc(&failed_decompress);
mod_stat_add_long(len, &invalid_decompress_bytes);
return err;
}
} else {
info.hdr = buf;
info.len = len;
}
ret = load_module(&info, uargs, flags);
idempotent_complete(&idem, ret);
return ret;
}
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
{
int err;
struct fd f;
err = may_init_module();
if (err)
@@ -3108,28 +3200,10 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
|MODULE_INIT_COMPRESSED_FILE))
return -EINVAL;
len = kernel_read_file_from_fd(fd, 0, &buf, INT_MAX, NULL,
READING_MODULE);
if (len < 0) {
mod_stat_inc(&failed_kreads);
mod_stat_add_long(len, &invalid_kread_bytes);
return len;
}
if (flags & MODULE_INIT_COMPRESSED_FILE) {
err = module_decompress(&info, buf, len);
vfree(buf); /* compressed data is no longer needed */
if (err) {
mod_stat_inc(&failed_decompress);
mod_stat_add_long(len, &invalid_decompress_bytes);
return err;
}
} else {
info.hdr = buf;
info.len = len;
}
return load_module(&info, uargs, flags);
f = fdget(fd);
err = init_module_from_file(f.file, uargs, flags);
fdput(f);
return err;
}
/* Keep in sync with MODULE_FLAGS_BUF_SIZE !!! */
@@ -59,9 +59,7 @@ int dump_ksym(struct bpf_iter__ksym *ctx)
} else {
BPF_SEQ_PRINTF(seq, "0x%llx %c %s ", value, type, iter->name);
}
if (!iter->pos_arch_end || iter->pos_arch_end > iter->pos)
BPF_SEQ_PRINTF(seq, "CORE ");
else if (!iter->pos_mod_end || iter->pos_mod_end > iter->pos)
if (!iter->pos_mod_end || iter->pos_mod_end > iter->pos)
BPF_SEQ_PRINTF(seq, "MOD ");
else if (!iter->pos_ftrace_mod_end || iter->pos_ftrace_mod_end > iter->pos)
BPF_SEQ_PRINTF(seq, "FTRACE_MOD ");