aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r--fs/proc/base.c108
1 files changed, 65 insertions, 43 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 54e270262979..29fd7ef97be9 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -400,23 +400,6 @@ static const struct file_operations proc_pid_cmdline_ops = {
400 .llseek = generic_file_llseek, 400 .llseek = generic_file_llseek,
401}; 401};
402 402
403static int proc_pid_auxv(struct seq_file *m, struct pid_namespace *ns,
404 struct pid *pid, struct task_struct *task)
405{
406 struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
407 if (mm && !IS_ERR(mm)) {
408 unsigned int nwords = 0;
409 do {
410 nwords += 2;
411 } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
412 seq_write(m, mm->saved_auxv, nwords * sizeof(mm->saved_auxv[0]));
413 mmput(mm);
414 return 0;
415 } else
416 return PTR_ERR(mm);
417}
418
419
420#ifdef CONFIG_KALLSYMS 403#ifdef CONFIG_KALLSYMS
421/* 404/*
422 * Provides a wchan file via kallsyms in a proper one-value-per-file format. 405 * Provides a wchan file via kallsyms in a proper one-value-per-file format.
@@ -483,7 +466,7 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
483 save_stack_trace_tsk(task, &trace); 466 save_stack_trace_tsk(task, &trace);
484 467
485 for (i = 0; i < trace.nr_entries; i++) { 468 for (i = 0; i < trace.nr_entries; i++) {
486 seq_printf(m, "[<%pK>] %pS\n", 469 seq_printf(m, "[<%pK>] %pB\n",
487 (void *)entries[i], (void *)entries[i]); 470 (void *)entries[i], (void *)entries[i]);
488 } 471 }
489 unlock_trace(task); 472 unlock_trace(task);
@@ -709,7 +692,7 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
709 if (attr->ia_valid & ATTR_MODE) 692 if (attr->ia_valid & ATTR_MODE)
710 return -EPERM; 693 return -EPERM;
711 694
712 error = inode_change_ok(inode, attr); 695 error = setattr_prepare(dentry, attr);
713 if (error) 696 if (error)
714 return error; 697 return error;
715 698
@@ -1014,6 +997,30 @@ static const struct file_operations proc_environ_operations = {
1014 .release = mem_release, 997 .release = mem_release,
1015}; 998};
1016 999
1000static int auxv_open(struct inode *inode, struct file *file)
1001{
1002 return __mem_open(inode, file, PTRACE_MODE_READ_FSCREDS);
1003}
1004
1005static ssize_t auxv_read(struct file *file, char __user *buf,
1006 size_t count, loff_t *ppos)
1007{
1008 struct mm_struct *mm = file->private_data;
1009 unsigned int nwords = 0;
1010 do {
1011 nwords += 2;
1012 } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
1013 return simple_read_from_buffer(buf, count, ppos, mm->saved_auxv,
1014 nwords * sizeof(mm->saved_auxv[0]));
1015}
1016
1017static const struct file_operations proc_auxv_operations = {
1018 .open = auxv_open,
1019 .read = auxv_read,
1020 .llseek = generic_file_llseek,
1021 .release = mem_release,
1022};
1023
1017static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count, 1024static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
1018 loff_t *ppos) 1025 loff_t *ppos)
1019{ 1026{
@@ -1556,18 +1563,13 @@ static const struct file_operations proc_pid_set_comm_operations = {
1556static int proc_exe_link(struct dentry *dentry, struct path *exe_path) 1563static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
1557{ 1564{
1558 struct task_struct *task; 1565 struct task_struct *task;
1559 struct mm_struct *mm;
1560 struct file *exe_file; 1566 struct file *exe_file;
1561 1567
1562 task = get_proc_task(d_inode(dentry)); 1568 task = get_proc_task(d_inode(dentry));
1563 if (!task) 1569 if (!task)
1564 return -ENOENT; 1570 return -ENOENT;
1565 mm = get_task_mm(task); 1571 exe_file = get_task_exe_file(task);
1566 put_task_struct(task); 1572 put_task_struct(task);
1567 if (!mm)
1568 return -ENOENT;
1569 exe_file = get_mm_exe_file(mm);
1570 mmput(mm);
1571 if (exe_file) { 1573 if (exe_file) {
1572 *exe_path = exe_file->f_path; 1574 *exe_path = exe_file->f_path;
1573 path_get(&exe_file->f_path); 1575 path_get(&exe_file->f_path);
@@ -2285,16 +2287,27 @@ static ssize_t timerslack_ns_write(struct file *file, const char __user *buf,
2285 if (!p) 2287 if (!p)
2286 return -ESRCH; 2288 return -ESRCH;
2287 2289
2288 if (ptrace_may_access(p, PTRACE_MODE_ATTACH_FSCREDS)) { 2290 if (p != current) {
2289 task_lock(p); 2291 if (!capable(CAP_SYS_NICE)) {
2290 if (slack_ns == 0) 2292 count = -EPERM;
2291 p->timer_slack_ns = p->default_timer_slack_ns; 2293 goto out;
2292 else 2294 }
2293 p->timer_slack_ns = slack_ns; 2295
2294 task_unlock(p); 2296 err = security_task_setscheduler(p);
2295 } else 2297 if (err) {
2296 count = -EPERM; 2298 count = err;
2299 goto out;
2300 }
2301 }
2302
2303 task_lock(p);
2304 if (slack_ns == 0)
2305 p->timer_slack_ns = p->default_timer_slack_ns;
2306 else
2307 p->timer_slack_ns = slack_ns;
2308 task_unlock(p);
2297 2309
2310out:
2298 put_task_struct(p); 2311 put_task_struct(p);
2299 2312
2300 return count; 2313 return count;
@@ -2304,19 +2317,28 @@ static int timerslack_ns_show(struct seq_file *m, void *v)
2304{ 2317{
2305 struct inode *inode = m->private; 2318 struct inode *inode = m->private;
2306 struct task_struct *p; 2319 struct task_struct *p;
2307 int err = 0; 2320 int err = 0;
2308 2321
2309 p = get_proc_task(inode); 2322 p = get_proc_task(inode);
2310 if (!p) 2323 if (!p)
2311 return -ESRCH; 2324 return -ESRCH;
2312 2325
2313 if (ptrace_may_access(p, PTRACE_MODE_ATTACH_FSCREDS)) { 2326 if (p != current) {
2314 task_lock(p);
2315 seq_printf(m, "%llu\n", p->timer_slack_ns);
2316 task_unlock(p);
2317 } else
2318 err = -EPERM;
2319 2327
2328 if (!capable(CAP_SYS_NICE)) {
2329 err = -EPERM;
2330 goto out;
2331 }
2332 err = security_task_getscheduler(p);
2333 if (err)
2334 goto out;
2335 }
2336
2337 task_lock(p);
2338 seq_printf(m, "%llu\n", p->timer_slack_ns);
2339 task_unlock(p);
2340
2341out:
2320 put_task_struct(p); 2342 put_task_struct(p);
2321 2343
2322 return err; 2344 return err;
@@ -2827,7 +2849,7 @@ static const struct pid_entry tgid_base_stuff[] = {
2827 DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations), 2849 DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
2828#endif 2850#endif
2829 REG("environ", S_IRUSR, proc_environ_operations), 2851 REG("environ", S_IRUSR, proc_environ_operations),
2830 ONE("auxv", S_IRUSR, proc_pid_auxv), 2852 REG("auxv", S_IRUSR, proc_auxv_operations),
2831 ONE("status", S_IRUGO, proc_pid_status), 2853 ONE("status", S_IRUGO, proc_pid_status),
2832 ONE("personality", S_IRUSR, proc_pid_personality), 2854 ONE("personality", S_IRUSR, proc_pid_personality),
2833 ONE("limits", S_IRUGO, proc_pid_limits), 2855 ONE("limits", S_IRUGO, proc_pid_limits),
@@ -3215,7 +3237,7 @@ static const struct pid_entry tid_base_stuff[] = {
3215 DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations), 3237 DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
3216#endif 3238#endif
3217 REG("environ", S_IRUSR, proc_environ_operations), 3239 REG("environ", S_IRUSR, proc_environ_operations),
3218 ONE("auxv", S_IRUSR, proc_pid_auxv), 3240 REG("auxv", S_IRUSR, proc_auxv_operations),
3219 ONE("status", S_IRUGO, proc_pid_status), 3241 ONE("status", S_IRUGO, proc_pid_status),
3220 ONE("personality", S_IRUSR, proc_pid_personality), 3242 ONE("personality", S_IRUSR, proc_pid_personality),
3221 ONE("limits", S_IRUGO, proc_pid_limits), 3243 ONE("limits", S_IRUGO, proc_pid_limits),