linux/kernel/ksysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * kernel/ksysfs.c - sysfs attributes in /sys/kernel, which
   4 *                   are not related to any other subsystem
   5 *
   6 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
   7 */
   8
   9#include <linux/kobject.h>
  10#include <linux/string.h>
  11#include <linux/sysfs.h>
  12#include <linux/export.h>
  13#include <linux/init.h>
  14#include <linux/kexec.h>
  15#include <linux/profile.h>
  16#include <linux/stat.h>
  17#include <linux/sched.h>
  18#include <linux/capability.h>
  19#include <linux/compiler.h>
  20
  21#include <linux/rcupdate.h>     /* rcu_expedited and rcu_normal */
  22
  23#define KERNEL_ATTR_RO(_name) \
  24static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
  25
  26#define KERNEL_ATTR_RW(_name) \
  27static struct kobj_attribute _name##_attr = \
  28        __ATTR(_name, 0644, _name##_show, _name##_store)
  29
  30/* current uevent sequence number */
  31static ssize_t uevent_seqnum_show(struct kobject *kobj,
  32                                  struct kobj_attribute *attr, char *buf)
  33{
  34        return sprintf(buf, "%llu\n", (unsigned long long)uevent_seqnum);
  35}
  36KERNEL_ATTR_RO(uevent_seqnum);
  37
  38#ifdef CONFIG_UEVENT_HELPER
  39/* uevent helper program, used during early boot */
  40static ssize_t uevent_helper_show(struct kobject *kobj,
  41                                  struct kobj_attribute *attr, char *buf)
  42{
  43        return sprintf(buf, "%s\n", uevent_helper);
  44}
  45static ssize_t uevent_helper_store(struct kobject *kobj,
  46                                   struct kobj_attribute *attr,
  47                                   const char *buf, size_t count)
  48{
  49        if (count+1 > UEVENT_HELPER_PATH_LEN)
  50                return -ENOENT;
  51        memcpy(uevent_helper, buf, count);
  52        uevent_helper[count] = '\0';
  53        if (count && uevent_helper[count-1] == '\n')
  54                uevent_helper[count-1] = '\0';
  55        return count;
  56}
  57KERNEL_ATTR_RW(uevent_helper);
  58#endif
  59
  60#ifdef CONFIG_PROFILING
  61static ssize_t profiling_show(struct kobject *kobj,
  62                                  struct kobj_attribute *attr, char *buf)
  63{
  64        return sprintf(buf, "%d\n", prof_on);
  65}
  66static ssize_t profiling_store(struct kobject *kobj,
  67                                   struct kobj_attribute *attr,
  68                                   const char *buf, size_t count)
  69{
  70        int ret;
  71
  72        if (prof_on)
  73                return -EEXIST;
  74        /*
  75         * This eventually calls into get_option() which
  76         * has a ton of callers and is not const.  It is
  77         * easiest to cast it away here.
  78         */
  79        profile_setup((char *)buf);
  80        ret = profile_init();
  81        if (ret)
  82                return ret;
  83        ret = create_proc_profile();
  84        if (ret)
  85                return ret;
  86        return count;
  87}
  88KERNEL_ATTR_RW(profiling);
  89#endif
  90
  91#ifdef CONFIG_KEXEC_CORE
  92static ssize_t kexec_loaded_show(struct kobject *kobj,
  93                                 struct kobj_attribute *attr, char *buf)
  94{
  95        return sprintf(buf, "%d\n", !!kexec_image);
  96}
  97KERNEL_ATTR_RO(kexec_loaded);
  98
  99static ssize_t kexec_crash_loaded_show(struct kobject *kobj,
 100                                       struct kobj_attribute *attr, char *buf)
 101{
 102        return sprintf(buf, "%d\n", kexec_crash_loaded());
 103}
 104KERNEL_ATTR_RO(kexec_crash_loaded);
 105
 106static ssize_t kexec_crash_size_show(struct kobject *kobj,
 107                                       struct kobj_attribute *attr, char *buf)
 108{
 109        return sprintf(buf, "%zu\n", crash_get_memory_size());
 110}
 111static ssize_t kexec_crash_size_store(struct kobject *kobj,
 112                                   struct kobj_attribute *attr,
 113                                   const char *buf, size_t count)
 114{
 115        unsigned long cnt;
 116        int ret;
 117
 118        if (kstrtoul(buf, 0, &cnt))
 119                return -EINVAL;
 120
 121        ret = crash_shrink_memory(cnt);
 122        return ret < 0 ? ret : count;
 123}
 124KERNEL_ATTR_RW(kexec_crash_size);
 125
 126#endif /* CONFIG_KEXEC_CORE */
 127
 128#ifdef CONFIG_CRASH_CORE
 129
 130static ssize_t vmcoreinfo_show(struct kobject *kobj,
 131                               struct kobj_attribute *attr, char *buf)
 132{
 133        phys_addr_t vmcore_base = paddr_vmcoreinfo_note();
 134        return sprintf(buf, "%pa %x\n", &vmcore_base,
 135                        (unsigned int)VMCOREINFO_NOTE_SIZE);
 136}
 137KERNEL_ATTR_RO(vmcoreinfo);
 138
 139#endif /* CONFIG_CRASH_CORE */
 140
 141/* whether file capabilities are enabled */
 142static ssize_t fscaps_show(struct kobject *kobj,
 143                                  struct kobj_attribute *attr, char *buf)
 144{
 145        return sprintf(buf, "%d\n", file_caps_enabled);
 146}
 147KERNEL_ATTR_RO(fscaps);
 148
 149#ifndef CONFIG_TINY_RCU
 150int rcu_expedited;
 151static ssize_t rcu_expedited_show(struct kobject *kobj,
 152                                  struct kobj_attribute *attr, char *buf)
 153{
 154        return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
 155}
 156static ssize_t rcu_expedited_store(struct kobject *kobj,
 157                                   struct kobj_attribute *attr,
 158                                   const char *buf, size_t count)
 159{
 160        if (kstrtoint(buf, 0, &rcu_expedited))
 161                return -EINVAL;
 162
 163        return count;
 164}
 165KERNEL_ATTR_RW(rcu_expedited);
 166
 167int rcu_normal;
 168static ssize_t rcu_normal_show(struct kobject *kobj,
 169                               struct kobj_attribute *attr, char *buf)
 170{
 171        return sprintf(buf, "%d\n", READ_ONCE(rcu_normal));
 172}
 173static ssize_t rcu_normal_store(struct kobject *kobj,
 174                                struct kobj_attribute *attr,
 175                                const char *buf, size_t count)
 176{
 177        if (kstrtoint(buf, 0, &rcu_normal))
 178                return -EINVAL;
 179
 180        return count;
 181}
 182KERNEL_ATTR_RW(rcu_normal);
 183#endif /* #ifndef CONFIG_TINY_RCU */
 184
 185/*
 186 * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
 187 */
 188extern const void __start_notes __weak;
 189extern const void __stop_notes __weak;
 190#define notes_size (&__stop_notes - &__start_notes)
 191
 192static ssize_t notes_read(struct file *filp, struct kobject *kobj,
 193                          struct bin_attribute *bin_attr,
 194                          char *buf, loff_t off, size_t count)
 195{
 196        memcpy(buf, &__start_notes + off, count);
 197        return count;
 198}
 199
 200static struct bin_attribute notes_attr __ro_after_init  = {
 201        .attr = {
 202                .name = "notes",
 203                .mode = S_IRUGO,
 204        },
 205        .read = &notes_read,
 206};
 207
 208struct kobject *kernel_kobj;
 209EXPORT_SYMBOL_GPL(kernel_kobj);
 210
 211static struct attribute * kernel_attrs[] = {
 212        &fscaps_attr.attr,
 213        &uevent_seqnum_attr.attr,
 214#ifdef CONFIG_UEVENT_HELPER
 215        &uevent_helper_attr.attr,
 216#endif
 217#ifdef CONFIG_PROFILING
 218        &profiling_attr.attr,
 219#endif
 220#ifdef CONFIG_KEXEC_CORE
 221        &kexec_loaded_attr.attr,
 222        &kexec_crash_loaded_attr.attr,
 223        &kexec_crash_size_attr.attr,
 224#endif
 225#ifdef CONFIG_CRASH_CORE
 226        &vmcoreinfo_attr.attr,
 227#endif
 228#ifndef CONFIG_TINY_RCU
 229        &rcu_expedited_attr.attr,
 230        &rcu_normal_attr.attr,
 231#endif
 232        NULL
 233};
 234
 235static const struct attribute_group kernel_attr_group = {
 236        .attrs = kernel_attrs,
 237};
 238
 239static int __init ksysfs_init(void)
 240{
 241        int error;
 242
 243        kernel_kobj = kobject_create_and_add("kernel", NULL);
 244        if (!kernel_kobj) {
 245                error = -ENOMEM;
 246                goto exit;
 247        }
 248        error = sysfs_create_group(kernel_kobj, &kernel_attr_group);
 249        if (error)
 250                goto kset_exit;
 251
 252        if (notes_size > 0) {
 253                notes_attr.size = notes_size;
 254                error = sysfs_create_bin_file(kernel_kobj, &notes_attr);
 255                if (error)
 256                        goto group_exit;
 257        }
 258
 259        return 0;
 260
 261group_exit:
 262        sysfs_remove_group(kernel_kobj, &kernel_attr_group);
 263kset_exit:
 264        kobject_put(kernel_kobj);
 265exit:
 266        return error;
 267}
 268
 269core_initcall(ksysfs_init);
 270