Branch data 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 : 0 : static ssize_t profiling_show(struct kobject *kobj,
62 : : struct kobj_attribute *attr, char *buf)
63 : : {
64 : 0 : return sprintf(buf, "%d\n", prof_on);
65 : : }
66 : 0 : 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 : 0 : 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 : 0 : profile_setup((char *)buf);
80 : 0 : ret = profile_init();
81 : 0 : if (ret)
82 : : return ret;
83 : 0 : ret = create_proc_profile();
84 : 0 : if (ret)
85 : : return ret;
86 : 0 : 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 : 3 : static int __init ksysfs_init(void)
240 : : {
241 : : int error;
242 : :
243 : 3 : kernel_kobj = kobject_create_and_add("kernel", NULL);
244 : 3 : if (!kernel_kobj) {
245 : : error = -ENOMEM;
246 : : goto exit;
247 : : }
248 : 3 : error = sysfs_create_group(kernel_kobj, &kernel_attr_group);
249 : 3 : if (error)
250 : : goto kset_exit;
251 : :
252 : 3 : if (notes_size > 0) {
253 : 3 : notes_attr.size = notes_size;
254 : 3 : error = sysfs_create_bin_file(kernel_kobj, ¬es_attr);
255 : 3 : if (error)
256 : : goto group_exit;
257 : : }
258 : :
259 : : return 0;
260 : :
261 : : group_exit:
262 : 0 : sysfs_remove_group(kernel_kobj, &kernel_attr_group);
263 : : kset_exit:
264 : 0 : kobject_put(kernel_kobj);
265 : : exit:
266 : 0 : return error;
267 : : }
268 : :
269 : : core_initcall(ksysfs_init);
|