View | Details | Raw Unified | Return to bug 728774
Collapse All | Expand All

(-)a/fs/namei.c (+5 lines)
Lines 3294-3299 out: Link Here
3294
				error = -ECHILD;
3294
				error = -ECHILD;
3295
			else
3295
			else
3296
				error = -ESTALE;
3296
				error = -ESTALE;
3297
		} else if (nd->flags & LOOKUP_DUP_FD) {
3298
			file = fget_raw(nd->dup_fd);
3299
			if (S_ISSOCK(file->f_inode->i_mode))
3300
				return file;
3301
			fput(file);
3297
		}
3302
		}
3298
		file = ERR_PTR(error);
3303
		file = ERR_PTR(error);
3299
	}
3304
	}
(-)a/fs/proc/base.c (-2 / +2 lines)
Lines 1454-1460 static int proc_exe_link(struct dentry * Link Here
1454
		return -ENOENT;
1454
		return -ENOENT;
1455
}
1455
}
1456
1456
1457
static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
1457
void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
1458
{
1458
{
1459
	struct inode *inode = dentry->d_inode;
1459
	struct inode *inode = dentry->d_inode;
1460
	struct path path;
1460
	struct path path;
Lines 1498-1504 static int do_proc_readlink(struct path Link Here
1498
	return len;
1498
	return len;
1499
}
1499
}
1500
1500
1501
static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int buflen)
1501
int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int buflen)
1502
{
1502
{
1503
	int error = -EACCES;
1503
	int error = -EACCES;
1504
	struct inode *inode = dentry->d_inode;
1504
	struct inode *inode = dentry->d_inode;
(-)a/fs/proc/fd.c (-1 / +34 lines)
Lines 167-172 static int proc_fd_link(struct dentry *d Link Here
167
	return ret;
167
	return ret;
168
}
168
}
169
169
170
void *proc_pid_fd_follow_link(struct dentry *dentry, struct nameidata *nd)
171
{
172
	void *v;
173
174
	v = proc_pid_follow_link(dentry, nd);
175
	if (v)
176
		return v;
177
178
	/*
179
	 * Sockets can't be opened directly, which breaks
180
	 * /dev/stderr and friends. We stuff the fd in the nameidata
181
	 * here so that the open path can dup the fd after the open
182
	 * fails.
183
	 */
184
	if (S_ISSOCK(nd->inode->i_mode)) {
185
		struct task_struct *task = get_proc_task(dentry->d_inode);
186
		if (task == current) {
187
			nd->flags |= LOOKUP_DUP_FD;
188
			nd->dup_fd = proc_fd(dentry->d_inode);
189
		}
190
		put_task_struct(task);
191
	}
192
193
194
	return NULL;
195
}
196
197
static const struct inode_operations proc_pid_fd_link_inode_operations = {
198
	.readlink	= proc_pid_readlink,
199
	.follow_link	= proc_pid_fd_follow_link,
200
	.setattr	= proc_setattr,
201
};
202
170
static int
203
static int
171
proc_fd_instantiate(struct inode *dir, struct dentry *dentry,
204
proc_fd_instantiate(struct inode *dir, struct dentry *dentry,
172
		    struct task_struct *task, const void *ptr)
205
		    struct task_struct *task, const void *ptr)
Lines 183-189 proc_fd_instantiate(struct inode *dir, s Link Here
183
	ei->fd = fd;
216
	ei->fd = fd;
184
217
185
	inode->i_mode = S_IFLNK;
218
	inode->i_mode = S_IFLNK;
186
	inode->i_op = &proc_pid_link_inode_operations;
219
	inode->i_op = &proc_pid_fd_link_inode_operations;
187
	inode->i_size = 64;
220
	inode->i_size = 64;
188
221
189
	ei->op.proc_get_link = proc_fd_link;
222
	ei->op.proc_get_link = proc_fd_link;
(-)a/fs/proc/internal.h (+3 lines)
Lines 168-173 extern int pid_delete_dentry(const struc Link Here
168
extern int proc_pid_readdir(struct file *, struct dir_context *);
168
extern int proc_pid_readdir(struct file *, struct dir_context *);
169
extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int);
169
extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int);
170
extern loff_t mem_lseek(struct file *, loff_t, int);
170
extern loff_t mem_lseek(struct file *, loff_t, int);
171
extern int proc_pid_readlink(struct dentry * dentry, char __user * buffer,
172
			     int buflen);
173
extern void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd);
171
174
172
/* Lookups */
175
/* Lookups */
173
typedef int instantiate_t(struct inode *, struct dentry *,
176
typedef int instantiate_t(struct inode *, struct dentry *,
(-)a/include/linux/namei.h (+6 lines)
Lines 19-24 struct nameidata { Link Here
19
	unsigned	seq;
19
	unsigned	seq;
20
	int		last_type;
20
	int		last_type;
21
	unsigned	depth;
21
	unsigned	depth;
22
	int		dup_fd;
22
	char *saved_names[MAX_NESTED_LINKS + 1];
23
	char *saved_names[MAX_NESTED_LINKS + 1];
23
};
24
};
24
25
Lines 56-61 enum {LAST_NORM, LAST_ROOT, LAST_DOT, LA Link Here
56
#define LOOKUP_ROOT		0x2000
57
#define LOOKUP_ROOT		0x2000
57
#define LOOKUP_EMPTY		0x4000
58
#define LOOKUP_EMPTY		0x4000
58
59
60
/*
61
 * Caller should dup the fd in dup_fd rather than open a new struct file
62
 */
63
#define LOOKUP_DUP_FD		0x8000
64
59
extern int user_path_at(int, const char __user *, unsigned, struct path *);
65
extern int user_path_at(int, const char __user *, unsigned, struct path *);
60
extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
66
extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
61
67

Return to bug 728774