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