File Index
Files and directories
Sign in
FILE

fd.c

File preview with syntax highlighting.

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