Commit ce69fb3b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'kallsyms_show_value-v5.8-rc5' of...

Merge tag 'kallsyms_show_value-v5.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull kallsyms fix from Kees Cook:
 "Refactor kallsyms_show_value() users for correct cred.

  I'm not delighted by the timing of getting these changes to you, but
  it does fix a handful of kernel address exposures, and no one has
  screamed yet at the patches.

  Several users of kallsyms_show_value() were performing checks not
  during "open". Refactor everything needed to gain proper checks
  against file->f_cred for modules, kprobes, and bpf"

* tag 'kallsyms_show_value-v5.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  selftests: kmod: Add module address visibility test
  bpf: Check correct cred for CAP_SYSLOG in bpf_dump_raw_ok()
  kprobes: Do not expose probe addresses to non-CAP_SYSLOG
  module: Do not expose section addresses to non-CAP_SYSLOG
  module: Refactor section attr into bin attribute
  kallsyms: Refactor kallsyms_show_value() to take cred
parents 0bddd227 2c795839
...@@ -884,12 +884,12 @@ void bpf_jit_compile(struct bpf_prog *prog); ...@@ -884,12 +884,12 @@ void bpf_jit_compile(struct bpf_prog *prog);
bool bpf_jit_needs_zext(void); bool bpf_jit_needs_zext(void);
bool bpf_helper_changes_pkt_data(void *func); bool bpf_helper_changes_pkt_data(void *func);
static inline bool bpf_dump_raw_ok(void) static inline bool bpf_dump_raw_ok(const struct cred *cred)
{ {
/* Reconstruction of call-sites is dependent on kallsyms, /* Reconstruction of call-sites is dependent on kallsyms,
* thus make dump the same restriction. * thus make dump the same restriction.
*/ */
return kallsyms_show_value() == 1; return kallsyms_show_value(cred);
} }
struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \ #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1) 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
struct cred;
struct module; struct module;
static inline int is_kernel_inittext(unsigned long addr) static inline int is_kernel_inittext(unsigned long addr)
...@@ -98,7 +99,7 @@ int lookup_symbol_name(unsigned long addr, char *symname); ...@@ -98,7 +99,7 @@ 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); 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? */ /* How and when do we show kallsyms values? */
extern int kallsyms_show_value(void); extern bool kallsyms_show_value(const struct cred *cred);
#else /* !CONFIG_KALLSYMS */ #else /* !CONFIG_KALLSYMS */
...@@ -158,7 +159,7 @@ static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, u ...@@ -158,7 +159,7 @@ static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, u
return -ERANGE; return -ERANGE;
} }
static inline int kallsyms_show_value(void) static inline bool kallsyms_show_value(const struct cred *cred)
{ {
return false; return false;
} }
......
...@@ -3139,7 +3139,8 @@ static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog, ...@@ -3139,7 +3139,8 @@ static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog,
return NULL; return NULL;
} }
static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog) static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog,
const struct cred *f_cred)
{ {
const struct bpf_map *map; const struct bpf_map *map;
struct bpf_insn *insns; struct bpf_insn *insns;
...@@ -3165,7 +3166,7 @@ static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog) ...@@ -3165,7 +3166,7 @@ static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog)
code == (BPF_JMP | BPF_CALL_ARGS)) { code == (BPF_JMP | BPF_CALL_ARGS)) {
if (code == (BPF_JMP | BPF_CALL_ARGS)) if (code == (BPF_JMP | BPF_CALL_ARGS))
insns[i].code = BPF_JMP | BPF_CALL; insns[i].code = BPF_JMP | BPF_CALL;
if (!bpf_dump_raw_ok()) if (!bpf_dump_raw_ok(f_cred))
insns[i].imm = 0; insns[i].imm = 0;
continue; continue;
} }
...@@ -3221,7 +3222,8 @@ static int set_info_rec_size(struct bpf_prog_info *info) ...@@ -3221,7 +3222,8 @@ static int set_info_rec_size(struct bpf_prog_info *info)
return 0; return 0;
} }
static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, static int bpf_prog_get_info_by_fd(struct file *file,
struct bpf_prog *prog,
const union bpf_attr *attr, const union bpf_attr *attr,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
...@@ -3290,11 +3292,11 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, ...@@ -3290,11 +3292,11 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
struct bpf_insn *insns_sanitized; struct bpf_insn *insns_sanitized;
bool fault; bool fault;
if (prog->blinded && !bpf_dump_raw_ok()) { if (prog->blinded && !bpf_dump_raw_ok(file->f_cred)) {
info.xlated_prog_insns = 0; info.xlated_prog_insns = 0;
goto done; goto done;
} }
insns_sanitized = bpf_insn_prepare_dump(prog); insns_sanitized = bpf_insn_prepare_dump(prog, file->f_cred);
if (!insns_sanitized) if (!insns_sanitized)
return -ENOMEM; return -ENOMEM;
uinsns = u64_to_user_ptr(info.xlated_prog_insns); uinsns = u64_to_user_ptr(info.xlated_prog_insns);
...@@ -3328,7 +3330,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, ...@@ -3328,7 +3330,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
} }
if (info.jited_prog_len && ulen) { if (info.jited_prog_len && ulen) {
if (bpf_dump_raw_ok()) { if (bpf_dump_raw_ok(file->f_cred)) {
uinsns = u64_to_user_ptr(info.jited_prog_insns); uinsns = u64_to_user_ptr(info.jited_prog_insns);
ulen = min_t(u32, info.jited_prog_len, ulen); ulen = min_t(u32, info.jited_prog_len, ulen);
...@@ -3363,7 +3365,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, ...@@ -3363,7 +3365,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
ulen = info.nr_jited_ksyms; ulen = info.nr_jited_ksyms;
info.nr_jited_ksyms = prog->aux->func_cnt ? : 1; info.nr_jited_ksyms = prog->aux->func_cnt ? : 1;
if (ulen) { if (ulen) {
if (bpf_dump_raw_ok()) { if (bpf_dump_raw_ok(file->f_cred)) {
unsigned long ksym_addr; unsigned long ksym_addr;
u64 __user *user_ksyms; u64 __user *user_ksyms;
u32 i; u32 i;
...@@ -3394,7 +3396,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, ...@@ -3394,7 +3396,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
ulen = info.nr_jited_func_lens; ulen = info.nr_jited_func_lens;
info.nr_jited_func_lens = prog->aux->func_cnt ? : 1; info.nr_jited_func_lens = prog->aux->func_cnt ? : 1;
if (ulen) { if (ulen) {
if (bpf_dump_raw_ok()) { if (bpf_dump_raw_ok(file->f_cred)) {
u32 __user *user_lens; u32 __user *user_lens;
u32 func_len, i; u32 func_len, i;
...@@ -3451,7 +3453,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, ...@@ -3451,7 +3453,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
else else
info.nr_jited_line_info = 0; info.nr_jited_line_info = 0;
if (info.nr_jited_line_info && ulen) { if (info.nr_jited_line_info && ulen) {
if (bpf_dump_raw_ok()) { if (bpf_dump_raw_ok(file->f_cred)) {
__u64 __user *user_linfo; __u64 __user *user_linfo;
u32 i; u32 i;
...@@ -3497,7 +3499,8 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, ...@@ -3497,7 +3499,8 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
return 0; return 0;
} }
static int bpf_map_get_info_by_fd(struct bpf_map *map, static int bpf_map_get_info_by_fd(struct file *file,
struct bpf_map *map,
const union bpf_attr *attr, const union bpf_attr *attr,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
...@@ -3540,7 +3543,8 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, ...@@ -3540,7 +3543,8 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
return 0; return 0;
} }
static int bpf_btf_get_info_by_fd(struct btf *btf, static int bpf_btf_get_info_by_fd(struct file *file,
struct btf *btf,
const union bpf_attr *attr, const union bpf_attr *attr,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
...@@ -3555,7 +3559,8 @@ static int bpf_btf_get_info_by_fd(struct btf *btf, ...@@ -3555,7 +3559,8 @@ static int bpf_btf_get_info_by_fd(struct btf *btf,
return btf_get_info_by_fd(btf, attr, uattr); return btf_get_info_by_fd(btf, attr, uattr);
} }
static int bpf_link_get_info_by_fd(struct bpf_link *link, static int bpf_link_get_info_by_fd(struct file *file,
struct bpf_link *link,
const union bpf_attr *attr, const union bpf_attr *attr,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
...@@ -3608,15 +3613,15 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, ...@@ -3608,15 +3613,15 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
return -EBADFD; return -EBADFD;
if (f.file->f_op == &bpf_prog_fops) if (f.file->f_op == &bpf_prog_fops)
err = bpf_prog_get_info_by_fd(f.file->private_data, attr, err = bpf_prog_get_info_by_fd(f.file, f.file->private_data, attr,
uattr); uattr);
else if (f.file->f_op == &bpf_map_fops) else if (f.file->f_op == &bpf_map_fops)
err = bpf_map_get_info_by_fd(f.file->private_data, attr, err = bpf_map_get_info_by_fd(f.file, f.file->private_data, attr,
uattr); uattr);
else if (f.file->f_op == &btf_fops) else if (f.file->f_op == &btf_fops)
err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr); err = bpf_btf_get_info_by_fd(f.file, f.file->private_data, attr, uattr);
else if (f.file->f_op == &bpf_link_fops) else if (f.file->f_op == &bpf_link_fops)
err = bpf_link_get_info_by_fd(f.file->private_data, err = bpf_link_get_info_by_fd(f.file, f.file->private_data,
attr, uattr); attr, uattr);
else else
err = -EINVAL; err = -EINVAL;
......
...@@ -644,19 +644,20 @@ static inline int kallsyms_for_perf(void) ...@@ -644,19 +644,20 @@ static inline int kallsyms_for_perf(void)
* Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to * Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
* block even that). * block even that).
*/ */
int kallsyms_show_value(void) bool kallsyms_show_value(const struct cred *cred)
{ {
switch (kptr_restrict) { switch (kptr_restrict) {
case 0: case 0:
if (kallsyms_for_perf()) if (kallsyms_for_perf())
return 1; return true;
/* fallthrough */ /* fallthrough */
case 1: case 1:
if (has_capability_noaudit(current, CAP_SYSLOG)) if (security_capable(cred, &init_user_ns, CAP_SYSLOG,
return 1; CAP_OPT_NOAUDIT) == 0)
return true;
/* fallthrough */ /* fallthrough */
default: default:
return 0; return false;
} }
} }
...@@ -673,7 +674,11 @@ static int kallsyms_open(struct inode *inode, struct file *file) ...@@ -673,7 +674,11 @@ static int kallsyms_open(struct inode *inode, struct file *file)
return -ENOMEM; return -ENOMEM;
reset_iter(iter, 0); reset_iter(iter, 0);
iter->show_value = kallsyms_show_value(); /*
* Instead of checking this on every s_show() call, cache
* the result here at open time.
*/
iter->show_value = kallsyms_show_value(file->f_cred);
return 0; return 0;
} }
......
...@@ -2448,7 +2448,7 @@ static void report_probe(struct seq_file *pi, struct kprobe *p, ...@@ -2448,7 +2448,7 @@ static void report_probe(struct seq_file *pi, struct kprobe *p,
else else
kprobe_type = "k"; kprobe_type = "k";
if (!kallsyms_show_value()) if (!kallsyms_show_value(pi->file->f_cred))
addr = NULL; addr = NULL;
if (sym) if (sym)
...@@ -2540,7 +2540,7 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v) ...@@ -2540,7 +2540,7 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v)
* If /proc/kallsyms is not showing kernel address, we won't * If /proc/kallsyms is not showing kernel address, we won't
* show them here either. * show them here either.
*/ */
if (!kallsyms_show_value()) if (!kallsyms_show_value(m->file->f_cred))
seq_printf(m, "0x%px-0x%px\t%ps\n", NULL, NULL, seq_printf(m, "0x%px-0x%px\t%ps\n", NULL, NULL,
(void *)ent->start_addr); (void *)ent->start_addr);
else else
......
...@@ -1510,8 +1510,7 @@ static inline bool sect_empty(const Elf_Shdr *sect) ...@@ -1510,8 +1510,7 @@ static inline bool sect_empty(const Elf_Shdr *sect)
} }
struct module_sect_attr { struct module_sect_attr {
struct module_attribute mattr; struct bin_attribute battr;
char *name;
unsigned long address; unsigned long address;
}; };
...@@ -1521,13 +1520,18 @@ struct module_sect_attrs { ...@@ -1521,13 +1520,18 @@ struct module_sect_attrs {
struct module_sect_attr attrs[]; struct module_sect_attr attrs[];
}; };
static ssize_t module_sect_show(struct module_attribute *mattr, static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
struct module_kobject *mk, char *buf) struct bin_attribute *battr,
char *buf, loff_t pos, size_t count)
{ {
struct module_sect_attr *sattr = struct module_sect_attr *sattr =
container_of(mattr, struct module_sect_attr, mattr); container_of(battr, struct module_sect_attr, battr);
return sprintf(buf, "0x%px\n", kptr_restrict < 2 ?
(void *)sattr->address : NULL); if (pos != 0)
return -EINVAL;
return sprintf(buf, "0x%px\n",
kallsyms_show_value(file->f_cred) ? (void *)sattr->address : NULL);
} }
static void free_sect_attrs(struct module_sect_attrs *sect_attrs) static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
...@@ -1535,7 +1539,7 @@ static void free_sect_attrs(struct module_sect_attrs *sect_attrs) ...@@ -1535,7 +1539,7 @@ static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
unsigned int section; unsigned int section;
for (section = 0; section < sect_attrs->nsections; section++) for (section = 0; section < sect_attrs->nsections; section++)
kfree(sect_attrs->attrs[section].name); kfree(sect_attrs->attrs[section].battr.attr.name);
kfree(sect_attrs); kfree(sect_attrs);
} }
...@@ -1544,42 +1548,41 @@ static void add_sect_attrs(struct module *mod, const struct load_info *info) ...@@ -1544,42 +1548,41 @@ static void add_sect_attrs(struct module *mod, const struct load_info *info)
unsigned int nloaded = 0, i, size[2]; unsigned int nloaded = 0, i, size[2];
struct module_sect_attrs *sect_attrs; struct module_sect_attrs *sect_attrs;
struct module_sect_attr *sattr; struct module_sect_attr *sattr;
struct attribute **gattr; struct bin_attribute **gattr;
/* Count loaded sections and allocate structures */ /* Count loaded sections and allocate structures */
for (i = 0; i < info->hdr->e_shnum; i++) for (i = 0; i < info->hdr->e_shnum; i++)
if (!sect_empty(&info->sechdrs[i])) if (!sect_empty(&info->sechdrs[i]))
nloaded++; nloaded++;
size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded), size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded),
sizeof(sect_attrs->grp.attrs[0])); sizeof(sect_attrs->grp.bin_attrs[0]));
size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]); size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]);
sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL); sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
if (sect_attrs == NULL) if (sect_attrs == NULL)
return; return;
/* Setup section attributes. */ /* Setup section attributes. */
sect_attrs->grp.name = "sections"; sect_attrs->grp.name = "sections";
sect_attrs->grp.attrs = (void *)sect_attrs + size[0]; sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0];
sect_attrs->nsections = 0; sect_attrs->nsections = 0;
sattr = &sect_attrs->attrs[0]; sattr = &sect_attrs->attrs[0];
gattr = &sect_attrs->grp.attrs[0]; gattr = &sect_attrs->grp.bin_attrs[0];
for (i = 0; i < info->hdr->e_shnum; i++) { for (i = 0; i < info->hdr->e_shnum; i++) {
Elf_Shdr *sec = &info->sechdrs[i]; Elf_Shdr *sec = &info->sechdrs[i];
if (sect_empty(sec)) if (sect_empty(sec))
continue; continue;
sysfs_bin_attr_init(&sattr->battr);
sattr->address = sec->sh_addr; sattr->address = sec->sh_addr;
sattr->name = kstrdup(info->secstrings + sec->sh_name, sattr->battr.attr.name =
GFP_KERNEL); kstrdup(info->secstrings + sec->sh_name, GFP_KERNEL);
if (sattr->name == NULL) if (sattr->battr.attr.name == NULL)
goto out; goto out;
sect_attrs->nsections++; sect_attrs->nsections++;
sysfs_attr_init(&sattr->mattr.attr); sattr->battr.read = module_sect_read;
sattr->mattr.show = module_sect_show; sattr->battr.size = 3 /* "0x", "\n" */ + (BITS_PER_LONG / 4);
sattr->mattr.store = NULL; sattr->battr.attr.mode = 0400;
sattr->mattr.attr.name = sattr->name; *(gattr++) = &(sattr++)->battr;
sattr->mattr.attr.mode = S_IRUSR;
*(gattr++) = &(sattr++)->mattr.attr;
} }
*gattr = NULL; *gattr = NULL;
...@@ -1669,7 +1672,7 @@ static void add_notes_attrs(struct module *mod, const struct load_info *info) ...@@ -1669,7 +1672,7 @@ static void add_notes_attrs(struct module *mod, const struct load_info *info)
continue; continue;
if (info->sechdrs[i].sh_type == SHT_NOTE) { if (info->sechdrs[i].sh_type == SHT_NOTE) {
sysfs_bin_attr_init(nattr); sysfs_bin_attr_init(nattr);
nattr->attr.name = mod->sect_attrs->attrs[loaded].name; nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name;
nattr->attr.mode = S_IRUGO; nattr->attr.mode = S_IRUGO;
nattr->size = info->sechdrs[i].sh_size; nattr->size = info->sechdrs[i].sh_size;
nattr->private = (void *) info->sechdrs[i].sh_addr; nattr->private = (void *) info->sechdrs[i].sh_addr;
...@@ -4379,7 +4382,7 @@ static int modules_open(struct inode *inode, struct file *file) ...@@ -4379,7 +4382,7 @@ static int modules_open(struct inode *inode, struct file *file)
if (!err) { if (!err) {
struct seq_file *m = file->private_data; struct seq_file *m = file->private_data;
m->private = kallsyms_show_value() ? NULL : (void *)8ul; m->private = kallsyms_show_value(file->f_cred) ? NULL : (void *)8ul;
} }
return err; return err;
......
...@@ -274,7 +274,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write, ...@@ -274,7 +274,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write,
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
if (write && !ret) { if (write && !ret) {
if (jit_enable < 2 || if (jit_enable < 2 ||
(jit_enable == 2 && bpf_dump_raw_ok())) { (jit_enable == 2 && bpf_dump_raw_ok(current_cred()))) {
*(int *)table->data = jit_enable; *(int *)table->data = jit_enable;
if (jit_enable == 2) if (jit_enable == 2)
pr_warn("bpf_jit_enable = 2 was set! NEVER use this in production, only for JIT debugging!\n"); pr_warn("bpf_jit_enable = 2 was set! NEVER use this in production, only for JIT debugging!\n");
......
...@@ -63,6 +63,8 @@ ALL_TESTS="$ALL_TESTS 0008:150:1" ...@@ -63,6 +63,8 @@ ALL_TESTS="$ALL_TESTS 0008:150:1"
ALL_TESTS="$ALL_TESTS 0009:150:1" ALL_TESTS="$ALL_TESTS 0009:150:1"
ALL_TESTS="$ALL_TESTS 0010:1:1" ALL_TESTS="$ALL_TESTS 0010:1:1"
ALL_TESTS="$ALL_TESTS 0011:1:1" ALL_TESTS="$ALL_TESTS 0011:1:1"
ALL_TESTS="$ALL_TESTS 0012:1:1"
ALL_TESTS="$ALL_TESTS 0013:1:1"
# Kselftest framework requirement - SKIP code is 4. # Kselftest framework requirement - SKIP code is 4.
ksft_skip=4 ksft_skip=4
...@@ -470,6 +472,38 @@ kmod_test_0011() ...@@ -470,6 +472,38 @@ kmod_test_0011()
echo "$MODPROBE" > /proc/sys/kernel/modprobe echo "$MODPROBE" > /proc/sys/kernel/modprobe
} }
kmod_check_visibility()
{
local name="$1"
local cmd="$2"
modprobe $DEFAULT_KMOD_DRIVER
local priv=$(eval $cmd)
local unpriv=$(capsh --drop=CAP_SYSLOG -- -c "$cmd")
if [ "$priv" = "$unpriv" ] || \
[ "${priv:0:3}" = "0x0" ] || \
[ "${unpriv:0:3}" != "0x0" ] ; then
echo "${FUNCNAME[0]}: FAIL, $name visible to unpriv: '$priv' vs '$unpriv'" >&2
exit 1
else
echo "${FUNCNAME[0]}: OK!"
fi
}
kmod_test_0012()
{
kmod_check_visibility /proc/modules \
"grep '^${DEFAULT_KMOD_DRIVER}\b' /proc/modules | awk '{print \$NF}'"
}
kmod_test_0013()
{
kmod_check_visibility '/sys/module/*/sections/*' \
"cat /sys/module/${DEFAULT_KMOD_DRIVER}/sections/.*text | head -n1"
}
list_tests() list_tests()
{ {
echo "Test ID list:" echo "Test ID list:"
...@@ -489,6 +523,8 @@ list_tests() ...@@ -489,6 +523,8 @@ list_tests()
echo "0009 x $(get_test_count 0009) - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()" echo "0009 x $(get_test_count 0009) - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()"
echo "0010 x $(get_test_count 0010) - test nonexistent modprobe path" echo "0010 x $(get_test_count 0010) - test nonexistent modprobe path"
echo "0011 x $(get_test_count 0011) - test completely disabling module autoloading" echo "0011 x $(get_test_count 0011) - test completely disabling module autoloading"
echo "0012 x $(get_test_count 0012) - test /proc/modules address visibility under CAP_SYSLOG"
echo "0013 x $(get_test_count 0013) - test /sys/module/*/sections/* visibility under CAP_SYSLOG"
} }
usage() usage()
......
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