syzbot found that touch /proc/testfile causes NULL pointer dereference at tomoyo_get_local_path() because inode of the dentry is NULL. Before c59f415a7cb6, Tomoyo received pid_ns from proc's s_fs_info directly. Since proc_pid_ns() can only work with inode, using it in the tomoyo_get_local_path() was wrong. To avoid creating more functions for getting proc_ns, change the argument type of the proc_pid_ns() function. Then, Tomoyo can use the existing super_block to get pid_ns.
Unified · Split
| @@ -2823,7 +2823,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, · 2822 unmodified lines | |||
| 2823 | { | 2823 | { |
| 2824 | struct inode *inode = NULL; | 2824 | struct inode *inode = NULL; |
| 2825 | unsigned int fl_pid; | 2825 | unsigned int fl_pid; |
| 2826 | struct pid_namespace *proc_pidns = proc_pid_ns(file_inode(f->file)); | 2826 | struct pid_namespace *proc_pidns = proc_pid_ns(file_inode(f->file)->i_sb); |
| 2827 | 2827 | ||
| 2828 | fl_pid = locks_translate_pid(fl, proc_pidns); | 2828 | fl_pid = locks_translate_pid(fl, proc_pidns); |
| 2829 | /* | 2829 | /* |
| @@ -2901,7 +2901,7 @@ static int locks_show(struct seq_file *f, void *v) · 71 unmodified lines | |||
| 2901 | { | 2901 | { |
| 2902 | struct locks_iterator *iter = f->private; | 2902 | struct locks_iterator *iter = f->private; |
| 2903 | struct file_lock *fl, *bfl; | 2903 | struct file_lock *fl, *bfl; |
| 2904 | struct pid_namespace *proc_pidns = proc_pid_ns(file_inode(f->file)); | 2904 | struct pid_namespace *proc_pidns = proc_pid_ns(file_inode(f->file)->i_sb); |
| 2905 | 2905 | ||
| 2906 | fl = hlist_entry(v, struct file_lock, fl_link); | 2906 | fl = hlist_entry(v, struct file_lock, fl_link); |
| 2907 | 2907 | ||
| @@ -728,7 +728,7 @@ static int children_seq_show(struct seq_file *seq, void *v) · 727 unmodified lines | |||
| 728 | { | 728 | { |
| 729 | struct inode *inode = file_inode(seq->file); | 729 | struct inode *inode = file_inode(seq->file); |
| 730 | 730 | ||
| 731 | seq_printf(seq, "%d ", pid_nr_ns(v, proc_pid_ns(inode))); | 731 | seq_printf(seq, "%d ", pid_nr_ns(v, proc_pid_ns(inode->i_sb))); |
| 732 | return 0; | 732 | return 0; |
| 733 | } | 733 | } |
| 734 | 734 | ||
| @@ -754,7 +754,7 @@ static const struct inode_operations proc_def_inode_operations = { · 753 unmodified lines | |||
| 754 | static int proc_single_show(struct seq_file *m, void *v) | 754 | static int proc_single_show(struct seq_file *m, void *v) |
| 755 | { | 755 | { |
| 756 | struct inode *inode = m->private; | 756 | struct inode *inode = m->private; |
| 757 | struct pid_namespace *ns = proc_pid_ns(inode); | 757 | struct pid_namespace *ns = proc_pid_ns(inode->i_sb); |
| 758 | struct pid *pid = proc_pid(inode); | 758 | struct pid *pid = proc_pid(inode); |
| 759 | struct task_struct *task; | 759 | struct task_struct *task; |
| 760 | int ret; | 760 | int ret; |
| @@ -1423,7 +1423,7 @@ static const struct file_operations proc_fail_nth_operations = { · 662 unmodified lines | |||
| 1423 | static int sched_show(struct seq_file *m, void *v) | 1423 | static int sched_show(struct seq_file *m, void *v) |
| 1424 | { | 1424 | { |
| 1425 | struct inode *inode = m->private; | 1425 | struct inode *inode = m->private; |
| 1426 | struct pid_namespace *ns = proc_pid_ns(inode); | 1426 | struct pid_namespace *ns = proc_pid_ns(inode->i_sb); |
| 1427 | struct task_struct *p; | 1427 | struct task_struct *p; |
| 1428 | 1428 | ||
| 1429 | p = get_proc_task(inode); | 1429 | p = get_proc_task(inode); |
| @@ -2466,7 +2466,7 @@ static int proc_timers_open(struct inode *inode, struct file *file) · 1036 unmodified lines | |||
| 2466 | return -ENOMEM; | 2466 | return -ENOMEM; |
| 2467 | 2467 | ||
| 2468 | tp->pid = proc_pid(inode); | 2468 | tp->pid = proc_pid(inode); |
| 2469 | tp->ns = proc_pid_ns(inode); | 2469 | tp->ns = proc_pid_ns(inode->i_sb); |
| 2470 | return 0; | 2470 | return 0; |
| 2471 | } | 2471 | } |
| 2472 | 2472 | ||
| @@ -3377,7 +3377,7 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx) · 904 unmodified lines | |||
| 3377 | { | 3377 | { |
| 3378 | struct tgid_iter iter; | 3378 | struct tgid_iter iter; |
| 3379 | struct proc_fs_info *fs_info = proc_sb_info(file_inode(file)->i_sb); | 3379 | struct proc_fs_info *fs_info = proc_sb_info(file_inode(file)->i_sb); |
| 3380 | struct pid_namespace *ns = proc_pid_ns(file_inode(file)); | 3380 | struct pid_namespace *ns = proc_pid_ns(file_inode(file)->i_sb); |
| 3381 | loff_t pos = ctx->pos; | 3381 | loff_t pos = ctx->pos; |
| 3382 | 3382 | ||
| 3383 | if (pos >= PID_MAX_LIMIT + TGID_OFFSET) | 3383 | if (pos >= PID_MAX_LIMIT + TGID_OFFSET) |
| @@ -3730,7 +3730,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx) · 346 unmodified lines | |||
| 3730 | /* f_version caches the tgid value that the last readdir call couldn't | 3730 | /* f_version caches the tgid value that the last readdir call couldn't |
| 3731 | * return. lseek aka telldir automagically resets f_version to 0. | 3731 | * return. lseek aka telldir automagically resets f_version to 0. |
| 3732 | */ | 3732 | */ |
| 3733 | ns = proc_pid_ns(inode); | 3733 | ns = proc_pid_ns(inode->i_sb); |
| 3734 | tid = (int)file->f_version; | 3734 | tid = (int)file->f_version; |
| 3735 | file->f_version = 0; | 3735 | file->f_version = 0; |
| 3736 | for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns); | 3736 | for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns); |
| @@ -12,7 +12,7 @@ static const char *proc_self_get_link(struct dentry *dentry, · 11 unmodified lines | |||
| 12 | struct inode *inode, | 12 | struct inode *inode, |
| 13 | struct delayed_call *done) | 13 | struct delayed_call *done) |
| 14 | { | 14 | { |
| 15 | struct pid_namespace *ns = proc_pid_ns(inode); | 15 | struct pid_namespace *ns = proc_pid_ns(inode->i_sb); |
| 16 | pid_t tgid = task_tgid_nr_ns(current, ns); | 16 | pid_t tgid = task_tgid_nr_ns(current, ns); |
| 17 | char *name; | 17 | char *name; |
| 18 | 18 | ||
| @@ -12,7 +12,7 @@ static const char *proc_thread_self_get_link(struct dentry *dentry, · 11 unmodified lines | |||
| 12 | struct inode *inode, | 12 | struct inode *inode, |
| 13 | struct delayed_call *done) | 13 | struct delayed_call *done) |
| 14 | { | 14 | { |
| 15 | struct pid_namespace *ns = proc_pid_ns(inode); | 15 | struct pid_namespace *ns = proc_pid_ns(inode->i_sb); |
| 16 | pid_t tgid = task_tgid_nr_ns(current, ns); | 16 | pid_t tgid = task_tgid_nr_ns(current, ns); |
| 17 | pid_t pid = task_pid_nr_ns(current, ns); | 17 | pid_t pid = task_pid_nr_ns(current, ns); |
| 18 | char *name; | 18 | char *name; |
| @@ -202,9 +202,9 @@ int open_related_ns(struct ns_common *ns, · 201 unmodified lines | |||
| 202 | struct ns_common *(*get_ns)(struct ns_common *ns)); | 202 | struct ns_common *(*get_ns)(struct ns_common *ns)); |
| 203 | 203 | ||
| 204 | /* get the associated pid namespace for a file in procfs */ | 204 | /* get the associated pid namespace for a file in procfs */ |
| 205 | static inline struct pid_namespace *proc_pid_ns(const struct inode *inode) | 205 | static inline struct pid_namespace *proc_pid_ns(struct super_block *sb) |
| 206 | { | 206 | { |
| 207 | return proc_sb_info(inode->i_sb)->pid_ns; | 207 | return proc_sb_info(sb)->pid_ns; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | #endif /* _LINUX_PROC_FS_H */ | 210 | #endif /* _LINUX_PROC_FS_H */ |
| @@ -1745,7 +1745,7 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f) · 1744 unmodified lines | |||
| 1745 | pid_t nr = -1; | 1745 | pid_t nr = -1; |
| 1746 | 1746 | ||
| 1747 | if (likely(pid_has_task(pid, PIDTYPE_PID))) { | 1747 | if (likely(pid_has_task(pid, PIDTYPE_PID))) { |
| 1748 | ns = proc_pid_ns(file_inode(m->file)); | 1748 | ns = proc_pid_ns(file_inode(m->file)->i_sb); |
| 1749 | nr = pid_nr_ns(pid, ns); | 1749 | nr = pid_nr_ns(pid, ns); |
| 1750 | } | 1750 | } |
| 1751 | 1751 | ||
| @@ -779,7 +779,7 @@ static void *ip6fl_seq_start(struct seq_file *seq, loff_t *pos) · 778 unmodified lines | |||
| 779 | { | 779 | { |
| 780 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | 780 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); |
| 781 | 781 | ||
| 782 | state->pid_ns = proc_pid_ns(file_inode(seq->file)); | 782 | state->pid_ns = proc_pid_ns(file_inode(seq->file)->i_sb); |
| 783 | 783 | ||
| 784 | rcu_read_lock_bh(); | 784 | rcu_read_lock_bh(); |
| 785 | return *pos ? ip6fl_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; | 785 | return *pos ? ip6fl_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; |
| @@ -162,7 +162,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, · 161 unmodified lines | |||
| 162 | if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') { | 162 | if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') { |
| 163 | char *ep; | 163 | char *ep; |
| 164 | const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10); | 164 | const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10); |
| 165 | struct pid_namespace *proc_pidns = proc_pid_ns(d_inode(dentry)); | 165 | struct pid_namespace *proc_pidns = proc_pid_ns(sb); |
| 166 | 166 | ||
| 167 | if (*ep == '/' && pid && pid == | 167 | if (*ep == '/' && pid && pid == |
| 168 | task_tgid_nr_ns(current, proc_pidns)) { | 168 | task_tgid_nr_ns(current, proc_pidns)) { |