1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2016-2018, Matthew Macy <mmacy@freebsd.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/queue.h>
32 #include <sys/blist.h>
33 #include <sys/conf.h>
34 #include <sys/exec.h>
35 #include <sys/filedesc.h>
36 #include <sys/kernel.h>
37 #include <sys/linker.h>
38 #include <sys/malloc.h>
39 #include <sys/mount.h>
40 #include <sys/mutex.h>
41 #include <sys/proc.h>
42 #include <sys/resourcevar.h>
43 #include <sys/sbuf.h>
44 #include <sys/smp.h>
45 #include <sys/socket.h>
46 #include <sys/vnode.h>
47 #include <sys/bus.h>
48 #include <sys/pciio.h>
49
50 #include <dev/pci/pcivar.h>
51 #include <dev/pci/pcireg.h>
52
53 #include <net/if.h>
54
55 #include <vm/vm.h>
56 #include <vm/pmap.h>
57 #include <vm/vm_map.h>
58 #include <vm/vm_param.h>
59 #include <vm/vm_object.h>
60 #include <vm/swap_pager.h>
61
62 #include <machine/bus.h>
63
64 #include <compat/linux/linux_ioctl.h>
65 #include <compat/linux/linux_mib.h>
66 #include <compat/linux/linux_util.h>
67 #include <fs/pseudofs/pseudofs.h>
68
69 #include <asm/atomic.h>
70 #include <linux/compat.h>
71 #include <linux/debugfs.h>
72 #include <linux/fs.h>
73
74 MALLOC_DEFINE(M_DFSINT, "debugfsint", "Linux debugfs internal");
75
76 static struct pfs_node *debugfs_root;
77
78 #define DM_SYMLINK 0x1
79 #define DM_DIR 0x2
80 #define DM_FILE 0x3
81
82 struct dentry_meta {
83 struct dentry dm_dnode;
84 const struct file_operations *dm_fops;
85 void *dm_data;
86 umode_t dm_mode;
87 int dm_type;
88 };
89
90 static int
debugfs_attr(PFS_ATTR_ARGS)91 debugfs_attr(PFS_ATTR_ARGS)
92 {
93 struct dentry_meta *dm;
94
95 dm = pn->pn_data;
96
97 vap->va_mode = dm->dm_mode;
98 return (0);
99 }
100
101 static int
debugfs_destroy(PFS_DESTROY_ARGS)102 debugfs_destroy(PFS_DESTROY_ARGS)
103 {
104 struct dentry_meta *dm;
105
106 dm = pn->pn_data;
107 if (dm != NULL && dm->dm_type == DM_SYMLINK)
108 free(dm->dm_data, M_DFSINT);
109
110 free(dm, M_DFSINT);
111 return (0);
112 }
113
114 static int
debugfs_fill(PFS_FILL_ARGS)115 debugfs_fill(PFS_FILL_ARGS)
116 {
117 struct dentry_meta *d;
118 struct linux_file lf = {};
119 struct vnode vn;
120 struct iovec *iov;
121 size_t cnt, orig_resid;
122 ssize_t rc;
123 off_t off;
124
125 /* Linux file operations assume a pointer to a user buffer. */
126 if (uio->uio_segflg != UIO_USERSPACE)
127 return (EOPNOTSUPP);
128
129 if ((rc = linux_set_current_flags(curthread, M_NOWAIT)))
130 return (rc);
131
132 d = pn->pn_data;
133 vn.v_data = d->dm_data;
134
135 rc = d->dm_fops->open(&vn, &lf);
136 if (rc < 0) {
137 #ifdef INVARIANTS
138 printf("%s:%d open failed with %zd\n", __func__, __LINE__, rc);
139 #endif
140 return (-rc);
141 }
142
143 off = uio->uio_offset;
144 orig_resid = uio->uio_resid;
145 while (uio->uio_resid > 0) {
146 KASSERT(uio->uio_iovcnt > 0,
147 ("%s: uio %p iovcnt underflow", __func__, uio));
148
149 iov = uio->uio_iov;
150 cnt = iov->iov_len;
151 if (cnt == 0) {
152 uio->uio_iov++;
153 uio->uio_iovcnt--;
154 continue;
155 }
156 if (cnt > uio->uio_resid)
157 cnt = uio->uio_resid;
158
159 switch (uio->uio_rw) {
160 case UIO_READ:
161 if (d->dm_fops->read != NULL)
162 rc = d->dm_fops->read(&lf, iov->iov_base, cnt,
163 &off);
164 else
165 rc = -ENODEV;
166 break;
167 case UIO_WRITE:
168 if (d->dm_fops->write != NULL)
169 rc = d->dm_fops->write(&lf, iov->iov_base, cnt,
170 &off);
171 else
172 rc = -ENODEV;
173 break;
174 }
175
176 if (rc <= 0)
177 break;
178
179 iov->iov_base = (char *)iov->iov_base + rc;
180 iov->iov_len -= rc;
181 uio->uio_resid -= rc;
182 uio->uio_offset = off;
183 }
184
185 if (d->dm_fops->release)
186 d->dm_fops->release(&vn, &lf);
187
188 /* Return success for short operations. */
189 if (orig_resid != uio->uio_resid)
190 rc = 0;
191
192 if (rc < 0) {
193 #ifdef INVARIANTS
194 printf("%s:%d read/write failed with %zd\n", __func__, __LINE__,
195 rc);
196 #endif
197 return (-rc);
198 }
199 return (0);
200 }
201
202 static int
debugfs_fill_data(PFS_FILL_ARGS)203 debugfs_fill_data(PFS_FILL_ARGS)
204 {
205 struct dentry_meta *dm;
206
207 dm = pn->pn_data;
208 sbuf_printf(sb, "%s", (char *)dm->dm_data);
209 return (0);
210 }
211
212 struct dentry *
debugfs_create_file(const char * name,umode_t mode,struct dentry * parent,void * data,const struct file_operations * fops)213 debugfs_create_file(const char *name, umode_t mode,
214 struct dentry *parent, void *data,
215 const struct file_operations *fops)
216 {
217 struct dentry_meta *dm;
218 struct dentry *dnode;
219 struct pfs_node *pnode;
220 int flags;
221
222 dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
223 if (dm == NULL)
224 return (NULL);
225 dnode = &dm->dm_dnode;
226 dm->dm_fops = fops;
227 dm->dm_data = data;
228 dm->dm_mode = mode;
229 dm->dm_type = DM_FILE;
230 if (parent != NULL)
231 pnode = parent->d_pfs_node;
232 else
233 pnode = debugfs_root;
234
235 flags = fops->write ? PFS_RDWR : PFS_RD;
236 pfs_create_file(pnode, &dnode->d_pfs_node, name, debugfs_fill,
237 debugfs_attr, NULL, debugfs_destroy, flags | PFS_RAW | PFS_NOWAIT);
238 if (dnode->d_pfs_node == NULL) {
239 free(dm, M_DFSINT);
240 return (NULL);
241 }
242 dnode->d_pfs_node->pn_data = dm;
243
244 return (dnode);
245 }
246
247 struct dentry *
debugfs_create_file_size(const char * name,umode_t mode,struct dentry * parent,void * data,const struct file_operations * fops,loff_t file_size __unused)248 debugfs_create_file_size(const char *name, umode_t mode,
249 struct dentry *parent, void *data,
250 const struct file_operations *fops,
251 loff_t file_size __unused)
252 {
253
254 return debugfs_create_file(name, mode, parent, data, fops);
255 }
256
257 /*
258 * NOTE: Files created with the _unsafe moniker will not be protected from
259 * debugfs core file removals. It is the responsibility of @fops to protect
260 * its file using debugfs_file_get() and debugfs_file_put().
261 *
262 * FreeBSD's LinuxKPI lindebugfs does not perform file removals at the time
263 * of writing. Therefore there is no difference between functions with _unsafe
264 * and functions without _unsafe when using lindebugfs. Functions with _unsafe
265 * exist only for Linux compatibility.
266 */
267 struct dentry *
debugfs_create_file_unsafe(const char * name,umode_t mode,struct dentry * parent,void * data,const struct file_operations * fops)268 debugfs_create_file_unsafe(const char *name, umode_t mode,
269 struct dentry *parent, void *data,
270 const struct file_operations *fops)
271 {
272
273 return (debugfs_create_file(name, mode, parent, data, fops));
274 }
275
276 struct dentry *
debugfs_create_mode_unsafe(const char * name,umode_t mode,struct dentry * parent,void * data,const struct file_operations * fops,const struct file_operations * fops_ro,const struct file_operations * fops_wo)277 debugfs_create_mode_unsafe(const char *name, umode_t mode,
278 struct dentry *parent, void *data,
279 const struct file_operations *fops,
280 const struct file_operations *fops_ro,
281 const struct file_operations *fops_wo)
282 {
283 umode_t read = mode & S_IRUGO;
284 umode_t write = mode & S_IWUGO;
285
286 if (read && !write)
287 return (debugfs_create_file_unsafe(name, mode, parent, data, fops_ro));
288
289 if (write && !read)
290 return (debugfs_create_file_unsafe(name, mode, parent, data, fops_wo));
291
292 return (debugfs_create_file_unsafe(name, mode, parent, data, fops));
293 }
294
295 struct dentry *
debugfs_create_dir(const char * name,struct dentry * parent)296 debugfs_create_dir(const char *name, struct dentry *parent)
297 {
298 struct dentry_meta *dm;
299 struct dentry *dnode;
300 struct pfs_node *pnode;
301
302 if (name == NULL)
303 return (NULL);
304
305 dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
306 if (dm == NULL)
307 return (NULL);
308 dnode = &dm->dm_dnode;
309 dm->dm_mode = 0700;
310 dm->dm_type = DM_DIR;
311 if (parent != NULL)
312 pnode = parent->d_pfs_node;
313 else
314 pnode = debugfs_root;
315
316 pfs_create_dir(pnode, &dnode->d_pfs_node, name, debugfs_attr, NULL,
317 debugfs_destroy, PFS_RD | PFS_NOWAIT);
318 if (dnode->d_pfs_node == NULL) {
319 free(dm, M_DFSINT);
320 return (NULL);
321 }
322 dnode->d_pfs_node->pn_data = dm;
323 return (dnode);
324 }
325
326 struct dentry *
debugfs_create_symlink(const char * name,struct dentry * parent,const char * dest)327 debugfs_create_symlink(const char *name, struct dentry *parent,
328 const char *dest)
329 {
330 struct dentry_meta *dm;
331 struct dentry *dnode;
332 struct pfs_node *pnode;
333 void *data;
334
335 data = strdup_flags(dest, M_DFSINT, M_NOWAIT);
336 if (data == NULL)
337 return (NULL);
338 dm = malloc(sizeof(*dm), M_DFSINT, M_NOWAIT | M_ZERO);
339 if (dm == NULL)
340 goto fail1;
341 dnode = &dm->dm_dnode;
342 dm->dm_mode = 0700;
343 dm->dm_type = DM_SYMLINK;
344 dm->dm_data = data;
345 if (parent != NULL)
346 pnode = parent->d_pfs_node;
347 else
348 pnode = debugfs_root;
349
350 pfs_create_link(pnode, &dnode->d_pfs_node, name, &debugfs_fill_data,
351 NULL, NULL, NULL, PFS_NOWAIT);
352 if (dnode->d_pfs_node == NULL)
353 goto fail;
354 dnode->d_pfs_node->pn_data = dm;
355 return (dnode);
356 fail:
357 free(dm, M_DFSINT);
358 fail1:
359 free(data, M_DFSINT);
360 return (NULL);
361 }
362
363 struct dentry *
debugfs_lookup(const char * name,struct dentry * parent)364 debugfs_lookup(const char *name, struct dentry *parent)
365 {
366 struct dentry_meta *dm;
367 struct dentry *dnode;
368 struct pfs_node *pnode;
369
370 pnode = pfs_find_node(parent->d_pfs_node, name);
371 if (pnode == NULL)
372 return (NULL);
373
374 dm = (struct dentry_meta *)pnode->pn_data;
375 dnode = &dm->dm_dnode;
376
377 return (dnode);
378 }
379
380 void
debugfs_remove(struct dentry * dnode)381 debugfs_remove(struct dentry *dnode)
382 {
383 if (dnode == NULL)
384 return;
385
386 pfs_destroy(dnode->d_pfs_node);
387 }
388
389 void
debugfs_remove_recursive(struct dentry * dnode)390 debugfs_remove_recursive(struct dentry *dnode)
391 {
392 if (dnode == NULL)
393 return;
394
395 pfs_destroy(dnode->d_pfs_node);
396 }
397
398 static int
debugfs_bool_get(void * data,uint64_t * ullval)399 debugfs_bool_get(void *data, uint64_t *ullval)
400 {
401 bool *bval = data;
402
403 if (*bval)
404 *ullval = 1;
405 else
406 *ullval = 0;
407
408 return (0);
409 }
410
411 static int
debugfs_bool_set(void * data,uint64_t ullval)412 debugfs_bool_set(void *data, uint64_t ullval)
413 {
414 bool *bval = data;
415
416 if (ullval)
417 *bval = 1;
418 else
419 *bval = 0;
420
421 return (0);
422 }
423
424 DEFINE_DEBUGFS_ATTRIBUTE(fops_bool, debugfs_bool_get, debugfs_bool_set, "%llu\n");
425 DEFINE_DEBUGFS_ATTRIBUTE(fops_bool_ro, debugfs_bool_get, NULL, "%llu\n");
426 DEFINE_DEBUGFS_ATTRIBUTE(fops_bool_wo, NULL, debugfs_bool_set, "%llu\n");
427
428 void
debugfs_create_bool(const char * name,umode_t mode,struct dentry * parent,bool * value)429 debugfs_create_bool(const char *name, umode_t mode, struct dentry *parent, bool *value)
430 {
431
432 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_bool,
433 &fops_bool_ro, &fops_bool_wo);
434 }
435
436
437 static int
debugfs_u8_get(void * data,uint64_t * value)438 debugfs_u8_get(void *data, uint64_t *value)
439 {
440 uint8_t *u8data = data;
441 *value = *u8data;
442 return (0);
443 }
444
445 static int
debugfs_u8_set(void * data,uint64_t value)446 debugfs_u8_set(void *data, uint64_t value)
447 {
448 uint8_t *u8data = data;
449 *u8data = (uint8_t)value;
450 return (0);
451 }
452
453 DEFINE_DEBUGFS_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%u\n");
454 DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%u\n");
455 DEFINE_DEBUGFS_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%u\n");
456
457 void
debugfs_create_u8(const char * name,umode_t mode,struct dentry * parent,uint8_t * value)458 debugfs_create_u8(const char *name, umode_t mode, struct dentry *parent, uint8_t *value)
459 {
460
461 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u8,
462 &fops_u8_ro, &fops_u8_wo);
463 }
464
465 DEFINE_DEBUGFS_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%016llx\n");
466 DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%016llx\n");
467 DEFINE_DEBUGFS_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%016llx\n");
468
469 void
debugfs_create_x8(const char * name,umode_t mode,struct dentry * parent,uint8_t * value)470 debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, uint8_t *value)
471 {
472
473 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x8,
474 &fops_x8_ro, &fops_x8_wo);
475 }
476
477
478 static int
debugfs_u16_get(void * data,uint64_t * value)479 debugfs_u16_get(void *data, uint64_t *value)
480 {
481 uint16_t *u16data = data;
482 *value = *u16data;
483 return (0);
484 }
485
486 static int
debugfs_u16_set(void * data,uint64_t value)487 debugfs_u16_set(void *data, uint64_t value)
488 {
489 uint16_t *u16data = data;
490 *u16data = (uint16_t)value;
491 return (0);
492 }
493
494 DEFINE_DEBUGFS_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%u\n");
495 DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%u\n");
496 DEFINE_DEBUGFS_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%u\n");
497
498 void
debugfs_create_u16(const char * name,umode_t mode,struct dentry * parent,uint16_t * value)499 debugfs_create_u16(const char *name, umode_t mode, struct dentry *parent, uint16_t *value)
500 {
501
502 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u16,
503 &fops_u16_ro, &fops_u16_wo);
504 }
505
506 DEFINE_DEBUGFS_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%016llx\n");
507 DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%016llx\n");
508 DEFINE_DEBUGFS_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%016llx\n");
509
510 void
debugfs_create_x16(const char * name,umode_t mode,struct dentry * parent,uint16_t * value)511 debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, uint16_t *value)
512 {
513
514 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x16,
515 &fops_x16_ro, &fops_x16_wo);
516 }
517
518
519 static int
debugfs_u32_get(void * data,uint64_t * value)520 debugfs_u32_get(void *data, uint64_t *value)
521 {
522 uint32_t *u32data = data;
523 *value = *u32data;
524 return (0);
525 }
526
527 static int
debugfs_u32_set(void * data,uint64_t value)528 debugfs_u32_set(void *data, uint64_t value)
529 {
530 uint32_t *u32data = data;
531 *u32data = (uint32_t)value;
532 return (0);
533 }
534
535 DEFINE_DEBUGFS_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%u\n");
536 DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%u\n");
537 DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%u\n");
538
539 void
debugfs_create_u32(const char * name,umode_t mode,struct dentry * parent,uint32_t * value)540 debugfs_create_u32(const char *name, umode_t mode, struct dentry *parent, uint32_t *value)
541 {
542
543 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u32,
544 &fops_u32_ro, &fops_u32_wo);
545 }
546
547 DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%016llx\n");
548 DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%016llx\n");
549 DEFINE_DEBUGFS_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%016llx\n");
550
551 void
debugfs_create_x32(const char * name,umode_t mode,struct dentry * parent,uint32_t * value)552 debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, uint32_t *value)
553 {
554
555 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x32,
556 &fops_x32_ro, &fops_x32_wo);
557 }
558
559
560 static int
debugfs_u64_get(void * data,uint64_t * value)561 debugfs_u64_get(void *data, uint64_t *value)
562 {
563 uint64_t *u64data = data;
564 *value = *u64data;
565 return (0);
566 }
567
568 static int
debugfs_u64_set(void * data,uint64_t value)569 debugfs_u64_set(void *data, uint64_t value)
570 {
571 uint64_t *u64data = data;
572 *u64data = (uint64_t)value;
573 return (0);
574 }
575
576 DEFINE_DEBUGFS_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%u\n");
577 DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%u\n");
578 DEFINE_DEBUGFS_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%u\n");
579
580 void
debugfs_create_u64(const char * name,umode_t mode,struct dentry * parent,uint64_t * value)581 debugfs_create_u64(const char *name, umode_t mode, struct dentry *parent, uint64_t *value)
582 {
583
584 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_u64,
585 &fops_u64_ro, &fops_u64_wo);
586 }
587
588 DEFINE_DEBUGFS_ATTRIBUTE(fops_x64, debugfs_u64_get, debugfs_u64_set, "0x%016llx\n");
589 DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_ro, debugfs_u64_get, NULL, "0x%016llx\n");
590 DEFINE_DEBUGFS_ATTRIBUTE(fops_x64_wo, NULL, debugfs_u64_set, "0x%016llx\n");
591
592 void
debugfs_create_x64(const char * name,umode_t mode,struct dentry * parent,uint64_t * value)593 debugfs_create_x64(const char *name, umode_t mode, struct dentry *parent, uint64_t *value)
594 {
595
596 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_x64,
597 &fops_x64_ro, &fops_x64_wo);
598 }
599
600
601 static int
debugfs_ulong_get(void * data,uint64_t * value)602 debugfs_ulong_get(void *data, uint64_t *value)
603 {
604 uint64_t *uldata = data;
605 *value = *uldata;
606 return (0);
607 }
608
609 static int
debugfs_ulong_set(void * data,uint64_t value)610 debugfs_ulong_set(void *data, uint64_t value)
611 {
612 uint64_t *uldata = data;
613 *uldata = value;
614 return (0);
615 }
616
617 DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong, debugfs_ulong_get, debugfs_ulong_set, "%llu\n");
618 DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_ro, debugfs_ulong_get, NULL, "%llu\n");
619 DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n");
620
621 void
debugfs_create_ulong(const char * name,umode_t mode,struct dentry * parent,unsigned long * value)622 debugfs_create_ulong(const char *name, umode_t mode, struct dentry *parent, unsigned long *value)
623 {
624
625 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_ulong,
626 &fops_ulong_ro, &fops_ulong_wo);
627 }
628
629
630 static int
debugfs_atomic_t_get(void * data,uint64_t * value)631 debugfs_atomic_t_get(void *data, uint64_t *value)
632 {
633 atomic_t *atomic_data = data;
634 *value = atomic_read(atomic_data);
635 return (0);
636 }
637
638 static int
debugfs_atomic_t_set(void * data,uint64_t value)639 debugfs_atomic_t_set(void *data, uint64_t value)
640 {
641 atomic_t *atomic_data = data;
642 atomic_set(atomic_data, (int)value);
643 return (0);
644 }
645
646 DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, debugfs_atomic_t_set, "%d\n");
647 DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, "%d\n");
648 DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, "%d\n");
649
650 void
debugfs_create_atomic_t(const char * name,umode_t mode,struct dentry * parent,atomic_t * value)651 debugfs_create_atomic_t(const char *name, umode_t mode, struct dentry *parent, atomic_t *value)
652 {
653
654 debugfs_create_mode_unsafe(name, mode, parent, value, &fops_atomic_t,
655 &fops_atomic_t_ro, &fops_atomic_t_wo);
656 }
657
658
659 static int
fops_str_open(struct inode * inode,struct file * filp)660 fops_str_open(struct inode *inode, struct file *filp)
661 {
662
663 return (simple_open(inode, filp));
664 }
665
666 static ssize_t
fops_str_read(struct file * filp,char __user * ubuf,size_t read_size,loff_t * ppos)667 fops_str_read(struct file *filp, char __user *ubuf, size_t read_size,
668 loff_t *ppos)
669 {
670 ssize_t ret;
671 char *str, *str_with_newline;
672 size_t str_len, str_with_newline_len;
673
674 if (filp->private_data == NULL)
675 return (-EINVAL);
676
677 str = *(char **)filp->private_data;
678 str_len = strlen(str);
679
680 /*
681 * `str_with_newline` is terminated with a newline, but is not
682 * NUL-terminated.
683 */
684 str_with_newline_len = str_len + 1;
685 str_with_newline = kmalloc(str_with_newline_len, GFP_KERNEL);
686 if (str_with_newline == NULL)
687 return (-ENOMEM);
688
689 strncpy(str_with_newline, str, str_len);
690 str_with_newline[str_len] = '\n';
691
692 ret = simple_read_from_buffer(ubuf, read_size, ppos,
693 str_with_newline, str_with_newline_len);
694
695 kfree(str_with_newline);
696
697 return (ret);
698 }
699
700 static ssize_t
fops_str_write(struct file * filp,const char __user * buf,size_t write_size,loff_t * ppos)701 fops_str_write(struct file *filp, const char __user *buf, size_t write_size,
702 loff_t *ppos)
703 {
704 char *old, *new;
705 size_t old_len, new_len;
706
707 if (filp->private_data == NULL)
708 return (-EINVAL);
709
710 old = *(char **)filp->private_data;
711 new = NULL;
712
713 /*
714 * We enforce concatenation of the newly written value to the existing
715 * value.
716 */
717 old_len = strlen(old);
718 if (*ppos && *ppos != old_len)
719 return (-EINVAL);
720
721 new_len = old_len + write_size;
722 if (new_len + 1 > PAGE_SIZE)
723 return (-E2BIG);
724
725 new = kmalloc(new_len + 1, GFP_KERNEL);
726 if (new == NULL)
727 return (-ENOMEM);
728
729 memcpy(new, old, old_len);
730 if (copy_from_user(new + old_len, buf, write_size) != 0) {
731 kfree(new);
732 return (-EFAULT);
733 }
734
735 new[new_len] = '\0';
736 strim(new);
737
738 filp->private_data = &new;
739
740 kfree(old);
741
742 return (write_size);
743 }
744
745 static const struct file_operations fops_str = {
746 .owner = THIS_MODULE,
747 .open = fops_str_open,
748 .read = fops_str_read,
749 .write = fops_str_write,
750 .llseek = no_llseek
751 };
752 static const struct file_operations fops_str_ro = {
753 .owner = THIS_MODULE,
754 .open = fops_str_open,
755 .read = fops_str_read,
756 .llseek = no_llseek
757 };
758 static const struct file_operations fops_str_wo = {
759 .owner = THIS_MODULE,
760 .open = fops_str_open,
761 .write = fops_str_write,
762 .llseek = no_llseek
763 };
764
765 void
debugfs_create_str(const char * name,umode_t mode,struct dentry * parent,char ** value)766 debugfs_create_str(const char *name, umode_t mode, struct dentry *parent,
767 char **value)
768 {
769 debugfs_create_mode_unsafe(name, mode, parent, value,
770 &fops_str, &fops_str_ro, &fops_str_wo);
771 }
772
773
774 static ssize_t
fops_blob_read(struct file * filp,char __user * ubuf,size_t read_size,loff_t * ppos)775 fops_blob_read(struct file *filp, char __user *ubuf, size_t read_size, loff_t *ppos)
776 {
777 struct debugfs_blob_wrapper *blob;
778
779 blob = filp->private_data;
780 if (blob == NULL)
781 return (-EINVAL);
782 if (blob->size == 0 || blob->data == NULL)
783 return (-EINVAL);
784
785 return (simple_read_from_buffer(ubuf, read_size, ppos, blob->data, blob->size));
786 }
787
788 static int
fops_blob_open(struct inode * inode,struct file * filp)789 fops_blob_open(struct inode *inode, struct file *filp)
790 {
791
792 return (simple_open(inode, filp));
793 }
794
795 static const struct file_operations __fops_blob_ro = {
796 .owner = THIS_MODULE,
797 .open = fops_blob_open,
798 .read = fops_blob_read,
799 .llseek = no_llseek
800 };
801
802 struct dentry *
debugfs_create_blob(const char * name,umode_t mode,struct dentry * parent,struct debugfs_blob_wrapper * value)803 debugfs_create_blob(const char *name, umode_t mode, struct dentry *parent,
804 struct debugfs_blob_wrapper *value)
805 {
806 /* Blobs are read-only. */
807 return (debugfs_create_file(name, mode & 0444, parent, value, &__fops_blob_ro));
808 }
809
810
811 static int
lindebugfs_init(PFS_INIT_ARGS)812 lindebugfs_init(PFS_INIT_ARGS)
813 {
814
815 debugfs_root = pi->pi_root;
816
817 (void)debugfs_create_symlink("kcov", NULL, "/dev/kcov");
818
819 return (0);
820 }
821
822 static int
lindebugfs_uninit(PFS_INIT_ARGS)823 lindebugfs_uninit(PFS_INIT_ARGS)
824 {
825
826 return (0);
827 }
828
829 PSEUDOFS(lindebugfs, 1, VFCF_JAIL);
830 MODULE_DEPEND(lindebugfs, linuxkpi, 1, 1, 1);
831