1
2
3
4
5#include <linux/init.h>
6#include <linux/sysctl.h>
7#include <linux/poll.h>
8#include <linux/proc_fs.h>
9#include <linux/printk.h>
10#include <linux/security.h>
11#include <linux/sched.h>
12#include <linux/cred.h>
13#include <linux/namei.h>
14#include <linux/mm.h>
15#include <linux/module.h>
16#include "internal.h"
17
18static const struct dentry_operations proc_sys_dentry_operations;
19static const struct file_operations proc_sys_file_operations;
20static const struct inode_operations proc_sys_inode_operations;
21static const struct file_operations proc_sys_dir_file_operations;
22static const struct inode_operations proc_sys_dir_operations;
23
24
25
26struct ctl_table sysctl_mount_point[] = {
27 { }
28};
29
30static bool is_empty_dir(struct ctl_table_header *head)
31{
32 return head->ctl_table[0].child == sysctl_mount_point;
33}
34
35static void set_empty_dir(struct ctl_dir *dir)
36{
37 dir->header.ctl_table[0].child = sysctl_mount_point;
38}
39
40static void clear_empty_dir(struct ctl_dir *dir)
41
42{
43 dir->header.ctl_table[0].child = NULL;
44}
45
46void proc_sys_poll_notify(struct ctl_table_poll *poll)
47{
48 if (!poll)
49 return;
50
51 atomic_inc(&poll->event);
52 wake_up_interruptible(&poll->wait);
53}
54
55static struct ctl_table root_table[] = {
56 {
57 .procname = "",
58 .mode = S_IFDIR|S_IRUGO|S_IXUGO,
59 },
60 { }
61};
62static struct ctl_table_root sysctl_table_root = {
63 .default_set.dir.header = {
64 {{.count = 1,
65 .nreg = 1,
66 .ctl_table = root_table }},
67 .ctl_table_arg = root_table,
68 .root = &sysctl_table_root,
69 .set = &sysctl_table_root.default_set,
70 },
71};
72
73static DEFINE_SPINLOCK(sysctl_lock);
74
75static void drop_sysctl_table(struct ctl_table_header *header);
76static int sysctl_follow_link(struct ctl_table_header **phead,
77 struct ctl_table **pentry);
78static int insert_links(struct ctl_table_header *head);
79static void put_links(struct ctl_table_header *header);
80
81static void sysctl_print_dir(struct ctl_dir *dir)
82{
83 if (dir->header.parent)
84 sysctl_print_dir(dir->header.parent);
85 pr_cont("%s/", dir->header.ctl_table[0].procname);
86}
87
88static int namecmp(const char *name1, int len1, const char *name2, int len2)
89{
90 int minlen;
91 int cmp;
92
93 minlen = len1;
94 if (minlen > len2)
95 minlen = len2;
96
97 cmp = memcmp(name1, name2, minlen);
98 if (cmp == 0)
99 cmp = len1 - len2;
100 return cmp;
101}
102
103
104static struct ctl_table *find_entry(struct ctl_table_header **phead,
105 struct ctl_dir *dir, const char *name, int namelen)
106{
107 struct ctl_table_header *head;
108 struct ctl_table *entry;
109 struct rb_node *node = dir->root.rb_node;
110
111 while (node)
112 {
113 struct ctl_node *ctl_node;
114 const char *procname;
115 int cmp;
116
117 ctl_node = rb_entry(node, struct ctl_node, node);
118 head = ctl_node->header;
119 entry = &head->ctl_table[ctl_node - head->node];
120 procname = entry->procname;
121
122 cmp = namecmp(name, namelen, procname, strlen(procname));
123 if (cmp < 0)
124 node = node->rb_left;
125 else if (cmp > 0)
126 node = node->rb_right;
127 else {
128 *phead = head;
129 return entry;
130 }
131 }
132 return NULL;
133}
134
135static int insert_entry(struct ctl_table_header *head, struct ctl_table *entry)
136{
137 struct rb_node *node = &head->node[entry - head->ctl_table].node;
138 struct rb_node **p = &head->parent->root.rb_node;
139 struct rb_node *parent = NULL;
140 const char *name = entry->procname;
141 int namelen = strlen(name);
142
143 while (*p) {
144 struct ctl_table_header *parent_head;
145 struct ctl_table *parent_entry;
146 struct ctl_node *parent_node;
147 const char *parent_name;
148 int cmp;
149
150 parent = *p;
151 parent_node = rb_entry(parent, struct ctl_node, node);
152 parent_head = parent_node->header;
153 parent_entry = &parent_head->ctl_table[parent_node - parent_head->node];
154 parent_name = parent_entry->procname;
155
156 cmp = namecmp(name, namelen, parent_name, strlen(parent_name));
157 if (cmp < 0)
158 p = &(*p)->rb_left;
159 else if (cmp > 0)
160 p = &(*p)->rb_right;
161 else {
162 pr_err("sysctl duplicate entry: ");
163 sysctl_print_dir(head->parent);
164 pr_cont("/%s\n", entry->procname);
165 return -EEXIST;
166 }
167 }
168
169 rb_link_node(node, parent, p);
170 rb_insert_color(node, &head->parent->root);
171 return 0;
172}
173
174static void erase_entry(struct ctl_table_header *head, struct ctl_table *entry)
175{
176 struct rb_node *node = &head->node[entry - head->ctl_table].node;
177
178 rb_erase(node, &head->parent->root);
179}
180
181static void init_header(struct ctl_table_header *head,
182 struct ctl_table_root *root, struct ctl_table_set *set,
183 struct ctl_node *node, struct ctl_table *table)
184{
185 head->ctl_table = table;
186 head->ctl_table_arg = table;
187 head->used = 0;
188 head->count = 1;
189 head->nreg = 1;
190 head->unregistering = NULL;
191 head->root = root;
192 head->set = set;
193 head->parent = NULL;
194 head->node = node;
195 INIT_HLIST_HEAD(&head->inodes);
196 if (node) {
197 struct ctl_table *entry;
198 for (entry = table; entry->procname; entry++, node++)
199 node->header = head;
200 }
201}
202
203static void erase_header(struct ctl_table_header *head)
204{
205 struct ctl_table *entry;
206 for (entry = head->ctl_table; entry->procname; entry++)
207 erase_entry(head, entry);
208}
209
210static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
211{
212 struct ctl_table *entry;
213 int err;
214
215
216 if (is_empty_dir(&dir->header))
217 return -EROFS;
218
219
220 if (header->ctl_table == sysctl_mount_point) {
221 if (!RB_EMPTY_ROOT(&dir->root))
222 return -EINVAL;
223 set_empty_dir(dir);
224 }
225
226 dir->header.nreg++;
227 header->parent = dir;
228 err = insert_links(header);
229 if (err)
230 goto fail_links;
231 for (entry = header->ctl_table; entry->procname; entry++) {
232 err = insert_entry(header, entry);
233 if (err)
234 goto fail;
235 }
236 return 0;
237fail:
238 erase_header(header);
239 put_links(header);
240fail_links:
241 if (header->ctl_table == sysctl_mount_point)
242 clear_empty_dir(dir);
243 header->parent = NULL;
244 drop_sysctl_table(&dir->header);
245 return err;
246}
247
248
249static int use_table(struct ctl_table_header *p)
250{
251 if (unlikely(p->unregistering))
252 return 0;
253 p->used++;
254 return 1;
255}
256
257
258static void unuse_table(struct ctl_table_header *p)
259{
260 if (!--p->used)
261 if (unlikely(p->unregistering))
262 complete(p->unregistering);
263}
264
265static void proc_sys_prune_dcache(struct ctl_table_header *head)
266{
267 struct inode *inode;
268 struct proc_inode *ei;
269 struct hlist_node *node;
270 struct super_block *sb;
271
272 rcu_read_lock();
273 for (;;) {
274 node = hlist_first_rcu(&head->inodes);
275 if (!node)
276 break;
277 ei = hlist_entry(node, struct proc_inode, sysctl_inodes);
278 spin_lock(&sysctl_lock);
279 hlist_del_init_rcu(&ei->sysctl_inodes);
280 spin_unlock(&sysctl_lock);
281
282 inode = &ei->vfs_inode;
283 sb = inode->i_sb;
284 if (!atomic_inc_not_zero(&sb->s_active))
285 continue;
286 inode = igrab(inode);
287 rcu_read_unlock();
288 if (unlikely(!inode)) {
289 deactivate_super(sb);
290 rcu_read_lock();
291 continue;
292 }
293
294 d_prune_aliases(inode);
295 iput(inode);
296 deactivate_super(sb);
297
298 rcu_read_lock();
299 }
300 rcu_read_unlock();
301}
302
303
304static void start_unregistering(struct ctl_table_header *p)
305{
306
307
308
309
310 if (unlikely(p->used)) {
311 struct completion wait;
312 init_completion(&wait);
313 p->unregistering = &wait;
314 spin_unlock(&sysctl_lock);
315 wait_for_completion(&wait);
316 } else {
317
318 p->unregistering = ERR_PTR(-EINVAL);
319 spin_unlock(&sysctl_lock);
320 }
321
322
323
324
325 proc_sys_prune_dcache(p);
326
327
328
329
330 spin_lock(&sysctl_lock);
331 erase_header(p);
332}
333
334static struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
335{
336 BUG_ON(!head);
337 spin_lock(&sysctl_lock);
338 if (!use_table(head))
339 head = ERR_PTR(-ENOENT);
340 spin_unlock(&sysctl_lock);
341 return head;
342}
343
344static void sysctl_head_finish(struct ctl_table_header *head)
345{
346 if (!head)
347 return;
348 spin_lock(&sysctl_lock);
349 unuse_table(head);
350 spin_unlock(&sysctl_lock);
351}
352
353static struct ctl_table_set *
354lookup_header_set(struct ctl_table_root *root)
355{
356 struct ctl_table_set *set = &root->default_set;
357 if (root->lookup)
358 set = root->lookup(root);
359 return set;
360}
361
362static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
363 struct ctl_dir *dir,
364 const char *name, int namelen)
365{
366 struct ctl_table_header *head;
367 struct ctl_table *entry;
368
369 spin_lock(&sysctl_lock);
370 entry = find_entry(&head, dir, name, namelen);
371 if (entry && use_table(head))
372 *phead = head;
373 else
374 entry = NULL;
375 spin_unlock(&sysctl_lock);
376 return entry;
377}
378
379static struct ctl_node *first_usable_entry(struct rb_node *node)
380{
381 struct ctl_node *ctl_node;
382
383 for (;node; node = rb_next(node)) {
384 ctl_node = rb_entry(node, struct ctl_node, node);
385 if (use_table(ctl_node->header))
386 return ctl_node;
387 }
388 return NULL;
389}
390
391static void first_entry(struct ctl_dir *dir,
392 struct ctl_table_header **phead, struct ctl_table **pentry)
393{
394 struct ctl_table_header *head = NULL;
395 struct ctl_table *entry = NULL;
396 struct ctl_node *ctl_node;
397
398 spin_lock(&sysctl_lock);
399 ctl_node = first_usable_entry(rb_first(&dir->root));
400 spin_unlock(&sysctl_lock);
401 if (ctl_node) {
402 head = ctl_node->header;
403 entry = &head->ctl_table[ctl_node - head->node];
404 }
405 *phead = head;
406 *pentry = entry;
407}
408
409static void next_entry(struct ctl_table_header **phead, struct ctl_table **pentry)
410{
411 struct ctl_table_header *head = *phead;
412 struct ctl_table *entry = *pentry;
413 struct ctl_node *ctl_node = &head->node[entry - head->ctl_table];
414
415 spin_lock(&sysctl_lock);
416 unuse_table(head);
417
418 ctl_node = first_usable_entry(rb_next(&ctl_node->node));
419 spin_unlock(&sysctl_lock);
420 head = NULL;
421 if (ctl_node) {
422 head = ctl_node->header;
423 entry = &head->ctl_table[ctl_node - head->node];
424 }
425 *phead = head;
426 *pentry = entry;
427}
428
429
430
431
432
433
434static int test_perm(int mode, int op)
435{
436 if (uid_eq(current_euid(), GLOBAL_ROOT_UID))
437 mode >>= 6;
438 else if (in_egroup_p(GLOBAL_ROOT_GID))
439 mode >>= 3;
440 if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0)
441 return 0;
442 return -EACCES;
443}
444
445static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, int op)
446{
447 struct ctl_table_root *root = head->root;
448 int mode;
449
450 if (root->permissions)
451 mode = root->permissions(head, table);
452 else
453 mode = table->mode;
454
455 return test_perm(mode, op);
456}
457
458static struct inode *proc_sys_make_inode(struct super_block *sb,
459 struct ctl_table_header *head, struct ctl_table *table)
460{
461 struct ctl_table_root *root = head->root;
462 struct inode *inode;
463 struct proc_inode *ei;
464
465 inode = new_inode(sb);
466 if (!inode)
467 goto out;
468
469 inode->i_ino = get_next_ino();
470
471 ei = PROC_I(inode);
472
473 spin_lock(&sysctl_lock);
474 if (unlikely(head->unregistering)) {
475 spin_unlock(&sysctl_lock);
476 iput(inode);
477 inode = NULL;
478 goto out;
479 }
480 ei->sysctl = head;
481 ei->sysctl_entry = table;
482 hlist_add_head_rcu(&ei->sysctl_inodes, &head->inodes);
483 head->count++;
484 spin_unlock(&sysctl_lock);
485
486 inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
487 inode->i_mode = table->mode;
488 if (!S_ISDIR(table->mode)) {
489 inode->i_mode |= S_IFREG;
490 inode->i_op = &proc_sys_inode_operations;
491 inode->i_fop = &proc_sys_file_operations;
492 } else {
493 inode->i_mode |= S_IFDIR;
494 inode->i_op = &proc_sys_dir_operations;
495 inode->i_fop = &proc_sys_dir_file_operations;
496 if (is_empty_dir(head))
497 make_empty_dir_inode(inode);
498 }
499
500 if (root->set_ownership)
501 root->set_ownership(head, table, &inode->i_uid, &inode->i_gid);
502
503out:
504 return inode;
505}
506
507void proc_sys_evict_inode(struct inode *inode, struct ctl_table_header *head)
508{
509 spin_lock(&sysctl_lock);
510 hlist_del_init_rcu(&PROC_I(inode)->sysctl_inodes);
511 if (!--head->count)
512 kfree_rcu(head, rcu);
513 spin_unlock(&sysctl_lock);
514}
515
516static struct ctl_table_header *grab_header(struct inode *inode)
517{
518 struct ctl_table_header *head = PROC_I(inode)->sysctl;
519 if (!head)
520 head = &sysctl_table_root.default_set.dir.header;
521 return sysctl_head_grab(head);
522}
523
524static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
525 unsigned int flags)
526{
527 struct ctl_table_header *head = grab_header(dir);
528 struct ctl_table_header *h = NULL;
529 const struct qstr *name = &dentry->d_name;
530 struct ctl_table *p;
531 struct inode *inode;
532 struct dentry *err = ERR_PTR(-ENOENT);
533 struct ctl_dir *ctl_dir;
534 int ret;
535
536 if (IS_ERR(head))
537 return ERR_CAST(head);
538
539 ctl_dir = container_of(head, struct ctl_dir, header);
540
541 p = lookup_entry(&h, ctl_dir, name->name, name->len);
542 if (!p)
543 goto out;
544
545 if (S_ISLNK(p->mode)) {
546 ret = sysctl_follow_link(&h, &p);
547 err = ERR_PTR(ret);
548 if (ret)
549 goto out;
550 }
551
552 err = ERR_PTR(-ENOMEM);
553 inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
554 if (!inode)
555 goto out;
556
557 d_set_d_op(dentry, &proc_sys_dentry_operations);
558 err = d_splice_alias(inode, dentry);
559
560out:
561 if (h)
562 sysctl_head_finish(h);
563 sysctl_head_finish(head);
564 return err;
565}
566
567static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
568 size_t count, loff_t *ppos, int write)
569{
570 struct inode *inode = file_inode(filp);
571 struct ctl_table_header *head = grab_header(inode);
572 struct ctl_table *table = PROC_I(inode)->sysctl_entry;
573 ssize_t error;
574 size_t res;
575
576 if (IS_ERR(head))
577 return PTR_ERR(head);
578
579
580
581
582
583 error = -EPERM;
584 if (sysctl_perm(head, table, write ? MAY_WRITE : MAY_READ))
585 goto out;
586
587
588 error = -EINVAL;
589 if (!table->proc_handler)
590 goto out;
591
592
593 res = count;
594 error = table->proc_handler(table, write, buf, &res, ppos);
595 if (!error)
596 error = res;
597out:
598 sysctl_head_finish(head);
599
600 return error;
601}
602
603static ssize_t proc_sys_read(struct file *filp, char __user *buf,
604 size_t count, loff_t *ppos)
605{
606 return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 0);
607}
608
609static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
610 size_t count, loff_t *ppos)
611{
612 return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 1);
613}
614
615static int proc_sys_open(struct inode *inode, struct file *filp)
616{
617 struct ctl_table_header *head = grab_header(inode);
618 struct ctl_table *table = PROC_I(inode)->sysctl_entry;
619
620
621 if (IS_ERR(head))
622 return PTR_ERR(head);
623
624 if (table->poll)
625 filp->private_data = proc_sys_poll_event(table->poll);
626
627 sysctl_head_finish(head);
628
629 return 0;
630}
631
632static __poll_t proc_sys_poll(struct file *filp, poll_table *wait)
633{
634 struct inode *inode = file_inode(filp);
635 struct ctl_table_header *head = grab_header(inode);
636 struct ctl_table *table = PROC_I(inode)->sysctl_entry;
637 __poll_t ret = DEFAULT_POLLMASK;
638 unsigned long event;
639
640
641 if (IS_ERR(head))
642 return EPOLLERR | EPOLLHUP;
643
644 if (!table->proc_handler)
645 goto out;
646
647 if (!table->poll)
648 goto out;
649
650 event = (unsigned long)filp->private_data;
651 poll_wait(filp, &table->poll->wait, wait);
652
653 if (event != atomic_read(&table->poll->event)) {
654 filp->private_data = proc_sys_poll_event(table->poll);
655 ret = EPOLLIN | EPOLLRDNORM | EPOLLERR | EPOLLPRI;
656 }
657
658out:
659 sysctl_head_finish(head);
660
661 return ret;
662}
663
664static bool proc_sys_fill_cache(struct file *file,
665 struct dir_context *ctx,
666 struct ctl_table_header *head,
667 struct ctl_table *table)
668{
669 struct dentry *child, *dir = file->f_path.dentry;
670 struct inode *inode;
671 struct qstr qname;
672 ino_t ino = 0;
673 unsigned type = DT_UNKNOWN;
674
675 qname.name = table->procname;
676 qname.len = strlen(table->procname);
677 qname.hash = full_name_hash(dir, qname.name, qname.len);
678
679 child = d_lookup(dir, &qname);
680 if (!child) {
681 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
682 child = d_alloc_parallel(dir, &qname, &wq);
683 if (IS_ERR(child))
684 return false;
685 if (d_in_lookup(child)) {
686 struct dentry *res;
687 inode = proc_sys_make_inode(dir->d_sb, head, table);
688 if (!inode) {
689 d_lookup_done(child);
690 dput(child);
691 return false;
692 }
693 d_set_d_op(child, &proc_sys_dentry_operations);
694 res = d_splice_alias(inode, child);
695 d_lookup_done(child);
696 if (unlikely(res)) {
697 if (IS_ERR(res)) {
698 dput(child);
699 return false;
700 }
701 dput(child);
702 child = res;
703 }
704 }
705 }
706 inode = d_inode(child);
707 ino = inode->i_ino;
708 type = inode->i_mode >> 12;
709 dput(child);
710 return dir_emit(ctx, qname.name, qname.len, ino, type);
711}
712
713static bool proc_sys_link_fill_cache(struct file *file,
714 struct dir_context *ctx,
715 struct ctl_table_header *head,
716 struct ctl_table *table)
717{
718 bool ret = true;
719
720 head = sysctl_head_grab(head);
721 if (IS_ERR(head))
722 return false;
723
724
725 if (sysctl_follow_link(&head, &table))
726 goto out;
727
728 ret = proc_sys_fill_cache(file, ctx, head, table);
729out:
730 sysctl_head_finish(head);
731 return ret;
732}
733
734static int scan(struct ctl_table_header *head, struct ctl_table *table,
735 unsigned long *pos, struct file *file,
736 struct dir_context *ctx)
737{
738 bool res;
739
740 if ((*pos)++ < ctx->pos)
741 return true;
742
743 if (unlikely(S_ISLNK(table->mode)))
744 res = proc_sys_link_fill_cache(file, ctx, head, table);
745 else
746 res = proc_sys_fill_cache(file, ctx, head, table);
747
748 if (res)
749 ctx->pos = *pos;
750
751 return res;
752}
753
754static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
755{
756 struct ctl_table_header *head = grab_header(file_inode(file));
757 struct ctl_table_header *h = NULL;
758 struct ctl_table *entry;
759 struct ctl_dir *ctl_dir;
760 unsigned long pos;
761
762 if (IS_ERR(head))
763 return PTR_ERR(head);
764
765 ctl_dir = container_of(head, struct ctl_dir, header);
766
767 if (!dir_emit_dots(file, ctx))
768 goto out;
769
770 pos = 2;
771
772 for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) {
773 if (!scan(h, entry, &pos, file, ctx)) {
774 sysctl_head_finish(h);
775 break;
776 }
777 }
778out:
779 sysctl_head_finish(head);
780 return 0;
781}
782
783static int proc_sys_permission(struct inode *inode, int mask)
784{
785
786
787
788
789 struct ctl_table_header *head;
790 struct ctl_table *table;
791 int error;
792
793
794 if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))
795 return -EACCES;
796
797 head = grab_header(inode);
798 if (IS_ERR(head))
799 return PTR_ERR(head);
800
801 table = PROC_I(inode)->sysctl_entry;
802 if (!table)
803 error = mask & MAY_WRITE ? -EACCES : 0;
804 else
805 error = sysctl_perm(head, table, mask & ~MAY_NOT_BLOCK);
806
807 sysctl_head_finish(head);
808 return error;
809}
810
811static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
812{
813 struct inode *inode = d_inode(dentry);
814 int error;
815
816 if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
817 return -EPERM;
818
819 error = setattr_prepare(dentry, attr);
820 if (error)
821 return error;
822
823 setattr_copy(inode, attr);
824 mark_inode_dirty(inode);
825 return 0;
826}
827
828static int proc_sys_getattr(const struct path *path, struct kstat *stat,
829 u32 request_mask, unsigned int query_flags)
830{
831 struct inode *inode = d_inode(path->dentry);
832 struct ctl_table_header *head = grab_header(inode);
833 struct ctl_table *table = PROC_I(inode)->sysctl_entry;
834
835 if (IS_ERR(head))
836 return PTR_ERR(head);
837
838 generic_fillattr(inode, stat);
839 if (table)
840 stat->mode = (stat->mode & S_IFMT) | table->mode;
841
842 sysctl_head_finish(head);
843 return 0;
844}
845
846static const struct file_operations proc_sys_file_operations = {
847 .open = proc_sys_open,
848 .poll = proc_sys_poll,
849 .read = proc_sys_read,
850 .write = proc_sys_write,
851 .llseek = default_llseek,
852};
853
854static const struct file_operations proc_sys_dir_file_operations = {
855 .read = generic_read_dir,
856 .iterate_shared = proc_sys_readdir,
857 .llseek = generic_file_llseek,
858};
859
860static const struct inode_operations proc_sys_inode_operations = {
861 .permission = proc_sys_permission,
862 .setattr = proc_sys_setattr,
863 .getattr = proc_sys_getattr,
864};
865
866static const struct inode_operations proc_sys_dir_operations = {
867 .lookup = proc_sys_lookup,
868 .permission = proc_sys_permission,
869 .setattr = proc_sys_setattr,
870 .getattr = proc_sys_getattr,
871};
872
873static int proc_sys_revalidate(struct dentry *dentry, unsigned int flags)
874{
875 if (flags & LOOKUP_RCU)
876 return -ECHILD;
877 return !PROC_I(d_inode(dentry))->sysctl->unregistering;
878}
879
880static int proc_sys_delete(const struct dentry *dentry)
881{
882 return !!PROC_I(d_inode(dentry))->sysctl->unregistering;
883}
884
885static int sysctl_is_seen(struct ctl_table_header *p)
886{
887 struct ctl_table_set *set = p->set;
888 int res;
889 spin_lock(&sysctl_lock);
890 if (p->unregistering)
891 res = 0;
892 else if (!set->is_seen)
893 res = 1;
894 else
895 res = set->is_seen(set);
896 spin_unlock(&sysctl_lock);
897 return res;
898}
899
900static int proc_sys_compare(const struct dentry *dentry,
901 unsigned int len, const char *str, const struct qstr *name)
902{
903 struct ctl_table_header *head;
904 struct inode *inode;
905
906
907
908
909 inode = d_inode_rcu(dentry);
910 if (!inode)
911 return 1;
912 if (name->len != len)
913 return 1;
914 if (memcmp(name->name, str, len))
915 return 1;
916 head = rcu_dereference(PROC_I(inode)->sysctl);
917 return !head || !sysctl_is_seen(head);
918}
919
920static const struct dentry_operations proc_sys_dentry_operations = {
921 .d_revalidate = proc_sys_revalidate,
922 .d_delete = proc_sys_delete,
923 .d_compare = proc_sys_compare,
924};
925
926static struct ctl_dir *find_subdir(struct ctl_dir *dir,
927 const char *name, int namelen)
928{
929 struct ctl_table_header *head;
930 struct ctl_table *entry;
931
932 entry = find_entry(&head, dir, name, namelen);
933 if (!entry)
934 return ERR_PTR(-ENOENT);
935 if (!S_ISDIR(entry->mode))
936 return ERR_PTR(-ENOTDIR);
937 return container_of(head, struct ctl_dir, header);
938}
939
940static struct ctl_dir *new_dir(struct ctl_table_set *set,
941 const char *name, int namelen)
942{
943 struct ctl_table *table;
944 struct ctl_dir *new;
945 struct ctl_node *node;
946 char *new_name;
947
948 new = kzalloc(sizeof(*new) + sizeof(struct ctl_node) +
949 sizeof(struct ctl_table)*2 + namelen + 1,
950 GFP_KERNEL);
951 if (!new)
952 return NULL;
953
954 node = (struct ctl_node *)(new + 1);
955 table = (struct ctl_table *)(node + 1);
956 new_name = (char *)(table + 2);
957 memcpy(new_name, name, namelen);
958 new_name[namelen] = '\0';
959 table[0].procname = new_name;
960 table[0].mode = S_IFDIR|S_IRUGO|S_IXUGO;
961 init_header(&new->header, set->dir.header.root, set, node, table);
962
963 return new;
964}
965
966
967
968
969
970
971
972
973
974
975
976
977
978static struct ctl_dir *get_subdir(struct ctl_dir *dir,
979 const char *name, int namelen)
980{
981 struct ctl_table_set *set = dir->header.set;
982 struct ctl_dir *subdir, *new = NULL;
983 int err;
984
985 spin_lock(&sysctl_lock);
986 subdir = find_subdir(dir, name, namelen);
987 if (!IS_ERR(subdir))
988 goto found;
989 if (PTR_ERR(subdir) != -ENOENT)
990 goto failed;
991
992 spin_unlock(&sysctl_lock);
993 new = new_dir(set, name, namelen);
994 spin_lock(&sysctl_lock);
995 subdir = ERR_PTR(-ENOMEM);
996 if (!new)
997 goto failed;
998
999
1000 subdir = find_subdir(dir, name, namelen);
1001 if (!IS_ERR(subdir))
1002 goto found;
1003 if (PTR_ERR(subdir) != -ENOENT)
1004 goto failed;
1005
1006
1007 err = insert_header(dir, &new->header);
1008 subdir = ERR_PTR(err);
1009 if (err)
1010 goto failed;
1011 subdir = new;
1012found:
1013 subdir->header.nreg++;
1014failed:
1015 if (IS_ERR(subdir)) {
1016 pr_err("sysctl could not get directory: ");
1017 sysctl_print_dir(dir);
1018 pr_cont("/%*.*s %ld\n",
1019 namelen, namelen, name, PTR_ERR(subdir));
1020 }
1021 drop_sysctl_table(&dir->header);
1022 if (new)
1023 drop_sysctl_table(&new->header);
1024 spin_unlock(&sysctl_lock);
1025 return subdir;
1026}
1027
1028static struct ctl_dir *xlate_dir(struct ctl_table_set *set, struct ctl_dir *dir)
1029{
1030 struct ctl_dir *parent;
1031 const char *procname;
1032 if (!dir->header.parent)
1033 return &set->dir;
1034 parent = xlate_dir(set, dir->header.parent);
1035 if (IS_ERR(parent))
1036 return parent;
1037 procname = dir->header.ctl_table[0].procname;
1038 return find_subdir(parent, procname, strlen(procname));
1039}
1040
1041static int sysctl_follow_link(struct ctl_table_header **phead,
1042 struct ctl_table **pentry)
1043{
1044 struct ctl_table_header *head;
1045 struct ctl_table_root *root;
1046 struct ctl_table_set *set;
1047 struct ctl_table *entry;
1048 struct ctl_dir *dir;
1049 int ret;
1050
1051 ret = 0;
1052 spin_lock(&sysctl_lock);
1053 root = (*pentry)->data;
1054 set = lookup_header_set(root);
1055 dir = xlate_dir(set, (*phead)->parent);
1056 if (IS_ERR(dir))
1057 ret = PTR_ERR(dir);
1058 else {
1059 const char *procname = (*pentry)->procname;
1060 head = NULL;
1061 entry = find_entry(&head, dir, procname, strlen(procname));
1062 ret = -ENOENT;
1063 if (entry && use_table(head)) {
1064 unuse_table(*phead);
1065 *phead = head;
1066 *pentry = entry;
1067 ret = 0;
1068 }
1069 }
1070
1071 spin_unlock(&sysctl_lock);
1072 return ret;
1073}
1074
1075static int sysctl_err(const char *path, struct ctl_table *table, char *fmt, ...)
1076{
1077 struct va_format vaf;
1078 va_list args;
1079
1080 va_start(args, fmt);
1081 vaf.fmt = fmt;
1082 vaf.va = &args;
1083
1084 pr_err("sysctl table check failed: %s/%s %pV\n",
1085 path, table->procname, &vaf);
1086
1087 va_end(args);
1088 return -EINVAL;
1089}
1090
1091static int sysctl_check_table_array(const char *path, struct ctl_table *table)
1092{
1093 int err = 0;
1094
1095 if ((table->proc_handler == proc_douintvec) ||
1096 (table->proc_handler == proc_douintvec_minmax)) {
1097 if (table->maxlen != sizeof(unsigned int))
1098 err |= sysctl_err(path, table, "array not allowed");
1099 }
1100
1101 return err;
1102}
1103
1104static int sysctl_check_table(const char *path, struct ctl_table *table)
1105{
1106 int err = 0;
1107 for (; table->procname; table++) {
1108 if (table->child)
1109 err |= sysctl_err(path, table, "Not a file");
1110
1111 if ((table->proc_handler == proc_dostring) ||
1112 (table->proc_handler == proc_dointvec) ||
1113 (table->proc_handler == proc_douintvec) ||
1114 (table->proc_handler == proc_douintvec_minmax) ||
1115 (table->proc_handler == proc_dointvec_minmax) ||
1116 (table->proc_handler == proc_dointvec_jiffies) ||
1117 (table->proc_handler == proc_dointvec_userhz_jiffies) ||
1118 (table->proc_handler == proc_dointvec_ms_jiffies) ||
1119 (table->proc_handler == proc_doulongvec_minmax) ||
1120 (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
1121 if (!table->data)
1122 err |= sysctl_err(path, table, "No data");
1123 if (!table->maxlen)
1124 err |= sysctl_err(path, table, "No maxlen");
1125 else
1126 err |= sysctl_check_table_array(path, table);
1127 }
1128 if (!table->proc_handler)
1129 err |= sysctl_err(path, table, "No proc_handler");
1130
1131 if ((table->mode & (S_IRUGO|S_IWUGO)) != table->mode)
1132 err |= sysctl_err(path, table, "bogus .mode 0%o",
1133 table->mode);
1134 }
1135 return err;
1136}
1137
1138static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table *table,
1139 struct ctl_table_root *link_root)
1140{
1141 struct ctl_table *link_table, *entry, *link;
1142 struct ctl_table_header *links;
1143 struct ctl_node *node;
1144 char *link_name;
1145 int nr_entries, name_bytes;
1146
1147 name_bytes = 0;
1148 nr_entries = 0;
1149 for (entry = table; entry->procname; entry++) {
1150 nr_entries++;
1151 name_bytes += strlen(entry->procname) + 1;
1152 }
1153
1154 links = kzalloc(sizeof(struct ctl_table_header) +
1155 sizeof(struct ctl_node)*nr_entries +
1156 sizeof(struct ctl_table)*(nr_entries + 1) +
1157 name_bytes,
1158 GFP_KERNEL);
1159
1160 if (!links)
1161 return NULL;
1162
1163 node = (struct ctl_node *)(links + 1);
1164 link_table = (struct ctl_table *)(node + nr_entries);
1165 link_name = (char *)&link_table[nr_entries + 1];
1166
1167 for (link = link_table, entry = table; entry->procname; link++, entry++) {
1168 int len = strlen(entry->procname) + 1;
1169 memcpy(link_name, entry->procname, len);
1170 link->procname = link_name;
1171 link->mode = S_IFLNK|S_IRWXUGO;
1172 link->data = link_root;
1173 link_name += len;
1174 }
1175 init_header(links, dir->header.root, dir->header.set, node, link_table);
1176 links->nreg = nr_entries;
1177
1178 return links;
1179}
1180
1181static bool get_links(struct ctl_dir *dir,
1182 struct ctl_table *table, struct ctl_table_root *link_root)
1183{
1184 struct ctl_table_header *head;
1185 struct ctl_table *entry, *link;
1186
1187
1188 for (entry = table; entry->procname; entry++) {
1189 const char *procname = entry->procname;
1190 link = find_entry(&head, dir, procname, strlen(procname));
1191 if (!link)
1192 return false;
1193 if (S_ISDIR(link->mode) && S_ISDIR(entry->mode))
1194 continue;
1195 if (S_ISLNK(link->mode) && (link->data == link_root))
1196 continue;
1197 return false;
1198 }
1199
1200
1201 for (entry = table; entry->procname; entry++) {
1202 const char *procname = entry->procname;
1203 link = find_entry(&head, dir, procname, strlen(procname));
1204 head->nreg++;
1205 }
1206 return true;
1207}
1208
1209static int insert_links(struct ctl_table_header *head)
1210{
1211 struct ctl_table_set *root_set = &sysctl_table_root.default_set;
1212 struct ctl_dir *core_parent = NULL;
1213 struct ctl_table_header *links;
1214 int err;
1215
1216 if (head->set == root_set)
1217 return 0;
1218
1219 core_parent = xlate_dir(root_set, head->parent);
1220 if (IS_ERR(core_parent))
1221 return 0;
1222
1223 if (get_links(core_parent, head->ctl_table, head->root))
1224 return 0;
1225
1226 core_parent->header.nreg++;
1227 spin_unlock(&sysctl_lock);
1228
1229 links = new_links(core_parent, head->ctl_table, head->root);
1230
1231 spin_lock(&sysctl_lock);
1232 err = -ENOMEM;
1233 if (!links)
1234 goto out;
1235
1236 err = 0;
1237 if (get_links(core_parent, head->ctl_table, head->root)) {
1238 kfree(links);
1239 goto out;
1240 }
1241
1242 err = insert_header(core_parent, links);
1243 if (err)
1244 kfree(links);
1245out:
1246 drop_sysctl_table(&core_parent->header);
1247 return err;
1248}
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292struct ctl_table_header *__register_sysctl_table(
1293 struct ctl_table_set *set,
1294 const char *path, struct ctl_table *table)
1295{
1296 struct ctl_table_root *root = set->dir.header.root;
1297 struct ctl_table_header *header;
1298 const char *name, *nextname;
1299 struct ctl_dir *dir;
1300 struct ctl_table *entry;
1301 struct ctl_node *node;
1302 int nr_entries = 0;
1303
1304 for (entry = table; entry->procname; entry++)
1305 nr_entries++;
1306
1307 header = kzalloc(sizeof(struct ctl_table_header) +
1308 sizeof(struct ctl_node)*nr_entries, GFP_KERNEL);
1309 if (!header)
1310 return NULL;
1311
1312 node = (struct ctl_node *)(header + 1);
1313 init_header(header, root, set, node, table);
1314 if (sysctl_check_table(path, table))
1315 goto fail;
1316
1317 spin_lock(&sysctl_lock);
1318 dir = &set->dir;
1319
1320 dir->header.nreg++;
1321 spin_unlock(&sysctl_lock);
1322
1323
1324 for (name = path; name; name = nextname) {
1325 int namelen;
1326 nextname = strchr(name, '/');
1327 if (nextname) {
1328 namelen = nextname - name;
1329 nextname++;
1330 } else {
1331 namelen = strlen(name);
1332 }
1333 if (namelen == 0)
1334 continue;
1335
1336 dir = get_subdir(dir, name, namelen);
1337 if (IS_ERR(dir))
1338 goto fail;
1339 }
1340
1341 spin_lock(&sysctl_lock);
1342 if (insert_header(dir, header))
1343 goto fail_put_dir_locked;
1344
1345 drop_sysctl_table(&dir->header);
1346 spin_unlock(&sysctl_lock);
1347
1348 return header;
1349
1350fail_put_dir_locked:
1351 drop_sysctl_table(&dir->header);
1352 spin_unlock(&sysctl_lock);
1353fail:
1354 kfree(header);
1355 dump_stack();
1356 return NULL;
1357}
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *table)
1370{
1371 return __register_sysctl_table(&sysctl_table_root.default_set,
1372 path, table);
1373}
1374EXPORT_SYMBOL(register_sysctl);
1375
1376static char *append_path(const char *path, char *pos, const char *name)
1377{
1378 int namelen;
1379 namelen = strlen(name);
1380 if (((pos - path) + namelen + 2) >= PATH_MAX)
1381 return NULL;
1382 memcpy(pos, name, namelen);
1383 pos[namelen] = '/';
1384 pos[namelen + 1] = '\0';
1385 pos += namelen + 1;
1386 return pos;
1387}
1388
1389static int count_subheaders(struct ctl_table *table)
1390{
1391 int has_files = 0;
1392 int nr_subheaders = 0;
1393 struct ctl_table *entry;
1394
1395
1396 if (!table || !table->procname)
1397 return 1;
1398
1399 for (entry = table; entry->procname; entry++) {
1400 if (entry->child)
1401 nr_subheaders += count_subheaders(entry->child);
1402 else
1403 has_files = 1;
1404 }
1405 return nr_subheaders + has_files;
1406}
1407
1408static int register_leaf_sysctl_tables(const char *path, char *pos,
1409 struct ctl_table_header ***subheader, struct ctl_table_set *set,
1410 struct ctl_table *table)
1411{
1412 struct ctl_table *ctl_table_arg = NULL;
1413 struct ctl_table *entry, *files;
1414 int nr_files = 0;
1415 int nr_dirs = 0;
1416 int err = -ENOMEM;
1417
1418 for (entry = table; entry->procname; entry++) {
1419 if (entry->child)
1420 nr_dirs++;
1421 else
1422 nr_files++;
1423 }
1424
1425 files = table;
1426
1427 if (nr_dirs && nr_files) {
1428 struct ctl_table *new;
1429 files = kcalloc(nr_files + 1, sizeof(struct ctl_table),
1430 GFP_KERNEL);
1431 if (!files)
1432 goto out;
1433
1434 ctl_table_arg = files;
1435 for (new = files, entry = table; entry->procname; entry++) {
1436 if (entry->child)
1437 continue;
1438 *new = *entry;
1439 new++;
1440 }
1441 }
1442
1443
1444 if (nr_files || !nr_dirs) {
1445 struct ctl_table_header *header;
1446 header = __register_sysctl_table(set, path, files);
1447 if (!header) {
1448 kfree(ctl_table_arg);
1449 goto out;
1450 }
1451
1452
1453 header->ctl_table_arg = ctl_table_arg;
1454 **subheader = header;
1455 (*subheader)++;
1456 }
1457
1458
1459 for (entry = table; entry->procname; entry++) {
1460 char *child_pos;
1461
1462 if (!entry->child)
1463 continue;
1464
1465 err = -ENAMETOOLONG;
1466 child_pos = append_path(path, pos, entry->procname);
1467 if (!child_pos)
1468 goto out;
1469
1470 err = register_leaf_sysctl_tables(path, child_pos, subheader,
1471 set, entry->child);
1472 pos[0] = '\0';
1473 if (err)
1474 goto out;
1475 }
1476 err = 0;
1477out:
1478
1479 return err;
1480}
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493struct ctl_table_header *__register_sysctl_paths(
1494 struct ctl_table_set *set,
1495 const struct ctl_path *path, struct ctl_table *table)
1496{
1497 struct ctl_table *ctl_table_arg = table;
1498 int nr_subheaders = count_subheaders(table);
1499 struct ctl_table_header *header = NULL, **subheaders, **subheader;
1500 const struct ctl_path *component;
1501 char *new_path, *pos;
1502
1503 pos = new_path = kmalloc(PATH_MAX, GFP_KERNEL);
1504 if (!new_path)
1505 return NULL;
1506
1507 pos[0] = '\0';
1508 for (component = path; component->procname; component++) {
1509 pos = append_path(new_path, pos, component->procname);
1510 if (!pos)
1511 goto out;
1512 }
1513 while (table->procname && table->child && !table[1].procname) {
1514 pos = append_path(new_path, pos, table->procname);
1515 if (!pos)
1516 goto out;
1517 table = table->child;
1518 }
1519 if (nr_subheaders == 1) {
1520 header = __register_sysctl_table(set, new_path, table);
1521 if (header)
1522 header->ctl_table_arg = ctl_table_arg;
1523 } else {
1524 header = kzalloc(sizeof(*header) +
1525 sizeof(*subheaders)*nr_subheaders, GFP_KERNEL);
1526 if (!header)
1527 goto out;
1528
1529 subheaders = (struct ctl_table_header **) (header + 1);
1530 subheader = subheaders;
1531 header->ctl_table_arg = ctl_table_arg;
1532
1533 if (register_leaf_sysctl_tables(new_path, pos, &subheader,
1534 set, table))
1535 goto err_register_leaves;
1536 }
1537
1538out:
1539 kfree(new_path);
1540 return header;
1541
1542err_register_leaves:
1543 while (subheader > subheaders) {
1544 struct ctl_table_header *subh = *(--subheader);
1545 struct ctl_table *table = subh->ctl_table_arg;
1546 unregister_sysctl_table(subh);
1547 kfree(table);
1548 }
1549 kfree(header);
1550 header = NULL;
1551 goto out;
1552}
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
1565 struct ctl_table *table)
1566{
1567 return __register_sysctl_paths(&sysctl_table_root.default_set,
1568 path, table);
1569}
1570EXPORT_SYMBOL(register_sysctl_paths);
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
1582{
1583 static const struct ctl_path null_path[] = { {} };
1584
1585 return register_sysctl_paths(null_path, table);
1586}
1587EXPORT_SYMBOL(register_sysctl_table);
1588
1589static void put_links(struct ctl_table_header *header)
1590{
1591 struct ctl_table_set *root_set = &sysctl_table_root.default_set;
1592 struct ctl_table_root *root = header->root;
1593 struct ctl_dir *parent = header->parent;
1594 struct ctl_dir *core_parent;
1595 struct ctl_table *entry;
1596
1597 if (header->set == root_set)
1598 return;
1599
1600 core_parent = xlate_dir(root_set, parent);
1601 if (IS_ERR(core_parent))
1602 return;
1603
1604 for (entry = header->ctl_table; entry->procname; entry++) {
1605 struct ctl_table_header *link_head;
1606 struct ctl_table *link;
1607 const char *name = entry->procname;
1608
1609 link = find_entry(&link_head, core_parent, name, strlen(name));
1610 if (link &&
1611 ((S_ISDIR(link->mode) && S_ISDIR(entry->mode)) ||
1612 (S_ISLNK(link->mode) && (link->data == root)))) {
1613 drop_sysctl_table(link_head);
1614 }
1615 else {
1616 pr_err("sysctl link missing during unregister: ");
1617 sysctl_print_dir(parent);
1618 pr_cont("/%s\n", name);
1619 }
1620 }
1621}
1622
1623static void drop_sysctl_table(struct ctl_table_header *header)
1624{
1625 struct ctl_dir *parent = header->parent;
1626
1627 if (--header->nreg)
1628 return;
1629
1630 put_links(header);
1631 start_unregistering(header);
1632 if (!--header->count)
1633 kfree_rcu(header, rcu);
1634
1635 if (parent)
1636 drop_sysctl_table(&parent->header);
1637}
1638
1639
1640
1641
1642
1643
1644
1645
1646void unregister_sysctl_table(struct ctl_table_header * header)
1647{
1648 int nr_subheaders;
1649 might_sleep();
1650
1651 if (header == NULL)
1652 return;
1653
1654 nr_subheaders = count_subheaders(header->ctl_table_arg);
1655 if (unlikely(nr_subheaders > 1)) {
1656 struct ctl_table_header **subheaders;
1657 int i;
1658
1659 subheaders = (struct ctl_table_header **)(header + 1);
1660 for (i = nr_subheaders -1; i >= 0; i--) {
1661 struct ctl_table_header *subh = subheaders[i];
1662 struct ctl_table *table = subh->ctl_table_arg;
1663 unregister_sysctl_table(subh);
1664 kfree(table);
1665 }
1666 kfree(header);
1667 return;
1668 }
1669
1670 spin_lock(&sysctl_lock);
1671 drop_sysctl_table(header);
1672 spin_unlock(&sysctl_lock);
1673}
1674EXPORT_SYMBOL(unregister_sysctl_table);
1675
1676void setup_sysctl_set(struct ctl_table_set *set,
1677 struct ctl_table_root *root,
1678 int (*is_seen)(struct ctl_table_set *))
1679{
1680 memset(set, 0, sizeof(*set));
1681 set->is_seen = is_seen;
1682 init_header(&set->dir.header, root, set, NULL, root_table);
1683}
1684
1685void retire_sysctl_set(struct ctl_table_set *set)
1686{
1687 WARN_ON(!RB_EMPTY_ROOT(&set->dir.root));
1688}
1689
1690int __init proc_sys_init(void)
1691{
1692 struct proc_dir_entry *proc_sys_root;
1693
1694 proc_sys_root = proc_mkdir("sys", NULL);
1695 proc_sys_root->proc_iops = &proc_sys_dir_operations;
1696 proc_sys_root->proc_fops = &proc_sys_dir_file_operations;
1697 proc_sys_root->nlink = 0;
1698
1699 return sysctl_init();
1700}
1701