Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 273250
b: refs/heads/master
c: aa6afca
h: refs/heads/master
v: v3
  • Loading branch information
Vasiliy Kulikov authored and Linus Torvalds committed Nov 2, 2011
1 parent 1e7a87d commit 1e0364c
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 44 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 887df07891de0435c25cffb92268fea2c621f99c
refs/heads/master: aa6afca5bcaba8101f3ea09d5c3e4100b2b9f0e5
146 changes: 103 additions & 43 deletions trunk/fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1652,12 +1652,46 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b
return error;
}

static int proc_pid_fd_link_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
int rc;

if (task == NULL)
return -ESRCH;

rc = -EACCES;
if (lock_trace(task))
goto out_task;

generic_fillattr(inode, stat);
unlock_trace(task);
rc = 0;
out_task:
put_task_struct(task);
return rc;
}

static const struct inode_operations proc_pid_link_inode_operations = {
.readlink = proc_pid_readlink,
.follow_link = proc_pid_follow_link,
.setattr = proc_setattr,
};

static const struct inode_operations proc_fdinfo_link_inode_operations = {
.setattr = proc_setattr,
.getattr = proc_pid_fd_link_getattr,
};

static const struct inode_operations proc_fd_link_inode_operations = {
.readlink = proc_pid_readlink,
.follow_link = proc_pid_follow_link,
.setattr = proc_setattr,
.getattr = proc_pid_fd_link_getattr,
};


/* building an inode */

Expand Down Expand Up @@ -1889,49 +1923,61 @@ static unsigned name_to_int(struct dentry *dentry)

static int proc_fd_info(struct inode *inode, struct path *path, char *info)
{
struct task_struct *task = get_proc_task(inode);
struct files_struct *files = NULL;
struct task_struct *task;
struct files_struct *files;
struct file *file;
int fd = proc_fd(inode);
int rc;

if (task) {
files = get_files_struct(task);
put_task_struct(task);
}
if (files) {
/*
* We are not taking a ref to the file structure, so we must
* hold ->file_lock.
*/
spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (file) {
unsigned int f_flags;
struct fdtable *fdt;

fdt = files_fdtable(files);
f_flags = file->f_flags & ~O_CLOEXEC;
if (FD_ISSET(fd, fdt->close_on_exec))
f_flags |= O_CLOEXEC;

if (path) {
*path = file->f_path;
path_get(&file->f_path);
}
if (info)
snprintf(info, PROC_FDINFO_MAX,
"pos:\t%lli\n"
"flags:\t0%o\n",
(long long) file->f_pos,
f_flags);
spin_unlock(&files->file_lock);
put_files_struct(files);
return 0;
task = get_proc_task(inode);
if (!task)
return -ENOENT;

rc = -EACCES;
if (lock_trace(task))
goto out_task;

rc = -ENOENT;
files = get_files_struct(task);
if (files == NULL)
goto out_unlock;

/*
* We are not taking a ref to the file structure, so we must
* hold ->file_lock.
*/
spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (file) {
unsigned int f_flags;
struct fdtable *fdt;

fdt = files_fdtable(files);
f_flags = file->f_flags & ~O_CLOEXEC;
if (FD_ISSET(fd, fdt->close_on_exec))
f_flags |= O_CLOEXEC;

if (path) {
*path = file->f_path;
path_get(&file->f_path);
}
spin_unlock(&files->file_lock);
put_files_struct(files);
}
return -ENOENT;
if (info)
snprintf(info, PROC_FDINFO_MAX,
"pos:\t%lli\n"
"flags:\t0%o\n",
(long long) file->f_pos,
f_flags);
rc = 0;
} else
rc = -ENOENT;
spin_unlock(&files->file_lock);
put_files_struct(files);

out_unlock:
unlock_trace(task);
out_task:
put_task_struct(task);
return rc;
}

static int proc_fd_link(struct inode *inode, struct path *path)
Expand Down Expand Up @@ -2026,7 +2072,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
spin_unlock(&files->file_lock);
put_files_struct(files);

inode->i_op = &proc_pid_link_inode_operations;
inode->i_op = &proc_fd_link_inode_operations;
inode->i_size = 64;
ei->op.proc_get_link = proc_fd_link;
d_set_d_op(dentry, &tid_fd_dentry_operations);
Expand Down Expand Up @@ -2058,7 +2104,12 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
if (fd == ~0U)
goto out;

result = ERR_PTR(-EACCES);
if (lock_trace(task))
goto out;

result = instantiate(dir, dentry, task, &fd);
unlock_trace(task);
out:
put_task_struct(task);
out_no_task:
Expand All @@ -2078,23 +2129,28 @@ static int proc_readfd_common(struct file * filp, void * dirent,
retval = -ENOENT;
if (!p)
goto out_no_task;

retval = -EACCES;
if (lock_trace(p))
goto out;

retval = 0;

fd = filp->f_pos;
switch (fd) {
case 0:
if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
goto out;
goto out_unlock;
filp->f_pos++;
case 1:
ino = parent_ino(dentry);
if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
goto out;
goto out_unlock;
filp->f_pos++;
default:
files = get_files_struct(p);
if (!files)
goto out;
goto out_unlock;
rcu_read_lock();
for (fd = filp->f_pos-2;
fd < files_fdtable(files)->max_fds;
Expand All @@ -2118,6 +2174,9 @@ static int proc_readfd_common(struct file * filp, void * dirent,
rcu_read_unlock();
put_files_struct(files);
}

out_unlock:
unlock_trace(p);
out:
put_task_struct(p);
out_no_task:
Expand Down Expand Up @@ -2195,6 +2254,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
ei->fd = fd;
inode->i_mode = S_IFREG | S_IRUSR;
inode->i_fop = &proc_fdinfo_file_operations;
inode->i_op = &proc_fdinfo_link_inode_operations;
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 */
Expand Down

0 comments on commit 1e0364c

Please sign in to comment.