1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 23f07c014SIngo Molnar #include <linux/sched/signal.h> 3faf60af1SCyrill Gorcunov #include <linux/errno.h> 4faf60af1SCyrill Gorcunov #include <linux/dcache.h> 5faf60af1SCyrill Gorcunov #include <linux/path.h> 6faf60af1SCyrill Gorcunov #include <linux/fdtable.h> 7faf60af1SCyrill Gorcunov #include <linux/namei.h> 8faf60af1SCyrill Gorcunov #include <linux/pid.h> 9faf60af1SCyrill Gorcunov #include <linux/security.h> 10ddd3e077SCyrill Gorcunov #include <linux/file.h> 11ddd3e077SCyrill Gorcunov #include <linux/seq_file.h> 126c8c9031SAndrey Vagin #include <linux/fs.h> 13faf60af1SCyrill Gorcunov 14faf60af1SCyrill Gorcunov #include <linux/proc_fs.h> 15faf60af1SCyrill Gorcunov 1649d063cbSAndrey Vagin #include "../mount.h" 17faf60af1SCyrill Gorcunov #include "internal.h" 18faf60af1SCyrill Gorcunov #include "fd.h" 19faf60af1SCyrill Gorcunov 20ddd3e077SCyrill Gorcunov static int seq_show(struct seq_file *m, void *v) 21faf60af1SCyrill Gorcunov { 22faf60af1SCyrill Gorcunov struct files_struct *files = NULL; 23ddd3e077SCyrill Gorcunov int f_flags = 0, ret = -ENOENT; 24ddd3e077SCyrill Gorcunov struct file *file = NULL; 25ddd3e077SCyrill Gorcunov struct task_struct *task; 26faf60af1SCyrill Gorcunov 27ddd3e077SCyrill Gorcunov task = get_proc_task(m->private); 28ddd3e077SCyrill Gorcunov if (!task) 29ddd3e077SCyrill Gorcunov return -ENOENT; 30ddd3e077SCyrill Gorcunov 31faf60af1SCyrill Gorcunov files = get_files_struct(task); 32faf60af1SCyrill Gorcunov put_task_struct(task); 33ddd3e077SCyrill Gorcunov 34faf60af1SCyrill Gorcunov if (files) { 35771187d6SAlexey Dobriyan unsigned int fd = proc_fd(m->private); 36ddd3e077SCyrill Gorcunov 37faf60af1SCyrill Gorcunov spin_lock(&files->file_lock); 38faf60af1SCyrill Gorcunov file = fcheck_files(files, fd); 39faf60af1SCyrill Gorcunov if (file) { 40ddd3e077SCyrill Gorcunov struct fdtable *fdt = files_fdtable(files); 41faf60af1SCyrill Gorcunov 42c6f3d811SAl Viro f_flags = file->f_flags; 43faf60af1SCyrill Gorcunov if (close_on_exec(fd, fdt)) 44faf60af1SCyrill Gorcunov f_flags |= O_CLOEXEC; 45faf60af1SCyrill Gorcunov 46ddd3e077SCyrill Gorcunov get_file(file); 47ddd3e077SCyrill Gorcunov ret = 0; 48faf60af1SCyrill Gorcunov } 49faf60af1SCyrill Gorcunov spin_unlock(&files->file_lock); 50faf60af1SCyrill Gorcunov put_files_struct(files); 51faf60af1SCyrill Gorcunov } 52ddd3e077SCyrill Gorcunov 536c8c9031SAndrey Vagin if (ret) 546c8c9031SAndrey Vagin return ret; 556c8c9031SAndrey Vagin 5649d063cbSAndrey Vagin seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n", 5749d063cbSAndrey Vagin (long long)file->f_pos, f_flags, 5849d063cbSAndrey Vagin real_mount(file->f_path.mnt)->mnt_id); 596c8c9031SAndrey Vagin 606c8c9031SAndrey Vagin show_fd_locks(m, file, files); 616c8c9031SAndrey Vagin if (seq_has_overflowed(m)) 626c8c9031SAndrey Vagin goto out; 636c8c9031SAndrey Vagin 6455985dd7SCyrill Gorcunov if (file->f_op->show_fdinfo) 65a3816ab0SJoe Perches file->f_op->show_fdinfo(m, file); 66faf60af1SCyrill Gorcunov 676c8c9031SAndrey Vagin out: 686c8c9031SAndrey Vagin fput(file); 696c8c9031SAndrey Vagin return 0; 70ddd3e077SCyrill Gorcunov } 71ddd3e077SCyrill Gorcunov 72ddd3e077SCyrill Gorcunov static int seq_fdinfo_open(struct inode *inode, struct file *file) 73ddd3e077SCyrill Gorcunov { 74ddd3e077SCyrill Gorcunov return single_open(file, seq_show, inode); 75ddd3e077SCyrill Gorcunov } 76ddd3e077SCyrill Gorcunov 77ddd3e077SCyrill Gorcunov static const struct file_operations proc_fdinfo_file_operations = { 78ddd3e077SCyrill Gorcunov .open = seq_fdinfo_open, 79ddd3e077SCyrill Gorcunov .read = seq_read, 80ddd3e077SCyrill Gorcunov .llseek = seq_lseek, 81ddd3e077SCyrill Gorcunov .release = single_release, 82ddd3e077SCyrill Gorcunov }; 83ddd3e077SCyrill Gorcunov 841ae9bd8bSAl Viro static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode) 851ae9bd8bSAl Viro { 861ae9bd8bSAl Viro struct files_struct *files = get_files_struct(task); 871ae9bd8bSAl Viro struct file *file; 881ae9bd8bSAl Viro 891ae9bd8bSAl Viro if (!files) 901ae9bd8bSAl Viro return false; 911ae9bd8bSAl Viro 921ae9bd8bSAl Viro rcu_read_lock(); 931ae9bd8bSAl Viro file = fcheck_files(files, fd); 941ae9bd8bSAl Viro if (file) 951ae9bd8bSAl Viro *mode = file->f_mode; 961ae9bd8bSAl Viro rcu_read_unlock(); 971ae9bd8bSAl Viro put_files_struct(files); 981ae9bd8bSAl Viro return !!file; 991ae9bd8bSAl Viro } 1001ae9bd8bSAl Viro 101*98836386SAl Viro static void tid_fd_update_inode(struct task_struct *task, struct inode *inode, 102*98836386SAl Viro fmode_t f_mode) 103faf60af1SCyrill Gorcunov { 10468eb94f1SEric W. Biederman task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); 105faf60af1SCyrill Gorcunov 106faf60af1SCyrill Gorcunov if (S_ISLNK(inode->i_mode)) { 107faf60af1SCyrill Gorcunov unsigned i_mode = S_IFLNK; 108faf60af1SCyrill Gorcunov if (f_mode & FMODE_READ) 109faf60af1SCyrill Gorcunov i_mode |= S_IRUSR | S_IXUSR; 110faf60af1SCyrill Gorcunov if (f_mode & FMODE_WRITE) 111faf60af1SCyrill Gorcunov i_mode |= S_IWUSR | S_IXUSR; 112faf60af1SCyrill Gorcunov inode->i_mode = i_mode; 113faf60af1SCyrill Gorcunov } 114faf60af1SCyrill Gorcunov security_task_to_inode(task, inode); 115*98836386SAl Viro } 116*98836386SAl Viro 117*98836386SAl Viro static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) 118*98836386SAl Viro { 119*98836386SAl Viro struct task_struct *task; 120*98836386SAl Viro struct inode *inode; 121*98836386SAl Viro unsigned int fd; 122*98836386SAl Viro 123*98836386SAl Viro if (flags & LOOKUP_RCU) 124*98836386SAl Viro return -ECHILD; 125*98836386SAl Viro 126*98836386SAl Viro inode = d_inode(dentry); 127*98836386SAl Viro task = get_proc_task(inode); 128*98836386SAl Viro fd = proc_fd(inode); 129*98836386SAl Viro 130*98836386SAl Viro if (task) { 131*98836386SAl Viro fmode_t f_mode; 132*98836386SAl Viro if (tid_fd_mode(task, fd, &f_mode)) { 133*98836386SAl Viro tid_fd_update_inode(task, inode, f_mode); 134faf60af1SCyrill Gorcunov put_task_struct(task); 135faf60af1SCyrill Gorcunov return 1; 136faf60af1SCyrill Gorcunov } 137faf60af1SCyrill Gorcunov put_task_struct(task); 138faf60af1SCyrill Gorcunov } 139faf60af1SCyrill Gorcunov return 0; 140faf60af1SCyrill Gorcunov } 141faf60af1SCyrill Gorcunov 142faf60af1SCyrill Gorcunov static const struct dentry_operations tid_fd_dentry_operations = { 143faf60af1SCyrill Gorcunov .d_revalidate = tid_fd_revalidate, 144faf60af1SCyrill Gorcunov .d_delete = pid_delete_dentry, 145faf60af1SCyrill Gorcunov }; 146faf60af1SCyrill Gorcunov 147faf60af1SCyrill Gorcunov static int proc_fd_link(struct dentry *dentry, struct path *path) 148faf60af1SCyrill Gorcunov { 149ddd3e077SCyrill Gorcunov struct files_struct *files = NULL; 150ddd3e077SCyrill Gorcunov struct task_struct *task; 151ddd3e077SCyrill Gorcunov int ret = -ENOENT; 152ddd3e077SCyrill Gorcunov 1532b0143b5SDavid Howells task = get_proc_task(d_inode(dentry)); 154ddd3e077SCyrill Gorcunov if (task) { 155ddd3e077SCyrill Gorcunov files = get_files_struct(task); 156ddd3e077SCyrill Gorcunov put_task_struct(task); 157ddd3e077SCyrill Gorcunov } 158ddd3e077SCyrill Gorcunov 159ddd3e077SCyrill Gorcunov if (files) { 160771187d6SAlexey Dobriyan unsigned int fd = proc_fd(d_inode(dentry)); 161ddd3e077SCyrill Gorcunov struct file *fd_file; 162ddd3e077SCyrill Gorcunov 163ddd3e077SCyrill Gorcunov spin_lock(&files->file_lock); 164ddd3e077SCyrill Gorcunov fd_file = fcheck_files(files, fd); 165ddd3e077SCyrill Gorcunov if (fd_file) { 166ddd3e077SCyrill Gorcunov *path = fd_file->f_path; 167ddd3e077SCyrill Gorcunov path_get(&fd_file->f_path); 168ddd3e077SCyrill Gorcunov ret = 0; 169ddd3e077SCyrill Gorcunov } 170ddd3e077SCyrill Gorcunov spin_unlock(&files->file_lock); 171ddd3e077SCyrill Gorcunov put_files_struct(files); 172ddd3e077SCyrill Gorcunov } 173ddd3e077SCyrill Gorcunov 174ddd3e077SCyrill Gorcunov return ret; 175faf60af1SCyrill Gorcunov } 176faf60af1SCyrill Gorcunov 177*98836386SAl Viro struct fd_data { 178*98836386SAl Viro fmode_t mode; 179*98836386SAl Viro unsigned fd; 180*98836386SAl Viro }; 181*98836386SAl Viro 182c52a47acSAl Viro static int 183faf60af1SCyrill Gorcunov proc_fd_instantiate(struct inode *dir, struct dentry *dentry, 184faf60af1SCyrill Gorcunov struct task_struct *task, const void *ptr) 185faf60af1SCyrill Gorcunov { 186*98836386SAl Viro const struct fd_data *data = ptr; 187faf60af1SCyrill Gorcunov struct proc_inode *ei; 188faf60af1SCyrill Gorcunov struct inode *inode; 189faf60af1SCyrill Gorcunov 190db978da8SAndreas Gruenbacher inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK); 191faf60af1SCyrill Gorcunov if (!inode) 192*98836386SAl Viro return -ENOENT; 193faf60af1SCyrill Gorcunov 194faf60af1SCyrill Gorcunov ei = PROC_I(inode); 195*98836386SAl Viro ei->fd = data->fd; 196faf60af1SCyrill Gorcunov 197faf60af1SCyrill Gorcunov inode->i_op = &proc_pid_link_inode_operations; 198faf60af1SCyrill Gorcunov inode->i_size = 64; 199faf60af1SCyrill Gorcunov 200faf60af1SCyrill Gorcunov ei->op.proc_get_link = proc_fd_link; 201*98836386SAl Viro tid_fd_update_inode(task, inode, data->mode); 202faf60af1SCyrill Gorcunov 203faf60af1SCyrill Gorcunov d_set_d_op(dentry, &tid_fd_dentry_operations); 204faf60af1SCyrill Gorcunov d_add(dentry, inode); 205c52a47acSAl Viro return 0; 206faf60af1SCyrill Gorcunov } 207faf60af1SCyrill Gorcunov 208faf60af1SCyrill Gorcunov static struct dentry *proc_lookupfd_common(struct inode *dir, 209faf60af1SCyrill Gorcunov struct dentry *dentry, 210faf60af1SCyrill Gorcunov instantiate_t instantiate) 211faf60af1SCyrill Gorcunov { 212faf60af1SCyrill Gorcunov struct task_struct *task = get_proc_task(dir); 213c52a47acSAl Viro int result = -ENOENT; 214*98836386SAl Viro struct fd_data data = {.fd = name_to_int(&dentry->d_name)}; 215faf60af1SCyrill Gorcunov 216faf60af1SCyrill Gorcunov if (!task) 217faf60af1SCyrill Gorcunov goto out_no_task; 218*98836386SAl Viro if (data.fd == ~0U) 219faf60af1SCyrill Gorcunov goto out; 220*98836386SAl Viro if (!tid_fd_mode(task, data.fd, &data.mode)) 2211ae9bd8bSAl Viro goto out; 222faf60af1SCyrill Gorcunov 223*98836386SAl Viro result = instantiate(dir, dentry, task, &data); 224faf60af1SCyrill Gorcunov out: 225faf60af1SCyrill Gorcunov put_task_struct(task); 226faf60af1SCyrill Gorcunov out_no_task: 227c52a47acSAl Viro return ERR_PTR(result); 228faf60af1SCyrill Gorcunov } 229faf60af1SCyrill Gorcunov 230f0c3b509SAl Viro static int proc_readfd_common(struct file *file, struct dir_context *ctx, 231f0c3b509SAl Viro instantiate_t instantiate) 232faf60af1SCyrill Gorcunov { 233f0c3b509SAl Viro struct task_struct *p = get_proc_task(file_inode(file)); 234faf60af1SCyrill Gorcunov struct files_struct *files; 235f0c3b509SAl Viro unsigned int fd; 236faf60af1SCyrill Gorcunov 237faf60af1SCyrill Gorcunov if (!p) 238f0c3b509SAl Viro return -ENOENT; 239faf60af1SCyrill Gorcunov 240f0c3b509SAl Viro if (!dir_emit_dots(file, ctx)) 241faf60af1SCyrill Gorcunov goto out; 242faf60af1SCyrill Gorcunov files = get_files_struct(p); 243faf60af1SCyrill Gorcunov if (!files) 244faf60af1SCyrill Gorcunov goto out; 245f0c3b509SAl Viro 246faf60af1SCyrill Gorcunov rcu_read_lock(); 247f0c3b509SAl Viro for (fd = ctx->pos - 2; 248faf60af1SCyrill Gorcunov fd < files_fdtable(files)->max_fds; 249f0c3b509SAl Viro fd++, ctx->pos++) { 250*98836386SAl Viro struct file *f; 251*98836386SAl Viro struct fd_data data; 252e3912ac3SAlexey Dobriyan char name[10 + 1]; 253faf60af1SCyrill Gorcunov int len; 254faf60af1SCyrill Gorcunov 255*98836386SAl Viro f = fcheck_files(files, fd); 256*98836386SAl Viro if (!f) 257faf60af1SCyrill Gorcunov continue; 258*98836386SAl Viro data.mode = f->f_mode; 259faf60af1SCyrill Gorcunov rcu_read_unlock(); 260*98836386SAl Viro data.fd = fd; 261faf60af1SCyrill Gorcunov 262771187d6SAlexey Dobriyan len = snprintf(name, sizeof(name), "%u", fd); 263f0c3b509SAl Viro if (!proc_fill_cache(file, ctx, 264faf60af1SCyrill Gorcunov name, len, instantiate, p, 265*98836386SAl Viro &data)) 266faf60af1SCyrill Gorcunov goto out_fd_loop; 2673cc4a84eSEric Dumazet cond_resched(); 268faf60af1SCyrill Gorcunov rcu_read_lock(); 269faf60af1SCyrill Gorcunov } 270faf60af1SCyrill Gorcunov rcu_read_unlock(); 271faf60af1SCyrill Gorcunov out_fd_loop: 272faf60af1SCyrill Gorcunov put_files_struct(files); 273faf60af1SCyrill Gorcunov out: 274faf60af1SCyrill Gorcunov put_task_struct(p); 275f0c3b509SAl Viro return 0; 276faf60af1SCyrill Gorcunov } 277faf60af1SCyrill Gorcunov 278f0c3b509SAl Viro static int proc_readfd(struct file *file, struct dir_context *ctx) 279faf60af1SCyrill Gorcunov { 280f0c3b509SAl Viro return proc_readfd_common(file, ctx, proc_fd_instantiate); 281faf60af1SCyrill Gorcunov } 282faf60af1SCyrill Gorcunov 283faf60af1SCyrill Gorcunov const struct file_operations proc_fd_operations = { 284faf60af1SCyrill Gorcunov .read = generic_read_dir, 285f50752eaSAl Viro .iterate_shared = proc_readfd, 286f50752eaSAl Viro .llseek = generic_file_llseek, 287faf60af1SCyrill Gorcunov }; 288faf60af1SCyrill Gorcunov 289faf60af1SCyrill Gorcunov static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry, 290faf60af1SCyrill Gorcunov unsigned int flags) 291faf60af1SCyrill Gorcunov { 292faf60af1SCyrill Gorcunov return proc_lookupfd_common(dir, dentry, proc_fd_instantiate); 293faf60af1SCyrill Gorcunov } 294faf60af1SCyrill Gorcunov 295faf60af1SCyrill Gorcunov /* 296faf60af1SCyrill Gorcunov * /proc/pid/fd needs a special permission handler so that a process can still 297faf60af1SCyrill Gorcunov * access /proc/self/fd after it has executed a setuid(). 298faf60af1SCyrill Gorcunov */ 299faf60af1SCyrill Gorcunov int proc_fd_permission(struct inode *inode, int mask) 300faf60af1SCyrill Gorcunov { 30154708d28SOleg Nesterov struct task_struct *p; 30254708d28SOleg Nesterov int rv; 30354708d28SOleg Nesterov 30454708d28SOleg Nesterov rv = generic_permission(inode, mask); 305faf60af1SCyrill Gorcunov if (rv == 0) 30654708d28SOleg Nesterov return rv; 30754708d28SOleg Nesterov 30854708d28SOleg Nesterov rcu_read_lock(); 30954708d28SOleg Nesterov p = pid_task(proc_pid(inode), PIDTYPE_PID); 31054708d28SOleg Nesterov if (p && same_thread_group(p, current)) 311faf60af1SCyrill Gorcunov rv = 0; 31254708d28SOleg Nesterov rcu_read_unlock(); 31354708d28SOleg Nesterov 314faf60af1SCyrill Gorcunov return rv; 315faf60af1SCyrill Gorcunov } 316faf60af1SCyrill Gorcunov 317faf60af1SCyrill Gorcunov const struct inode_operations proc_fd_inode_operations = { 318faf60af1SCyrill Gorcunov .lookup = proc_lookupfd, 319faf60af1SCyrill Gorcunov .permission = proc_fd_permission, 320faf60af1SCyrill Gorcunov .setattr = proc_setattr, 321faf60af1SCyrill Gorcunov }; 322faf60af1SCyrill Gorcunov 323c52a47acSAl Viro static int 324faf60af1SCyrill Gorcunov proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry, 325faf60af1SCyrill Gorcunov struct task_struct *task, const void *ptr) 326faf60af1SCyrill Gorcunov { 327*98836386SAl Viro const struct fd_data *data = ptr; 328faf60af1SCyrill Gorcunov struct proc_inode *ei; 329faf60af1SCyrill Gorcunov struct inode *inode; 330faf60af1SCyrill Gorcunov 331db978da8SAndreas Gruenbacher inode = proc_pid_make_inode(dir->i_sb, task, S_IFREG | S_IRUSR); 332faf60af1SCyrill Gorcunov if (!inode) 333*98836386SAl Viro return -ENOENT; 334faf60af1SCyrill Gorcunov 335faf60af1SCyrill Gorcunov ei = PROC_I(inode); 336*98836386SAl Viro ei->fd = data->fd; 337faf60af1SCyrill Gorcunov 338faf60af1SCyrill Gorcunov inode->i_fop = &proc_fdinfo_file_operations; 339*98836386SAl Viro tid_fd_update_inode(task, inode, 0); 340faf60af1SCyrill Gorcunov 341faf60af1SCyrill Gorcunov d_set_d_op(dentry, &tid_fd_dentry_operations); 342faf60af1SCyrill Gorcunov d_add(dentry, inode); 343c52a47acSAl Viro return 0; 344faf60af1SCyrill Gorcunov } 345faf60af1SCyrill Gorcunov 346faf60af1SCyrill Gorcunov static struct dentry * 347faf60af1SCyrill Gorcunov proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags) 348faf60af1SCyrill Gorcunov { 349faf60af1SCyrill Gorcunov return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); 350faf60af1SCyrill Gorcunov } 351faf60af1SCyrill Gorcunov 352f0c3b509SAl Viro static int proc_readfdinfo(struct file *file, struct dir_context *ctx) 353faf60af1SCyrill Gorcunov { 354f0c3b509SAl Viro return proc_readfd_common(file, ctx, 355faf60af1SCyrill Gorcunov proc_fdinfo_instantiate); 356faf60af1SCyrill Gorcunov } 357faf60af1SCyrill Gorcunov 358faf60af1SCyrill Gorcunov const struct inode_operations proc_fdinfo_inode_operations = { 359faf60af1SCyrill Gorcunov .lookup = proc_lookupfdinfo, 360faf60af1SCyrill Gorcunov .setattr = proc_setattr, 361faf60af1SCyrill Gorcunov }; 362faf60af1SCyrill Gorcunov 363faf60af1SCyrill Gorcunov const struct file_operations proc_fdinfo_operations = { 364faf60af1SCyrill Gorcunov .read = generic_read_dir, 365f50752eaSAl Viro .iterate_shared = proc_readfdinfo, 366f50752eaSAl Viro .llseek = generic_file_llseek, 367faf60af1SCyrill Gorcunov }; 368