Line data Source code
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) \
24 : static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
25 :
26 : #define KERNEL_ATTR_RW(_name) \
27 : static struct kobj_attribute _name##_attr = \
28 : __ATTR(_name, 0644, _name##_show, _name##_store)
29 :
30 : /* current uevent sequence number */
31 0 : static ssize_t uevent_seqnum_show(struct kobject *kobj,
32 : struct kobj_attribute *attr, char *buf)
33 : {
34 0 : return sprintf(buf, "%llu\n", (unsigned long long)uevent_seqnum);
35 : }
36 : KERNEL_ATTR_RO(uevent_seqnum);
37 :
38 : #ifdef CONFIG_UEVENT_HELPER
39 : /* uevent helper program, used during early boot */
40 0 : static ssize_t uevent_helper_show(struct kobject *kobj,
41 : struct kobj_attribute *attr, char *buf)
42 : {
43 0 : return sprintf(buf, "%s\n", uevent_helper);
44 : }
45 0 : static ssize_t uevent_helper_store(struct kobject *kobj,
46 : struct kobj_attribute *attr,
47 : const char *buf, size_t count)
48 : {
49 0 : if (count+1 > UEVENT_HELPER_PATH_LEN)
50 : return -ENOENT;
51 0 : memcpy(uevent_helper, buf, count);
52 0 : uevent_helper[count] = '\0';
53 0 : if (count && uevent_helper[count-1] == '\n')
54 0 : uevent_helper[count-1] = '\0';
55 0 : return count;
56 : }
57 : KERNEL_ATTR_RW(uevent_helper);
58 : #endif
59 :
60 : #ifdef CONFIG_PROFILING
61 : static ssize_t profiling_show(struct kobject *kobj,
62 : struct kobj_attribute *attr, char *buf)
63 : {
64 : return sprintf(buf, "%d\n", prof_on);
65 : }
66 : static 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 : }
88 : KERNEL_ATTR_RW(profiling);
89 : #endif
90 :
91 : #ifdef CONFIG_KEXEC_CORE
92 : static 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 : }
97 : KERNEL_ATTR_RO(kexec_loaded);
98 :
99 : static 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 : }
104 : KERNEL_ATTR_RO(kexec_crash_loaded);
105 :
106 : static 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 : }
111 : static 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 : }
124 : KERNEL_ATTR_RW(kexec_crash_size);
125 :
126 : #endif /* CONFIG_KEXEC_CORE */
127 :
128 : #ifdef CONFIG_CRASH_CORE
129 :
130 : static 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 : }
137 : KERNEL_ATTR_RO(vmcoreinfo);
138 :
139 : #endif /* CONFIG_CRASH_CORE */
140 :
141 : /* whether file capabilities are enabled */
142 0 : static ssize_t fscaps_show(struct kobject *kobj,
143 : struct kobj_attribute *attr, char *buf)
144 : {
145 0 : return sprintf(buf, "%d\n", file_caps_enabled);
146 : }
147 : KERNEL_ATTR_RO(fscaps);
148 :
149 : #ifndef CONFIG_TINY_RCU
150 : int rcu_expedited;
151 0 : static ssize_t rcu_expedited_show(struct kobject *kobj,
152 : struct kobj_attribute *attr, char *buf)
153 : {
154 0 : return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
155 : }
156 0 : static ssize_t rcu_expedited_store(struct kobject *kobj,
157 : struct kobj_attribute *attr,
158 : const char *buf, size_t count)
159 : {
160 0 : if (kstrtoint(buf, 0, &rcu_expedited))
161 : return -EINVAL;
162 :
163 0 : return count;
164 : }
165 : KERNEL_ATTR_RW(rcu_expedited);
166 :
167 : int rcu_normal;
168 0 : static ssize_t rcu_normal_show(struct kobject *kobj,
169 : struct kobj_attribute *attr, char *buf)
170 : {
171 0 : return sprintf(buf, "%d\n", READ_ONCE(rcu_normal));
172 : }
173 0 : static ssize_t rcu_normal_store(struct kobject *kobj,
174 : struct kobj_attribute *attr,
175 : const char *buf, size_t count)
176 : {
177 0 : if (kstrtoint(buf, 0, &rcu_normal))
178 : return -EINVAL;
179 :
180 0 : return count;
181 : }
182 : KERNEL_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 : */
188 : extern const void __start_notes __weak;
189 : extern const void __stop_notes __weak;
190 : #define notes_size (&__stop_notes - &__start_notes)
191 :
192 0 : static 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 0 : memcpy(buf, &__start_notes + off, count);
197 0 : return count;
198 : }
199 :
200 : static struct bin_attribute notes_attr __ro_after_init = {
201 : .attr = {
202 : .name = "notes",
203 : .mode = S_IRUGO,
204 : },
205 : .read = ¬es_read,
206 : };
207 :
208 : struct kobject *kernel_kobj;
209 : EXPORT_SYMBOL_GPL(kernel_kobj);
210 :
211 : static 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 :
235 : static const struct attribute_group kernel_attr_group = {
236 : .attrs = kernel_attrs,
237 : };
238 :
239 1 : static int __init ksysfs_init(void)
240 : {
241 1 : int error;
242 :
243 1 : kernel_kobj = kobject_create_and_add("kernel", NULL);
244 1 : if (!kernel_kobj) {
245 0 : error = -ENOMEM;
246 0 : goto exit;
247 : }
248 1 : error = sysfs_create_group(kernel_kobj, &kernel_attr_group);
249 1 : if (error)
250 0 : goto kset_exit;
251 :
252 1 : if (notes_size > 0) {
253 1 : notes_attr.size = notes_size;
254 1 : error = sysfs_create_bin_file(kernel_kobj, ¬es_attr);
255 1 : if (error)
256 0 : goto group_exit;
257 : }
258 :
259 : return 0;
260 :
261 0 : group_exit:
262 0 : sysfs_remove_group(kernel_kobj, &kernel_attr_group);
263 0 : kset_exit:
264 0 : kobject_put(kernel_kobj);
265 : exit:
266 : return error;
267 : }
268 :
269 : core_initcall(ksysfs_init);
|