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