Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * proc/fs/generic.c --- generic routines for the proc-fs
4 : : *
5 : : * This file contains generic proc-fs routines for handling
6 : : * directories and files.
7 : : *
8 : : * Copyright (C) 1991, 1992 Linus Torvalds.
9 : : * Copyright (C) 1997 Theodore Ts'o
10 : : */
11 : :
12 : : #include <linux/cache.h>
13 : : #include <linux/errno.h>
14 : : #include <linux/time.h>
15 : : #include <linux/proc_fs.h>
16 : : #include <linux/stat.h>
17 : : #include <linux/mm.h>
18 : : #include <linux/module.h>
19 : : #include <linux/namei.h>
20 : : #include <linux/slab.h>
21 : : #include <linux/printk.h>
22 : : #include <linux/mount.h>
23 : : #include <linux/init.h>
24 : : #include <linux/idr.h>
25 : : #include <linux/bitops.h>
26 : : #include <linux/spinlock.h>
27 : : #include <linux/completion.h>
28 : : #include <linux/uaccess.h>
29 : : #include <linux/seq_file.h>
30 : :
31 : : #include "internal.h"
32 : :
33 : : static DEFINE_RWLOCK(proc_subdir_lock);
34 : :
35 : : struct kmem_cache *proc_dir_entry_cache __ro_after_init;
36 : :
37 : 3 : void pde_free(struct proc_dir_entry *pde)
38 : : {
39 [ - + ]: 3 : if (S_ISLNK(pde->mode))
40 : 0 : kfree(pde->data);
41 [ - + ]: 3 : if (pde->name != pde->inline_name)
42 : 0 : kfree(pde->name);
43 : 3 : kmem_cache_free(proc_dir_entry_cache, pde);
44 : 3 : }
45 : :
46 : 4315 : static int proc_match(const char *name, struct proc_dir_entry *de, unsigned int len)
47 : : {
48 : 4315 : if (len < de->namelen)
49 : : return -1;
50 [ + + + + ]: 2970 : if (len > de->namelen)
51 : : return 1;
52 : :
53 : 1397 : return memcmp(name, de->name, len);
54 : : }
55 : :
56 : 3 : static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir)
57 : : {
58 [ - + - - : 3 : return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry,
- - - - ]
59 : : subdir_node);
60 : : }
61 : :
62 : 0 : static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir)
63 : : {
64 [ # # # # ]: 0 : return rb_entry_safe(rb_next(&dir->subdir_node), struct proc_dir_entry,
65 : : subdir_node);
66 : : }
67 : :
68 : 337 : static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
69 : : const char *name,
70 : : unsigned int len)
71 : : {
72 : 337 : struct rb_node *node = dir->subdir.rb_node;
73 : :
74 [ + + ]: 1694 : while (node) {
75 : 1519 : struct proc_dir_entry *de = rb_entry(node,
76 : : struct proc_dir_entry,
77 : : subdir_node);
78 [ + + ]: 1519 : int result = proc_match(name, de, len);
79 : :
80 [ + + ]: 641 : if (result < 0)
81 : 807 : node = node->rb_left;
82 [ + + ]: 712 : else if (result > 0)
83 : 550 : node = node->rb_right;
84 : : else
85 : 162 : return de;
86 : : }
87 : : return NULL;
88 : : }
89 : :
90 : 1029 : static bool pde_subdir_insert(struct proc_dir_entry *dir,
91 : : struct proc_dir_entry *de)
92 : : {
93 : 1029 : struct rb_root *root = &dir->subdir;
94 : 1029 : struct rb_node **new = &root->rb_node, *parent = NULL;
95 : :
96 : : /* Figure out where to put new node */
97 [ + + ]: 3825 : while (*new) {
98 : 2796 : struct proc_dir_entry *this = rb_entry(*new,
99 : : struct proc_dir_entry,
100 : : subdir_node);
101 [ + + ]: 2796 : int result = proc_match(de->name, this, de->namelen);
102 : :
103 : 756 : parent = *new;
104 [ + + ]: 756 : if (result < 0)
105 : 1017 : new = &(*new)->rb_left;
106 [ + - ]: 1779 : else if (result > 0)
107 : 1779 : new = &(*new)->rb_right;
108 : : else
109 : : return false;
110 : : }
111 : :
112 : : /* Add new node and rebalance tree. */
113 : 1029 : rb_link_node(&de->subdir_node, parent, new);
114 : 1029 : rb_insert_color(&de->subdir_node, root);
115 : 1029 : return true;
116 : : }
117 : :
118 : 0 : static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
119 : : {
120 : 0 : struct inode *inode = d_inode(dentry);
121 : 0 : struct proc_dir_entry *de = PDE(inode);
122 : 0 : int error;
123 : :
124 : 0 : error = setattr_prepare(dentry, iattr);
125 [ # # ]: 0 : if (error)
126 : : return error;
127 : :
128 : 0 : setattr_copy(inode, iattr);
129 : 0 : mark_inode_dirty(inode);
130 : :
131 : 0 : proc_set_user(de, inode->i_uid, inode->i_gid);
132 : 0 : de->mode = inode->i_mode;
133 : 0 : return 0;
134 : : }
135 : :
136 : 36 : static int proc_getattr(const struct path *path, struct kstat *stat,
137 : : u32 request_mask, unsigned int query_flags)
138 : : {
139 [ + - ]: 36 : struct inode *inode = d_inode(path->dentry);
140 [ + - ]: 36 : struct proc_dir_entry *de = PDE(inode);
141 [ + - ]: 36 : if (de) {
142 [ + - ]: 36 : nlink_t nlink = READ_ONCE(de->nlink);
143 [ + - ]: 36 : if (nlink > 0) {
144 : 36 : set_nlink(inode, nlink);
145 : : }
146 : : }
147 : :
148 : 36 : generic_fillattr(inode, stat);
149 : 36 : return 0;
150 : : }
151 : :
152 : : static const struct inode_operations proc_file_inode_operations = {
153 : : .setattr = proc_notify_change,
154 : : };
155 : :
156 : : /*
157 : : * This function parses a name such as "tty/driver/serial", and
158 : : * returns the struct proc_dir_entry for "/proc/tty/driver", and
159 : : * returns "serial" in residual.
160 : : */
161 : 1032 : static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
162 : : const char **residual)
163 : : {
164 : 1032 : const char *cp = name, *next;
165 : 1032 : struct proc_dir_entry *de;
166 : :
167 : 1032 : de = *ret;
168 [ + + ]: 1032 : if (!de)
169 : 231 : de = &proc_root;
170 : :
171 : 1182 : while (1) {
172 : 1182 : next = strchr(cp, '/');
173 [ + + ]: 1107 : if (!next)
174 : : break;
175 : :
176 : 75 : de = pde_subdir_find(de, cp, next - cp);
177 [ - + ]: 75 : if (!de) {
178 : 0 : WARN(1, "name '%s'\n", name);
179 : 0 : return -ENOENT;
180 : : }
181 : 75 : cp = next + 1;
182 : : }
183 : 1032 : *residual = cp;
184 : 1032 : *ret = de;
185 : 1032 : return 0;
186 : : }
187 : :
188 : 1029 : static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
189 : : const char **residual)
190 : : {
191 : 1029 : int rv;
192 : :
193 : 1029 : read_lock(&proc_subdir_lock);
194 : 1029 : rv = __xlate_proc_name(name, ret, residual);
195 : 1029 : read_unlock(&proc_subdir_lock);
196 : 1029 : return rv;
197 : : }
198 : :
199 : : static DEFINE_IDA(proc_inum_ida);
200 : :
201 : : #define PROC_DYNAMIC_FIRST 0xF0000000U
202 : :
203 : : /*
204 : : * Return an inode number between PROC_DYNAMIC_FIRST and
205 : : * 0xffffffff, or zero on failure.
206 : : */
207 : 1050 : int proc_alloc_inum(unsigned int *inum)
208 : : {
209 : 1050 : int i;
210 : :
211 : 21 : i = ida_simple_get(&proc_inum_ida, 0, UINT_MAX - PROC_DYNAMIC_FIRST + 1,
212 : : GFP_KERNEL);
213 [ + - + - ]: 1050 : if (i < 0)
214 : : return i;
215 : :
216 : 1050 : *inum = PROC_DYNAMIC_FIRST + (unsigned int)i;
217 : 21 : return 0;
218 : : }
219 : :
220 : 3 : void proc_free_inum(unsigned int inum)
221 : : {
222 : 0 : ida_simple_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
223 : 0 : }
224 : :
225 : 1434 : static int proc_misc_d_revalidate(struct dentry *dentry, unsigned int flags)
226 : : {
227 [ + + ]: 1434 : if (flags & LOOKUP_RCU)
228 : : return -ECHILD;
229 : :
230 [ - + ]: 717 : if (atomic_read(&PDE(d_inode(dentry))->in_use) < 0)
231 : 0 : return 0; /* revalidate */
232 : : return 1;
233 : : }
234 : :
235 : 371 : static int proc_misc_d_delete(const struct dentry *dentry)
236 : : {
237 : 371 : return atomic_read(&PDE(d_inode(dentry))->in_use) < 0;
238 : : }
239 : :
240 : : static const struct dentry_operations proc_misc_dentry_ops = {
241 : : .d_revalidate = proc_misc_d_revalidate,
242 : : .d_delete = proc_misc_d_delete,
243 : : };
244 : :
245 : : /*
246 : : * Don't create negative dentries here, return -ENOENT by hand
247 : : * instead.
248 : : */
249 : 259 : struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
250 : : struct proc_dir_entry *de)
251 : : {
252 : 259 : struct inode *inode;
253 : :
254 : 259 : read_lock(&proc_subdir_lock);
255 : 259 : de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len);
256 [ + + ]: 259 : if (de) {
257 : 84 : pde_get(de);
258 : 84 : read_unlock(&proc_subdir_lock);
259 : 84 : inode = proc_get_inode(dir->i_sb, de);
260 [ + - ]: 84 : if (!inode)
261 : : return ERR_PTR(-ENOMEM);
262 : 84 : d_set_d_op(dentry, de->proc_dops);
263 : 84 : return d_splice_alias(inode, dentry);
264 : : }
265 : 175 : read_unlock(&proc_subdir_lock);
266 : 175 : return ERR_PTR(-ENOENT);
267 : : }
268 : :
269 : 229 : struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
270 : : unsigned int flags)
271 : : {
272 : 229 : return proc_lookup_de(dir, dentry, PDE(dir));
273 : : }
274 : :
275 : : /*
276 : : * This returns non-zero if at EOF, so that the /proc
277 : : * root directory can use this and check if it should
278 : : * continue with the <pid> entries..
279 : : *
280 : : * Note that the VFS-layer doesn't care about the return
281 : : * value of the readdir() call, as long as it's non-negative
282 : : * for success..
283 : : */
284 : 0 : int proc_readdir_de(struct file *file, struct dir_context *ctx,
285 : : struct proc_dir_entry *de)
286 : : {
287 : 0 : int i;
288 : :
289 [ # # ]: 0 : if (!dir_emit_dots(file, ctx))
290 : : return 0;
291 : :
292 : 0 : i = ctx->pos - 2;
293 : 0 : read_lock(&proc_subdir_lock);
294 : 0 : de = pde_subdir_first(de);
295 : 0 : for (;;) {
296 [ # # ]: 0 : if (!de) {
297 : 0 : read_unlock(&proc_subdir_lock);
298 : 0 : return 0;
299 : : }
300 [ # # ]: 0 : if (!i)
301 : : break;
302 : 0 : de = pde_subdir_next(de);
303 : 0 : i--;
304 : : }
305 : :
306 : 0 : do {
307 : 0 : struct proc_dir_entry *next;
308 : 0 : pde_get(de);
309 : 0 : read_unlock(&proc_subdir_lock);
310 [ # # ]: 0 : if (!dir_emit(ctx, de->name, de->namelen,
311 : 0 : de->low_ino, de->mode >> 12)) {
312 : 0 : pde_put(de);
313 : 0 : return 0;
314 : : }
315 : 0 : ctx->pos++;
316 : 0 : read_lock(&proc_subdir_lock);
317 : 0 : next = pde_subdir_next(de);
318 : 0 : pde_put(de);
319 : 0 : de = next;
320 [ # # ]: 0 : } while (de);
321 : 0 : read_unlock(&proc_subdir_lock);
322 : 0 : return 1;
323 : : }
324 : :
325 : 0 : int proc_readdir(struct file *file, struct dir_context *ctx)
326 : : {
327 : 0 : struct inode *inode = file_inode(file);
328 : :
329 : 0 : return proc_readdir_de(file, ctx, PDE(inode));
330 : : }
331 : :
332 : : /*
333 : : * These are the generic /proc directory operations. They
334 : : * use the in-memory "struct proc_dir_entry" tree to parse
335 : : * the /proc directory.
336 : : */
337 : : static const struct file_operations proc_dir_operations = {
338 : : .llseek = generic_file_llseek,
339 : : .read = generic_read_dir,
340 : : .iterate_shared = proc_readdir,
341 : : };
342 : :
343 : : /*
344 : : * proc directories can do almost nothing..
345 : : */
346 : : static const struct inode_operations proc_dir_inode_operations = {
347 : : .lookup = proc_lookup,
348 : : .getattr = proc_getattr,
349 : : .setattr = proc_notify_change,
350 : : };
351 : :
352 : : /* returns the registered entry, or frees dp and returns NULL on failure */
353 : 1029 : struct proc_dir_entry *proc_register(struct proc_dir_entry *dir,
354 : : struct proc_dir_entry *dp)
355 : : {
356 : 1029 : if (proc_alloc_inum(&dp->low_ino))
357 : 0 : goto out_free_entry;
358 : :
359 : 1029 : write_lock(&proc_subdir_lock);
360 : 1029 : dp->parent = dir;
361 [ - + ]: 1029 : if (pde_subdir_insert(dir, dp) == false) {
362 : 0 : WARN(1, "proc_dir_entry '%s/%s' already registered\n",
363 : : dir->name, dp->name);
364 : 0 : write_unlock(&proc_subdir_lock);
365 : 0 : goto out_free_inum;
366 : : }
367 : 1029 : dir->nlink++;
368 : 1029 : write_unlock(&proc_subdir_lock);
369 : :
370 : 1029 : return dp;
371 : : out_free_inum:
372 : 0 : proc_free_inum(dp->low_ino);
373 : 0 : out_free_entry:
374 : 0 : pde_free(dp);
375 : 0 : return NULL;
376 : : }
377 : :
378 : 1029 : static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
379 : : const char *name,
380 : : umode_t mode,
381 : : nlink_t nlink)
382 : : {
383 : 1029 : struct proc_dir_entry *ent = NULL;
384 : 1029 : const char *fn;
385 : 1029 : struct qstr qstr;
386 : :
387 [ - + ]: 1029 : if (xlate_proc_name(name, parent, &fn) != 0)
388 : 0 : goto out;
389 : 1029 : qstr.name = fn;
390 : 1029 : qstr.len = strlen(fn);
391 [ - + ]: 1029 : if (qstr.len == 0 || qstr.len >= 256) {
392 : 0 : WARN(1, "name len %u\n", qstr.len);
393 : 0 : return NULL;
394 : : }
395 [ + + - + ]: 1029 : if (qstr.len == 1 && fn[0] == '.') {
396 : 0 : WARN(1, "name '.'\n");
397 : 0 : return NULL;
398 : : }
399 [ + + - + : 1029 : if (qstr.len == 2 && fn[0] == '.' && fn[1] == '.') {
- - ]
400 : 0 : WARN(1, "name '..'\n");
401 : 0 : return NULL;
402 : : }
403 [ + + - + ]: 1029 : if (*parent == &proc_root && name_to_int(&qstr) != ~0U) {
404 : 0 : WARN(1, "create '/proc/%s' by hand\n", qstr.name);
405 : 0 : return NULL;
406 : : }
407 [ + + - + ]: 2058 : if (is_empty_pde(*parent)) {
408 : 0 : WARN(1, "attempt to add to permanently empty directory");
409 : 0 : return NULL;
410 : : }
411 : :
412 : 1029 : ent = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL);
413 [ - + ]: 1029 : if (!ent)
414 : 0 : goto out;
415 : :
416 [ + + ]: 1029 : if (qstr.len + 1 <= SIZEOF_PDE_INLINE_NAME) {
417 : 849 : ent->name = ent->inline_name;
418 : : } else {
419 [ - + ]: 180 : ent->name = kmalloc(qstr.len + 1, GFP_KERNEL);
420 [ - + ]: 180 : if (!ent->name) {
421 : 0 : pde_free(ent);
422 : 0 : return NULL;
423 : : }
424 : : }
425 : :
426 : 1029 : memcpy(ent->name, fn, qstr.len + 1);
427 : 1029 : ent->namelen = qstr.len;
428 : 1029 : ent->mode = mode;
429 : 1029 : ent->nlink = nlink;
430 : 1029 : ent->subdir = RB_ROOT;
431 : 1029 : refcount_set(&ent->refcnt, 1);
432 : 1029 : spin_lock_init(&ent->pde_unload_lock);
433 : 1029 : INIT_LIST_HEAD(&ent->pde_openers);
434 : 1029 : proc_set_user(ent, (*parent)->uid, (*parent)->gid);
435 : :
436 : 1029 : ent->proc_dops = &proc_misc_dentry_ops;
437 : :
438 : : out:
439 : : return ent;
440 : : }
441 : :
442 : 12 : struct proc_dir_entry *proc_symlink(const char *name,
443 : : struct proc_dir_entry *parent, const char *dest)
444 : : {
445 : 12 : struct proc_dir_entry *ent;
446 : :
447 : 12 : ent = __proc_create(&parent, name,
448 : : (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
449 : :
450 [ + - ]: 12 : if (ent) {
451 [ - + ]: 12 : ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
452 [ + - ]: 12 : if (ent->data) {
453 : 12 : strcpy((char*)ent->data,dest);
454 : 12 : ent->proc_iops = &proc_link_inode_operations;
455 : 12 : ent = proc_register(parent, ent);
456 : : } else {
457 : 0 : pde_free(ent);
458 : 0 : ent = NULL;
459 : : }
460 : : }
461 : 12 : return ent;
462 : : }
463 : : EXPORT_SYMBOL(proc_symlink);
464 : :
465 : 180 : struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
466 : : struct proc_dir_entry *parent, void *data)
467 : : {
468 : 180 : struct proc_dir_entry *ent;
469 : :
470 [ + + ]: 180 : if (mode == 0)
471 : 174 : mode = S_IRUGO | S_IXUGO;
472 : :
473 : 180 : ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
474 [ + - ]: 180 : if (ent) {
475 : 180 : ent->data = data;
476 : 180 : ent->proc_dir_ops = &proc_dir_operations;
477 : 180 : ent->proc_iops = &proc_dir_inode_operations;
478 : 180 : ent = proc_register(parent, ent);
479 : : }
480 : 180 : return ent;
481 : : }
482 : : EXPORT_SYMBOL_GPL(proc_mkdir_data);
483 : :
484 : 6 : struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
485 : : struct proc_dir_entry *parent)
486 : : {
487 : 6 : return proc_mkdir_data(name, mode, parent, NULL);
488 : : }
489 : : EXPORT_SYMBOL(proc_mkdir_mode);
490 : :
491 : 162 : struct proc_dir_entry *proc_mkdir(const char *name,
492 : : struct proc_dir_entry *parent)
493 : : {
494 : 162 : return proc_mkdir_data(name, 0, parent, NULL);
495 : : }
496 : : EXPORT_SYMBOL(proc_mkdir);
497 : :
498 : 3 : struct proc_dir_entry *proc_create_mount_point(const char *name)
499 : : {
500 : 3 : umode_t mode = S_IFDIR | S_IRUGO | S_IXUGO;
501 : 3 : struct proc_dir_entry *ent, *parent = NULL;
502 : :
503 : 3 : ent = __proc_create(&parent, name, mode, 2);
504 [ + - ]: 3 : if (ent) {
505 : 3 : ent->data = NULL;
506 : 3 : ent->proc_dir_ops = NULL;
507 : 3 : ent->proc_iops = NULL;
508 : 3 : ent = proc_register(parent, ent);
509 : : }
510 : 3 : return ent;
511 : : }
512 : : EXPORT_SYMBOL(proc_create_mount_point);
513 : :
514 : 834 : struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode,
515 : : struct proc_dir_entry **parent, void *data)
516 : : {
517 : 834 : struct proc_dir_entry *p;
518 : :
519 [ + + ]: 834 : if ((mode & S_IFMT) == 0)
520 : 741 : mode |= S_IFREG;
521 [ + + ]: 834 : if ((mode & S_IALLUGO) == 0)
522 : 147 : mode |= S_IRUGO;
523 [ - + + - ]: 834 : if (WARN_ON_ONCE(!S_ISREG(mode)))
524 : : return NULL;
525 : :
526 : 834 : p = __proc_create(parent, name, mode, 1);
527 [ + - ]: 834 : if (p) {
528 : 834 : p->proc_iops = &proc_file_inode_operations;
529 : 834 : p->data = data;
530 : : }
531 : : return p;
532 : : }
533 : :
534 : 273 : struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
535 : : struct proc_dir_entry *parent,
536 : : const struct proc_ops *proc_ops, void *data)
537 : : {
538 : 273 : struct proc_dir_entry *p;
539 : :
540 : 273 : p = proc_create_reg(name, mode, &parent, data);
541 [ + - ]: 273 : if (!p)
542 : : return NULL;
543 : 273 : p->proc_ops = proc_ops;
544 : 273 : return proc_register(parent, p);
545 : : }
546 : : EXPORT_SYMBOL(proc_create_data);
547 : :
548 : 75 : struct proc_dir_entry *proc_create(const char *name, umode_t mode,
549 : : struct proc_dir_entry *parent,
550 : : const struct proc_ops *proc_ops)
551 : : {
552 : 75 : return proc_create_data(name, mode, parent, proc_ops, NULL);
553 : : }
554 : : EXPORT_SYMBOL(proc_create);
555 : :
556 : 0 : static int proc_seq_open(struct inode *inode, struct file *file)
557 : : {
558 [ # # ]: 0 : struct proc_dir_entry *de = PDE(inode);
559 : :
560 [ # # ]: 0 : if (de->state_size)
561 : 0 : return seq_open_private(file, de->seq_ops, de->state_size);
562 : 0 : return seq_open(file, de->seq_ops);
563 : : }
564 : :
565 : 0 : static int proc_seq_release(struct inode *inode, struct file *file)
566 : : {
567 [ # # ]: 0 : struct proc_dir_entry *de = PDE(inode);
568 : :
569 [ # # ]: 0 : if (de->state_size)
570 : 0 : return seq_release_private(inode, file);
571 : 0 : return seq_release(inode, file);
572 : : }
573 : :
574 : : static const struct proc_ops proc_seq_ops = {
575 : : .proc_open = proc_seq_open,
576 : : .proc_read = seq_read,
577 : : .proc_lseek = seq_lseek,
578 : : .proc_release = proc_seq_release,
579 : : };
580 : :
581 : 105 : struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
582 : : struct proc_dir_entry *parent, const struct seq_operations *ops,
583 : : unsigned int state_size, void *data)
584 : : {
585 : 105 : struct proc_dir_entry *p;
586 : :
587 : 105 : p = proc_create_reg(name, mode, &parent, data);
588 [ + - ]: 105 : if (!p)
589 : : return NULL;
590 : 105 : p->proc_ops = &proc_seq_ops;
591 : 105 : p->seq_ops = ops;
592 : 105 : p->state_size = state_size;
593 : 105 : return proc_register(parent, p);
594 : : }
595 : : EXPORT_SYMBOL(proc_create_seq_private);
596 : :
597 : 210 : static int proc_single_open(struct inode *inode, struct file *file)
598 : : {
599 : 210 : struct proc_dir_entry *de = PDE(inode);
600 : :
601 : 210 : return single_open(file, de->single_show, de->data);
602 : : }
603 : :
604 : : static const struct proc_ops proc_single_ops = {
605 : : .proc_open = proc_single_open,
606 : : .proc_read = seq_read,
607 : : .proc_lseek = seq_lseek,
608 : : .proc_release = single_release,
609 : : };
610 : :
611 : 315 : struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
612 : : struct proc_dir_entry *parent,
613 : : int (*show)(struct seq_file *, void *), void *data)
614 : : {
615 : 315 : struct proc_dir_entry *p;
616 : :
617 : 315 : p = proc_create_reg(name, mode, &parent, data);
618 [ + - ]: 315 : if (!p)
619 : : return NULL;
620 : 315 : p->proc_ops = &proc_single_ops;
621 : 315 : p->single_show = show;
622 : 315 : return proc_register(parent, p);
623 : : }
624 : : EXPORT_SYMBOL(proc_create_single_data);
625 : :
626 : 51 : void proc_set_size(struct proc_dir_entry *de, loff_t size)
627 : : {
628 : 51 : de->size = size;
629 : 51 : }
630 : : EXPORT_SYMBOL(proc_set_size);
631 : :
632 : 1059 : void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
633 : : {
634 : 1059 : de->uid = uid;
635 : 1029 : de->gid = gid;
636 : 30 : }
637 : : EXPORT_SYMBOL(proc_set_user);
638 : :
639 : 33 : void pde_put(struct proc_dir_entry *pde)
640 : : {
641 [ + + ]: 33 : if (refcount_dec_and_test(&pde->refcnt)) {
642 : 3 : proc_free_inum(pde->low_ino);
643 : 3 : pde_free(pde);
644 : : }
645 : 33 : }
646 : :
647 : : /*
648 : : * Remove a /proc entry and free it if it's not currently in use.
649 : : */
650 : 0 : void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
651 : : {
652 : 0 : struct proc_dir_entry *de = NULL;
653 : 0 : const char *fn = name;
654 : 0 : unsigned int len;
655 : :
656 : 0 : write_lock(&proc_subdir_lock);
657 [ # # ]: 0 : if (__xlate_proc_name(name, &parent, &fn) != 0) {
658 : 0 : write_unlock(&proc_subdir_lock);
659 : 0 : return;
660 : : }
661 : 0 : len = strlen(fn);
662 : :
663 : 0 : de = pde_subdir_find(parent, fn, len);
664 [ # # ]: 0 : if (de) {
665 : 0 : rb_erase(&de->subdir_node, &parent->subdir);
666 [ # # ]: 0 : if (S_ISDIR(de->mode)) {
667 : 0 : parent->nlink--;
668 : : }
669 : : }
670 : 0 : write_unlock(&proc_subdir_lock);
671 [ # # ]: 0 : if (!de) {
672 : 0 : WARN(1, "name '%s'\n", name);
673 : 0 : return;
674 : : }
675 : :
676 : 0 : proc_entry_rundown(de);
677 : :
678 [ # # ]: 0 : WARN(pde_subdir_first(de),
679 : : "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n",
680 : : __func__, de->parent->name, de->name, pde_subdir_first(de)->name);
681 : 0 : pde_put(de);
682 : : }
683 : : EXPORT_SYMBOL(remove_proc_entry);
684 : :
685 : 3 : int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
686 : : {
687 : 3 : struct proc_dir_entry *root = NULL, *de, *next;
688 : 3 : const char *fn = name;
689 : 3 : unsigned int len;
690 : :
691 : 3 : write_lock(&proc_subdir_lock);
692 [ - + ]: 3 : if (__xlate_proc_name(name, &parent, &fn) != 0) {
693 : 0 : write_unlock(&proc_subdir_lock);
694 : 0 : return -ENOENT;
695 : : }
696 : 3 : len = strlen(fn);
697 : :
698 : 3 : root = pde_subdir_find(parent, fn, len);
699 [ - + ]: 3 : if (!root) {
700 : 0 : write_unlock(&proc_subdir_lock);
701 : 0 : return -ENOENT;
702 : : }
703 : 3 : rb_erase(&root->subdir_node, &parent->subdir);
704 : :
705 : 3 : de = root;
706 : 3 : while (1) {
707 : 3 : next = pde_subdir_first(de);
708 [ # # ]: 0 : if (next) {
709 : 0 : rb_erase(&next->subdir_node, &de->subdir);
710 : 0 : de = next;
711 : 0 : continue;
712 : : }
713 : 3 : next = de->parent;
714 [ + - ]: 3 : if (S_ISDIR(de->mode))
715 : 3 : next->nlink--;
716 : 3 : write_unlock(&proc_subdir_lock);
717 : :
718 : 3 : proc_entry_rundown(de);
719 [ - + ]: 3 : if (de == root)
720 : : break;
721 : 0 : pde_put(de);
722 : :
723 : 0 : write_lock(&proc_subdir_lock);
724 : 0 : de = next;
725 : : }
726 : 3 : pde_put(root);
727 : 3 : return 0;
728 : : }
729 : : EXPORT_SYMBOL(remove_proc_subtree);
730 : :
731 : 0 : void *proc_get_parent_data(const struct inode *inode)
732 : : {
733 : 0 : struct proc_dir_entry *de = PDE(inode);
734 : 0 : return de->parent->data;
735 : : }
736 : : EXPORT_SYMBOL_GPL(proc_get_parent_data);
737 : :
738 : 3 : void proc_remove(struct proc_dir_entry *de)
739 : : {
740 [ + - ]: 3 : if (de)
741 : 3 : remove_proc_subtree(de->name, de->parent);
742 : 3 : }
743 : : EXPORT_SYMBOL(proc_remove);
744 : :
745 : 0 : void *PDE_DATA(const struct inode *inode)
746 : : {
747 : 0 : return __PDE_DATA(inode);
748 : : }
749 : : EXPORT_SYMBOL(PDE_DATA);
750 : :
751 : : /*
752 : : * Pull a user buffer into memory and pass it to the file's write handler if
753 : : * one is supplied. The ->write() method is permitted to modify the
754 : : * kernel-side buffer.
755 : : */
756 : 0 : ssize_t proc_simple_write(struct file *f, const char __user *ubuf, size_t size,
757 : : loff_t *_pos)
758 : : {
759 [ # # ]: 0 : struct proc_dir_entry *pde = PDE(file_inode(f));
760 : 0 : char *buf;
761 : 0 : int ret;
762 : :
763 [ # # ]: 0 : if (!pde->write)
764 : : return -EACCES;
765 [ # # ]: 0 : if (size == 0 || size > PAGE_SIZE - 1)
766 : : return -EINVAL;
767 : 0 : buf = memdup_user_nul(ubuf, size);
768 [ # # ]: 0 : if (IS_ERR(buf))
769 : 0 : return PTR_ERR(buf);
770 : 0 : ret = pde->write(f, buf, size);
771 : 0 : kfree(buf);
772 [ # # ]: 0 : return ret == 0 ? size : ret;
773 : : }
|