Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
^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) };