aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/proc_sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/proc_sysctl.c')
-rw-r--r--fs/proc/proc_sysctl.c78
1 files changed, 31 insertions, 47 deletions
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index ac05f33a0dde..71290463a1d3 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -573,12 +573,12 @@ out:
573 return ret; 573 return ret;
574} 574}
575 575
576static int proc_sys_fill_cache(struct file *filp, void *dirent, 576static bool proc_sys_fill_cache(struct file *file,
577 filldir_t filldir, 577 struct dir_context *ctx,
578 struct ctl_table_header *head, 578 struct ctl_table_header *head,
579 struct ctl_table *table) 579 struct ctl_table *table)
580{ 580{
581 struct dentry *child, *dir = filp->f_path.dentry; 581 struct dentry *child, *dir = file->f_path.dentry;
582 struct inode *inode; 582 struct inode *inode;
583 struct qstr qname; 583 struct qstr qname;
584 ino_t ino = 0; 584 ino_t ino = 0;
@@ -595,38 +595,38 @@ static int proc_sys_fill_cache(struct file *filp, void *dirent,
595 inode = proc_sys_make_inode(dir->d_sb, head, table); 595 inode = proc_sys_make_inode(dir->d_sb, head, table);
596 if (!inode) { 596 if (!inode) {
597 dput(child); 597 dput(child);
598 return -ENOMEM; 598 return false;
599 } else { 599 } else {
600 d_set_d_op(child, &proc_sys_dentry_operations); 600 d_set_d_op(child, &proc_sys_dentry_operations);
601 d_add(child, inode); 601 d_add(child, inode);
602 } 602 }
603 } else { 603 } else {
604 return -ENOMEM; 604 return false;
605 } 605 }
606 } 606 }
607 inode = child->d_inode; 607 inode = child->d_inode;
608 ino = inode->i_ino; 608 ino = inode->i_ino;
609 type = inode->i_mode >> 12; 609 type = inode->i_mode >> 12;
610 dput(child); 610 dput(child);
611 return !!filldir(dirent, qname.name, qname.len, filp->f_pos, ino, type); 611 return dir_emit(ctx, qname.name, qname.len, ino, type);
612} 612}
613 613
614static int proc_sys_link_fill_cache(struct file *filp, void *dirent, 614static bool proc_sys_link_fill_cache(struct file *file,
615 filldir_t filldir, 615 struct dir_context *ctx,
616 struct ctl_table_header *head, 616 struct ctl_table_header *head,
617 struct ctl_table *table) 617 struct ctl_table *table)
618{ 618{
619 int err, ret = 0; 619 bool ret = true;
620 head = sysctl_head_grab(head); 620 head = sysctl_head_grab(head);
621 621
622 if (S_ISLNK(table->mode)) { 622 if (S_ISLNK(table->mode)) {
623 /* It is not an error if we can not follow the link ignore it */ 623 /* It is not an error if we can not follow the link ignore it */
624 err = sysctl_follow_link(&head, &table, current->nsproxy); 624 int err = sysctl_follow_link(&head, &table, current->nsproxy);
625 if (err) 625 if (err)
626 goto out; 626 goto out;
627 } 627 }
628 628
629 ret = proc_sys_fill_cache(filp, dirent, filldir, head, table); 629 ret = proc_sys_fill_cache(file, ctx, head, table);
630out: 630out:
631 sysctl_head_finish(head); 631 sysctl_head_finish(head);
632 return ret; 632 return ret;
@@ -634,67 +634,50 @@ out:
634 634
635static int scan(struct ctl_table_header *head, ctl_table *table, 635static int scan(struct ctl_table_header *head, ctl_table *table,
636 unsigned long *pos, struct file *file, 636 unsigned long *pos, struct file *file,
637 void *dirent, filldir_t filldir) 637 struct dir_context *ctx)
638{ 638{
639 int res; 639 bool res;
640 640
641 if ((*pos)++ < file->f_pos) 641 if ((*pos)++ < ctx->pos)
642 return 0; 642 return true;
643 643
644 if (unlikely(S_ISLNK(table->mode))) 644 if (unlikely(S_ISLNK(table->mode)))
645 res = proc_sys_link_fill_cache(file, dirent, filldir, head, table); 645 res = proc_sys_link_fill_cache(file, ctx, head, table);
646 else 646 else
647 res = proc_sys_fill_cache(file, dirent, filldir, head, table); 647 res = proc_sys_fill_cache(file, ctx, head, table);
648 648
649 if (res == 0) 649 if (res)
650 file->f_pos = *pos; 650 ctx->pos = *pos;
651 651
652 return res; 652 return res;
653} 653}
654 654
655static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir) 655static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
656{ 656{
657 struct dentry *dentry = filp->f_path.dentry; 657 struct ctl_table_header *head = grab_header(file_inode(file));
658 struct inode *inode = dentry->d_inode;
659 struct ctl_table_header *head = grab_header(inode);
660 struct ctl_table_header *h = NULL; 658 struct ctl_table_header *h = NULL;
661 struct ctl_table *entry; 659 struct ctl_table *entry;
662 struct ctl_dir *ctl_dir; 660 struct ctl_dir *ctl_dir;
663 unsigned long pos; 661 unsigned long pos;
664 int ret = -EINVAL;
665 662
666 if (IS_ERR(head)) 663 if (IS_ERR(head))
667 return PTR_ERR(head); 664 return PTR_ERR(head);
668 665
669 ctl_dir = container_of(head, struct ctl_dir, header); 666 ctl_dir = container_of(head, struct ctl_dir, header);
670 667
671 ret = 0; 668 if (!dir_emit_dots(file, ctx))
672 /* Avoid a switch here: arm builds fail with missing __cmpdi2 */ 669 return 0;
673 if (filp->f_pos == 0) { 670
674 if (filldir(dirent, ".", 1, filp->f_pos,
675 inode->i_ino, DT_DIR) < 0)
676 goto out;
677 filp->f_pos++;
678 }
679 if (filp->f_pos == 1) {
680 if (filldir(dirent, "..", 2, filp->f_pos,
681 parent_ino(dentry), DT_DIR) < 0)
682 goto out;
683 filp->f_pos++;
684 }
685 pos = 2; 671 pos = 2;
686 672
687 for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) { 673 for (first_entry(ctl_dir, &h, &entry); h; next_entry(&h, &entry)) {
688 ret = scan(h, entry, &pos, filp, dirent, filldir); 674 if (!scan(h, entry, &pos, file, ctx)) {
689 if (ret) {
690 sysctl_head_finish(h); 675 sysctl_head_finish(h);
691 break; 676 break;
692 } 677 }
693 } 678 }
694 ret = 1;
695out:
696 sysctl_head_finish(head); 679 sysctl_head_finish(head);
697 return ret; 680 return 0;
698} 681}
699 682
700static int proc_sys_permission(struct inode *inode, int mask) 683static int proc_sys_permission(struct inode *inode, int mask)
@@ -769,7 +752,7 @@ static const struct file_operations proc_sys_file_operations = {
769 752
770static const struct file_operations proc_sys_dir_file_operations = { 753static const struct file_operations proc_sys_dir_file_operations = {
771 .read = generic_read_dir, 754 .read = generic_read_dir,
772 .readdir = proc_sys_readdir, 755 .iterate = proc_sys_readdir,
773 .llseek = generic_file_llseek, 756 .llseek = generic_file_llseek,
774}; 757};
775 758
@@ -813,15 +796,16 @@ static int sysctl_is_seen(struct ctl_table_header *p)
813 return res; 796 return res;
814} 797}
815 798
816static int proc_sys_compare(const struct dentry *parent, 799static int proc_sys_compare(const struct dentry *parent, const struct dentry *dentry,
817 const struct inode *pinode,
818 const struct dentry *dentry, const struct inode *inode,
819 unsigned int len, const char *str, const struct qstr *name) 800 unsigned int len, const char *str, const struct qstr *name)
820{ 801{
821 struct ctl_table_header *head; 802 struct ctl_table_header *head;
803 struct inode *inode;
804
822 /* Although proc doesn't have negative dentries, rcu-walk means 805 /* Although proc doesn't have negative dentries, rcu-walk means
823 * that inode here can be NULL */ 806 * that inode here can be NULL */
824 /* AV: can it, indeed? */ 807 /* AV: can it, indeed? */
808 inode = ACCESS_ONCE(dentry->d_inode);
825 if (!inode) 809 if (!inode)
826 return 1; 810 return 1;
827 if (name->len != len) 811 if (name->len != len)