hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/fs/proc/generic.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * proc/fs/generic.c --- generic routines for the proc-fs
34 *
....@@ -162,7 +163,6 @@
162163 {
163164 const char *cp = name, *next;
164165 struct proc_dir_entry *de;
165
- unsigned int len;
166166
167167 de = *ret;
168168 if (!de)
....@@ -173,13 +173,12 @@
173173 if (!next)
174174 break;
175175
176
- len = next - cp;
177
- de = pde_subdir_find(de, cp, len);
176
+ de = pde_subdir_find(de, cp, next - cp);
178177 if (!de) {
179178 WARN(1, "name '%s'\n", name);
180179 return -ENOENT;
181180 }
182
- cp += len + 1;
181
+ cp = next + 1;
183182 }
184183 *residual = cp;
185184 *ret = de;
....@@ -270,6 +269,11 @@
270269 struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
271270 unsigned int flags)
272271 {
272
+ struct proc_fs_info *fs_info = proc_sb_info(dir->i_sb);
273
+
274
+ if (fs_info->pidonly == PROC_PIDONLY_ON)
275
+ return ERR_PTR(-ENOENT);
276
+
273277 return proc_lookup_de(dir, dentry, PDE(dir));
274278 }
275279
....@@ -326,6 +330,10 @@
326330 int proc_readdir(struct file *file, struct dir_context *ctx)
327331 {
328332 struct inode *inode = file_inode(file);
333
+ struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
334
+
335
+ if (fs_info->pidonly == PROC_PIDONLY_ON)
336
+ return 1;
329337
330338 return proc_readdir_de(file, ctx, PDE(inode));
331339 }
....@@ -445,6 +453,9 @@
445453 proc_set_user(ent, (*parent)->uid, (*parent)->gid);
446454
447455 ent->proc_dops = &proc_misc_dentry_ops;
456
+ /* Revalidate everything under /proc/${pid}/net */
457
+ if ((*parent)->proc_dops == &proc_net_dentry_ops)
458
+ pde_force_lookup(ent);
448459
449460 out:
450461 return ent;
....@@ -484,7 +495,7 @@
484495 ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
485496 if (ent) {
486497 ent->data = data;
487
- ent->proc_fops = &proc_dir_operations;
498
+ ent->proc_dir_ops = &proc_dir_operations;
488499 ent->proc_iops = &proc_dir_inode_operations;
489500 if (force_lookup) {
490501 pde_force_lookup(ent);
....@@ -524,7 +535,7 @@
524535 ent = __proc_create(&parent, name, mode, 2);
525536 if (ent) {
526537 ent->data = NULL;
527
- ent->proc_fops = NULL;
538
+ ent->proc_dir_ops = NULL;
528539 ent->proc_iops = NULL;
529540 ent = proc_register(parent, ent);
530541 }
....@@ -552,27 +563,32 @@
552563 return p;
553564 }
554565
566
+static inline void pde_set_flags(struct proc_dir_entry *pde)
567
+{
568
+ if (pde->proc_ops->proc_flags & PROC_ENTRY_PERMANENT)
569
+ pde->flags |= PROC_ENTRY_PERMANENT;
570
+}
571
+
555572 struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
556573 struct proc_dir_entry *parent,
557
- const struct file_operations *proc_fops, void *data)
574
+ const struct proc_ops *proc_ops, void *data)
558575 {
559576 struct proc_dir_entry *p;
560
-
561
- BUG_ON(proc_fops == NULL);
562577
563578 p = proc_create_reg(name, mode, &parent, data);
564579 if (!p)
565580 return NULL;
566
- p->proc_fops = proc_fops;
581
+ p->proc_ops = proc_ops;
582
+ pde_set_flags(p);
567583 return proc_register(parent, p);
568584 }
569585 EXPORT_SYMBOL(proc_create_data);
570586
571587 struct proc_dir_entry *proc_create(const char *name, umode_t mode,
572588 struct proc_dir_entry *parent,
573
- const struct file_operations *proc_fops)
589
+ const struct proc_ops *proc_ops)
574590 {
575
- return proc_create_data(name, mode, parent, proc_fops, NULL);
591
+ return proc_create_data(name, mode, parent, proc_ops, NULL);
576592 }
577593 EXPORT_SYMBOL(proc_create);
578594
....@@ -594,11 +610,12 @@
594610 return seq_release(inode, file);
595611 }
596612
597
-static const struct file_operations proc_seq_fops = {
598
- .open = proc_seq_open,
599
- .read = seq_read,
600
- .llseek = seq_lseek,
601
- .release = proc_seq_release,
613
+static const struct proc_ops proc_seq_ops = {
614
+ /* not permanent -- can call into arbitrary seq_operations */
615
+ .proc_open = proc_seq_open,
616
+ .proc_read_iter = seq_read_iter,
617
+ .proc_lseek = seq_lseek,
618
+ .proc_release = proc_seq_release,
602619 };
603620
604621 struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
....@@ -610,7 +627,7 @@
610627 p = proc_create_reg(name, mode, &parent, data);
611628 if (!p)
612629 return NULL;
613
- p->proc_fops = &proc_seq_fops;
630
+ p->proc_ops = &proc_seq_ops;
614631 p->seq_ops = ops;
615632 p->state_size = state_size;
616633 return proc_register(parent, p);
....@@ -624,11 +641,12 @@
624641 return single_open(file, de->single_show, de->data);
625642 }
626643
627
-static const struct file_operations proc_single_fops = {
628
- .open = proc_single_open,
629
- .read = seq_read,
630
- .llseek = seq_lseek,
631
- .release = single_release,
644
+static const struct proc_ops proc_single_ops = {
645
+ /* not permanent -- can call into arbitrary ->single_show */
646
+ .proc_open = proc_single_open,
647
+ .proc_read_iter = seq_read_iter,
648
+ .proc_lseek = seq_lseek,
649
+ .proc_release = single_release,
632650 };
633651
634652 struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
....@@ -640,7 +658,7 @@
640658 p = proc_create_reg(name, mode, &parent, data);
641659 if (!p)
642660 return NULL;
643
- p->proc_fops = &proc_single_fops;
661
+ p->proc_ops = &proc_single_ops;
644662 p->single_show = show;
645663 return proc_register(parent, p);
646664 }
....@@ -685,9 +703,13 @@
685703
686704 de = pde_subdir_find(parent, fn, len);
687705 if (de) {
688
- rb_erase(&de->subdir_node, &parent->subdir);
689
- if (S_ISDIR(de->mode)) {
690
- parent->nlink--;
706
+ if (unlikely(pde_is_permanent(de))) {
707
+ WARN(1, "removing permanent /proc entry '%s'", de->name);
708
+ de = NULL;
709
+ } else {
710
+ rb_erase(&de->subdir_node, &parent->subdir);
711
+ if (S_ISDIR(de->mode))
712
+ parent->nlink--;
691713 }
692714 }
693715 write_unlock(&proc_subdir_lock);
....@@ -723,12 +745,24 @@
723745 write_unlock(&proc_subdir_lock);
724746 return -ENOENT;
725747 }
748
+ if (unlikely(pde_is_permanent(root))) {
749
+ write_unlock(&proc_subdir_lock);
750
+ WARN(1, "removing permanent /proc entry '%s/%s'",
751
+ root->parent->name, root->name);
752
+ return -EINVAL;
753
+ }
726754 rb_erase(&root->subdir_node, &parent->subdir);
727755
728756 de = root;
729757 while (1) {
730758 next = pde_subdir_first(de);
731759 if (next) {
760
+ if (unlikely(pde_is_permanent(next))) {
761
+ write_unlock(&proc_subdir_lock);
762
+ WARN(1, "removing permanent /proc entry '%s/%s'",
763
+ next->parent->name, next->name);
764
+ return -EINVAL;
765
+ }
732766 rb_erase(&next->subdir_node, &de->subdir);
733767 de = next;
734768 continue;