^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/dcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/path.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/fdtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/pid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "../mount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "fd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static int seq_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct files_struct *files = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int f_flags = 0, ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct file *file = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct task_struct *task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) task = get_proc_task(m->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (!task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) files = get_files_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) put_task_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) if (files) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned int fd = proc_fd(m->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) spin_lock(&files->file_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) file = fcheck_files(files, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct fdtable *fdt = files_fdtable(files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) f_flags = file->f_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (close_on_exec(fd, fdt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) f_flags |= O_CLOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) get_file(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) spin_unlock(&files->file_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) put_files_struct(files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\nino:\t%lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) (long long)file->f_pos, f_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) real_mount(file->f_path.mnt)->mnt_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) file_inode(file)->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) show_fd_locks(m, file, files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (seq_has_overflowed(m))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (file->f_op->show_fdinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) file->f_op->show_fdinfo(m, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) fput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static int proc_fdinfo_access_allowed(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) bool allowed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct task_struct *task = get_proc_task(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (!task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return -ESRCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) put_task_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!allowed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int seq_fdinfo_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int ret = proc_fdinfo_access_allowed(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return single_open(file, seq_show, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static const struct file_operations proc_fdinfo_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .open = seq_fdinfo_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct files_struct *files = get_files_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct file *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!files)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) file = fcheck_files(files, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *mode = file->f_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) put_files_struct(files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return !!file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void tid_fd_update_inode(struct task_struct *task, struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) fmode_t f_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (S_ISLNK(inode->i_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned i_mode = S_IFLNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (f_mode & FMODE_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) i_mode |= S_IRUSR | S_IXUSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (f_mode & FMODE_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) i_mode |= S_IWUSR | S_IXUSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) inode->i_mode = i_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) security_task_to_inode(task, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct task_struct *task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (flags & LOOKUP_RCU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return -ECHILD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) task = get_proc_task(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) fd = proc_fd(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (task) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) fmode_t f_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (tid_fd_mode(task, fd, &f_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) tid_fd_update_inode(task, inode, f_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) put_task_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) put_task_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static const struct dentry_operations tid_fd_dentry_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .d_revalidate = tid_fd_revalidate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .d_delete = pid_delete_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int proc_fd_link(struct dentry *dentry, struct path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct files_struct *files = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct task_struct *task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) task = get_proc_task(d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (task) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) files = get_files_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) put_task_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (files) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned int fd = proc_fd(d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct file *fd_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) spin_lock(&files->file_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) fd_file = fcheck_files(files, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (fd_file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) *path = fd_file->f_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) path_get(&fd_file->f_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) spin_unlock(&files->file_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) put_files_struct(files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct fd_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) fmode_t mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) unsigned fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static struct dentry *proc_fd_instantiate(struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct task_struct *task, const void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) const struct fd_data *data = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct proc_inode *ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ei = PROC_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ei->fd = data->fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) inode->i_op = &proc_pid_link_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) inode->i_size = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ei->op.proc_get_link = proc_fd_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) tid_fd_update_inode(task, inode, data->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) d_set_d_op(dentry, &tid_fd_dentry_operations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return d_splice_alias(inode, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static struct dentry *proc_lookupfd_common(struct inode *dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) instantiate_t instantiate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct task_struct *task = get_proc_task(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct fd_data data = {.fd = name_to_int(&dentry->d_name)};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct dentry *result = ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (!task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto out_no_task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (data.fd == ~0U)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (!tid_fd_mode(task, data.fd, &data.mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) result = instantiate(dentry, task, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) put_task_struct(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) out_no_task:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static int proc_readfd_common(struct file *file, struct dir_context *ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) instantiate_t instantiate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct task_struct *p = get_proc_task(file_inode(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct files_struct *files;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) unsigned int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (!dir_emit_dots(file, ctx))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) files = get_files_struct(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!files)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) for (fd = ctx->pos - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) fd < files_fdtable(files)->max_fds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) fd++, ctx->pos++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct file *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct fd_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) char name[10 + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) f = fcheck_files(files, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) data.mode = f->f_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) data.fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) len = snprintf(name, sizeof(name), "%u", fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!proc_fill_cache(file, ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) name, len, instantiate, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) &data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) goto out_fd_loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) out_fd_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) put_files_struct(files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) put_task_struct(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int proc_readfd(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return proc_readfd_common(file, ctx, proc_fd_instantiate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) const struct file_operations proc_fd_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .read = generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .iterate_shared = proc_readfd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * /proc/pid/fd needs a special permission handler so that a process can still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * access /proc/self/fd after it has executed a setuid().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) int proc_fd_permission(struct inode *inode, int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct task_struct *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) rv = generic_permission(inode, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (rv == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) p = pid_task(proc_pid(inode), PIDTYPE_PID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (p && same_thread_group(p, current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) rv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) const struct inode_operations proc_fd_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .lookup = proc_lookupfd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .permission = proc_fd_permission,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .setattr = proc_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static struct dentry *proc_fdinfo_instantiate(struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct task_struct *task, const void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) const struct fd_data *data = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct proc_inode *ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) inode = proc_pid_make_inode(dentry->d_sb, task, S_IFREG | S_IRUGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) ei = PROC_I(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) ei->fd = data->fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) inode->i_fop = &proc_fdinfo_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) tid_fd_update_inode(task, inode, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) d_set_d_op(dentry, &tid_fd_dentry_operations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return d_splice_alias(inode, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static struct dentry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static int proc_readfdinfo(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return proc_readfd_common(file, ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) proc_fdinfo_instantiate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static int proc_open_fdinfo(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) int ret = proc_fdinfo_access_allowed(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) const struct inode_operations proc_fdinfo_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .lookup = proc_lookupfdinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) .setattr = proc_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) const struct file_operations proc_fdinfo_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) .open = proc_open_fdinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) .read = generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .iterate_shared = proc_readfdinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) };