Loading fs/proc/fd.c +44 −37 Original line number Diff line number Diff line Loading @@ -98,12 +98,27 @@ static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode) return !!file; } static void tid_fd_update_inode(struct task_struct *task, struct inode *inode, fmode_t f_mode) { task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); if (S_ISLNK(inode->i_mode)) { unsigned i_mode = S_IFLNK; if (f_mode & FMODE_READ) i_mode |= S_IRUSR | S_IXUSR; if (f_mode & FMODE_WRITE) i_mode |= S_IWUSR | S_IXUSR; inode->i_mode = i_mode; } security_task_to_inode(task, inode); } static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) { struct task_struct *task; struct inode *inode; unsigned int fd; fmode_t f_mode; if (flags & LOOKUP_RCU) return -ECHILD; Loading @@ -113,18 +128,9 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) fd = proc_fd(inode); if (task) { fmode_t f_mode; if (tid_fd_mode(task, fd, &f_mode)) { task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); if (S_ISLNK(inode->i_mode)) { unsigned i_mode = S_IFLNK; if (f_mode & FMODE_READ) i_mode |= S_IRUSR | S_IXUSR; if (f_mode & FMODE_WRITE) i_mode |= S_IWUSR | S_IXUSR; inode->i_mode = i_mode; } security_task_to_inode(task, inode); tid_fd_update_inode(task, inode, f_mode); put_task_struct(task); return 1; } Loading Loading @@ -168,34 +174,35 @@ static int proc_fd_link(struct dentry *dentry, struct path *path) return ret; } struct fd_data { fmode_t mode; unsigned fd; }; static int proc_fd_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr) { unsigned fd = (unsigned long)ptr; const struct fd_data *data = ptr; struct proc_inode *ei; struct inode *inode; inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK); if (!inode) goto out; return -ENOENT; ei = PROC_I(inode); ei->fd = fd; ei->fd = data->fd; inode->i_op = &proc_pid_link_inode_operations; inode->i_size = 64; ei->op.proc_get_link = proc_fd_link; tid_fd_update_inode(task, inode, data->mode); d_set_d_op(dentry, &tid_fd_dentry_operations); d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ if (tid_fd_revalidate(dentry, 0)) return 0; out: return -ENOENT; } static struct dentry *proc_lookupfd_common(struct inode *dir, Loading @@ -204,17 +211,16 @@ static struct dentry *proc_lookupfd_common(struct inode *dir, { struct task_struct *task = get_proc_task(dir); int result = -ENOENT; unsigned fd = name_to_int(&dentry->d_name); fmode_t f_mode; struct fd_data data = {.fd = name_to_int(&dentry->d_name)}; if (!task) goto out_no_task; if (fd == ~0U) if (data.fd == ~0U) goto out; if (!tid_fd_mode(task, fd, &f_mode)) if (!tid_fd_mode(task, data.fd, &data.mode)) goto out; result = instantiate(dir, dentry, task, (void *)(unsigned long)fd); result = instantiate(dir, dentry, task, &data); out: put_task_struct(task); out_no_task: Loading @@ -241,17 +247,22 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx, for (fd = ctx->pos - 2; fd < files_fdtable(files)->max_fds; fd++, ctx->pos++) { struct file *f; struct fd_data data; char name[10 + 1]; int len; if (!fcheck_files(files, fd)) f = fcheck_files(files, fd); if (!f) continue; data.mode = f->f_mode; rcu_read_unlock(); data.fd = fd; len = snprintf(name, sizeof(name), "%u", fd); if (!proc_fill_cache(file, ctx, name, len, instantiate, p, (void *)(unsigned long)fd)) &data)) goto out_fd_loop; cond_resched(); rcu_read_lock(); Loading Loading @@ -313,27 +324,23 @@ static int proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr) { unsigned fd = (unsigned long)ptr; const struct fd_data *data = ptr; struct proc_inode *ei; struct inode *inode; inode = proc_pid_make_inode(dir->i_sb, task, S_IFREG | S_IRUSR); if (!inode) goto out; return -ENOENT; ei = PROC_I(inode); ei->fd = fd; ei->fd = data->fd; inode->i_fop = &proc_fdinfo_file_operations; tid_fd_update_inode(task, inode, 0); d_set_d_op(dentry, &tid_fd_dentry_operations); d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ if (tid_fd_revalidate(dentry, 0)) return 0; out: return -ENOENT; } static struct dentry * Loading Loading
fs/proc/fd.c +44 −37 Original line number Diff line number Diff line Loading @@ -98,12 +98,27 @@ static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode) return !!file; } static void tid_fd_update_inode(struct task_struct *task, struct inode *inode, fmode_t f_mode) { task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); if (S_ISLNK(inode->i_mode)) { unsigned i_mode = S_IFLNK; if (f_mode & FMODE_READ) i_mode |= S_IRUSR | S_IXUSR; if (f_mode & FMODE_WRITE) i_mode |= S_IWUSR | S_IXUSR; inode->i_mode = i_mode; } security_task_to_inode(task, inode); } static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) { struct task_struct *task; struct inode *inode; unsigned int fd; fmode_t f_mode; if (flags & LOOKUP_RCU) return -ECHILD; Loading @@ -113,18 +128,9 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) fd = proc_fd(inode); if (task) { fmode_t f_mode; if (tid_fd_mode(task, fd, &f_mode)) { task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid); if (S_ISLNK(inode->i_mode)) { unsigned i_mode = S_IFLNK; if (f_mode & FMODE_READ) i_mode |= S_IRUSR | S_IXUSR; if (f_mode & FMODE_WRITE) i_mode |= S_IWUSR | S_IXUSR; inode->i_mode = i_mode; } security_task_to_inode(task, inode); tid_fd_update_inode(task, inode, f_mode); put_task_struct(task); return 1; } Loading Loading @@ -168,34 +174,35 @@ static int proc_fd_link(struct dentry *dentry, struct path *path) return ret; } struct fd_data { fmode_t mode; unsigned fd; }; static int proc_fd_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr) { unsigned fd = (unsigned long)ptr; const struct fd_data *data = ptr; struct proc_inode *ei; struct inode *inode; inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK); if (!inode) goto out; return -ENOENT; ei = PROC_I(inode); ei->fd = fd; ei->fd = data->fd; inode->i_op = &proc_pid_link_inode_operations; inode->i_size = 64; ei->op.proc_get_link = proc_fd_link; tid_fd_update_inode(task, inode, data->mode); d_set_d_op(dentry, &tid_fd_dentry_operations); d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ if (tid_fd_revalidate(dentry, 0)) return 0; out: return -ENOENT; } static struct dentry *proc_lookupfd_common(struct inode *dir, Loading @@ -204,17 +211,16 @@ static struct dentry *proc_lookupfd_common(struct inode *dir, { struct task_struct *task = get_proc_task(dir); int result = -ENOENT; unsigned fd = name_to_int(&dentry->d_name); fmode_t f_mode; struct fd_data data = {.fd = name_to_int(&dentry->d_name)}; if (!task) goto out_no_task; if (fd == ~0U) if (data.fd == ~0U) goto out; if (!tid_fd_mode(task, fd, &f_mode)) if (!tid_fd_mode(task, data.fd, &data.mode)) goto out; result = instantiate(dir, dentry, task, (void *)(unsigned long)fd); result = instantiate(dir, dentry, task, &data); out: put_task_struct(task); out_no_task: Loading @@ -241,17 +247,22 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx, for (fd = ctx->pos - 2; fd < files_fdtable(files)->max_fds; fd++, ctx->pos++) { struct file *f; struct fd_data data; char name[10 + 1]; int len; if (!fcheck_files(files, fd)) f = fcheck_files(files, fd); if (!f) continue; data.mode = f->f_mode; rcu_read_unlock(); data.fd = fd; len = snprintf(name, sizeof(name), "%u", fd); if (!proc_fill_cache(file, ctx, name, len, instantiate, p, (void *)(unsigned long)fd)) &data)) goto out_fd_loop; cond_resched(); rcu_read_lock(); Loading Loading @@ -313,27 +324,23 @@ static int proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry, struct task_struct *task, const void *ptr) { unsigned fd = (unsigned long)ptr; const struct fd_data *data = ptr; struct proc_inode *ei; struct inode *inode; inode = proc_pid_make_inode(dir->i_sb, task, S_IFREG | S_IRUSR); if (!inode) goto out; return -ENOENT; ei = PROC_I(inode); ei->fd = fd; ei->fd = data->fd; inode->i_fop = &proc_fdinfo_file_operations; tid_fd_update_inode(task, inode, 0); d_set_d_op(dentry, &tid_fd_dentry_operations); d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ if (tid_fd_revalidate(dentry, 0)) return 0; out: return -ENOENT; } static struct dentry * Loading