diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 103 |
1 files changed, 26 insertions, 77 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index dfa532730e55..4ede550517a6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -600,7 +600,7 @@ static int proc_fd_access_allowed(struct inode *inode) | |||
600 | return allowed; | 600 | return allowed; |
601 | } | 601 | } |
602 | 602 | ||
603 | static int proc_setattr(struct dentry *dentry, struct iattr *attr) | 603 | int proc_setattr(struct dentry *dentry, struct iattr *attr) |
604 | { | 604 | { |
605 | int error; | 605 | int error; |
606 | struct inode *inode = dentry->d_inode; | 606 | struct inode *inode = dentry->d_inode; |
@@ -894,20 +894,20 @@ static ssize_t mem_write(struct file * file, const char __user *buf, | |||
894 | if (!task) | 894 | if (!task) |
895 | goto out_no_task; | 895 | goto out_no_task; |
896 | 896 | ||
897 | copied = -ENOMEM; | ||
898 | page = (char *)__get_free_page(GFP_TEMPORARY); | ||
899 | if (!page) | ||
900 | goto out_task; | ||
901 | |||
897 | mm = check_mem_permission(task); | 902 | mm = check_mem_permission(task); |
898 | copied = PTR_ERR(mm); | 903 | copied = PTR_ERR(mm); |
899 | if (IS_ERR(mm)) | 904 | if (IS_ERR(mm)) |
900 | goto out_task; | 905 | goto out_free; |
901 | 906 | ||
902 | copied = -EIO; | 907 | copied = -EIO; |
903 | if (file->private_data != (void *)((long)current->self_exec_id)) | 908 | if (file->private_data != (void *)((long)current->self_exec_id)) |
904 | goto out_mm; | 909 | goto out_mm; |
905 | 910 | ||
906 | copied = -ENOMEM; | ||
907 | page = (char *)__get_free_page(GFP_TEMPORARY); | ||
908 | if (!page) | ||
909 | goto out_mm; | ||
910 | |||
911 | copied = 0; | 911 | copied = 0; |
912 | while (count > 0) { | 912 | while (count > 0) { |
913 | int this_len, retval; | 913 | int this_len, retval; |
@@ -929,9 +929,11 @@ static ssize_t mem_write(struct file * file, const char __user *buf, | |||
929 | count -= retval; | 929 | count -= retval; |
930 | } | 930 | } |
931 | *ppos = dst; | 931 | *ppos = dst; |
932 | free_page((unsigned long) page); | 932 | |
933 | out_mm: | 933 | out_mm: |
934 | mmput(mm); | 934 | mmput(mm); |
935 | out_free: | ||
936 | free_page((unsigned long) page); | ||
935 | out_task: | 937 | out_task: |
936 | put_task_struct(task); | 938 | put_task_struct(task); |
937 | out_no_task: | 939 | out_no_task: |
@@ -1059,7 +1061,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1059 | { | 1061 | { |
1060 | struct task_struct *task; | 1062 | struct task_struct *task; |
1061 | char buffer[PROC_NUMBUF]; | 1063 | char buffer[PROC_NUMBUF]; |
1062 | long oom_adjust; | 1064 | int oom_adjust; |
1063 | unsigned long flags; | 1065 | unsigned long flags; |
1064 | int err; | 1066 | int err; |
1065 | 1067 | ||
@@ -1071,7 +1073,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1071 | goto out; | 1073 | goto out; |
1072 | } | 1074 | } |
1073 | 1075 | ||
1074 | err = strict_strtol(strstrip(buffer), 0, &oom_adjust); | 1076 | err = kstrtoint(strstrip(buffer), 0, &oom_adjust); |
1075 | if (err) | 1077 | if (err) |
1076 | goto out; | 1078 | goto out; |
1077 | if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && | 1079 | if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && |
@@ -1168,7 +1170,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1168 | struct task_struct *task; | 1170 | struct task_struct *task; |
1169 | char buffer[PROC_NUMBUF]; | 1171 | char buffer[PROC_NUMBUF]; |
1170 | unsigned long flags; | 1172 | unsigned long flags; |
1171 | long oom_score_adj; | 1173 | int oom_score_adj; |
1172 | int err; | 1174 | int err; |
1173 | 1175 | ||
1174 | memset(buffer, 0, sizeof(buffer)); | 1176 | memset(buffer, 0, sizeof(buffer)); |
@@ -1179,7 +1181,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1179 | goto out; | 1181 | goto out; |
1180 | } | 1182 | } |
1181 | 1183 | ||
1182 | err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); | 1184 | err = kstrtoint(strstrip(buffer), 0, &oom_score_adj); |
1183 | if (err) | 1185 | if (err) |
1184 | goto out; | 1186 | goto out; |
1185 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || | 1187 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || |
@@ -1468,7 +1470,7 @@ sched_autogroup_write(struct file *file, const char __user *buf, | |||
1468 | struct inode *inode = file->f_path.dentry->d_inode; | 1470 | struct inode *inode = file->f_path.dentry->d_inode; |
1469 | struct task_struct *p; | 1471 | struct task_struct *p; |
1470 | char buffer[PROC_NUMBUF]; | 1472 | char buffer[PROC_NUMBUF]; |
1471 | long nice; | 1473 | int nice; |
1472 | int err; | 1474 | int err; |
1473 | 1475 | ||
1474 | memset(buffer, 0, sizeof(buffer)); | 1476 | memset(buffer, 0, sizeof(buffer)); |
@@ -1477,9 +1479,9 @@ sched_autogroup_write(struct file *file, const char __user *buf, | |||
1477 | if (copy_from_user(buffer, buf, count)) | 1479 | if (copy_from_user(buffer, buf, count)) |
1478 | return -EFAULT; | 1480 | return -EFAULT; |
1479 | 1481 | ||
1480 | err = strict_strtol(strstrip(buffer), 0, &nice); | 1482 | err = kstrtoint(strstrip(buffer), 0, &nice); |
1481 | if (err) | 1483 | if (err < 0) |
1482 | return -EINVAL; | 1484 | return err; |
1483 | 1485 | ||
1484 | p = get_proc_task(inode); | 1486 | p = get_proc_task(inode); |
1485 | if (!p) | 1487 | if (!p) |
@@ -1576,57 +1578,6 @@ static const struct file_operations proc_pid_set_comm_operations = { | |||
1576 | .release = single_release, | 1578 | .release = single_release, |
1577 | }; | 1579 | }; |
1578 | 1580 | ||
1579 | /* | ||
1580 | * We added or removed a vma mapping the executable. The vmas are only mapped | ||
1581 | * during exec and are not mapped with the mmap system call. | ||
1582 | * Callers must hold down_write() on the mm's mmap_sem for these | ||
1583 | */ | ||
1584 | void added_exe_file_vma(struct mm_struct *mm) | ||
1585 | { | ||
1586 | mm->num_exe_file_vmas++; | ||
1587 | } | ||
1588 | |||
1589 | void removed_exe_file_vma(struct mm_struct *mm) | ||
1590 | { | ||
1591 | mm->num_exe_file_vmas--; | ||
1592 | if ((mm->num_exe_file_vmas == 0) && mm->exe_file){ | ||
1593 | fput(mm->exe_file); | ||
1594 | mm->exe_file = NULL; | ||
1595 | } | ||
1596 | |||
1597 | } | ||
1598 | |||
1599 | void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) | ||
1600 | { | ||
1601 | if (new_exe_file) | ||
1602 | get_file(new_exe_file); | ||
1603 | if (mm->exe_file) | ||
1604 | fput(mm->exe_file); | ||
1605 | mm->exe_file = new_exe_file; | ||
1606 | mm->num_exe_file_vmas = 0; | ||
1607 | } | ||
1608 | |||
1609 | struct file *get_mm_exe_file(struct mm_struct *mm) | ||
1610 | { | ||
1611 | struct file *exe_file; | ||
1612 | |||
1613 | /* We need mmap_sem to protect against races with removal of | ||
1614 | * VM_EXECUTABLE vmas */ | ||
1615 | down_read(&mm->mmap_sem); | ||
1616 | exe_file = mm->exe_file; | ||
1617 | if (exe_file) | ||
1618 | get_file(exe_file); | ||
1619 | up_read(&mm->mmap_sem); | ||
1620 | return exe_file; | ||
1621 | } | ||
1622 | |||
1623 | void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm) | ||
1624 | { | ||
1625 | /* It's safe to write the exe_file pointer without exe_file_lock because | ||
1626 | * this is called during fork when the task is not yet in /proc */ | ||
1627 | newmm->exe_file = get_mm_exe_file(oldmm); | ||
1628 | } | ||
1629 | |||
1630 | static int proc_exe_link(struct inode *inode, struct path *exe_path) | 1581 | static int proc_exe_link(struct inode *inode, struct path *exe_path) |
1631 | { | 1582 | { |
1632 | struct task_struct *task; | 1583 | struct task_struct *task; |
@@ -1736,8 +1687,7 @@ static int task_dumpable(struct task_struct *task) | |||
1736 | return 0; | 1687 | return 0; |
1737 | } | 1688 | } |
1738 | 1689 | ||
1739 | 1690 | struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task) | |
1740 | static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task) | ||
1741 | { | 1691 | { |
1742 | struct inode * inode; | 1692 | struct inode * inode; |
1743 | struct proc_inode *ei; | 1693 | struct proc_inode *ei; |
@@ -1779,7 +1729,7 @@ out_unlock: | |||
1779 | return NULL; | 1729 | return NULL; |
1780 | } | 1730 | } |
1781 | 1731 | ||
1782 | static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 1732 | int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
1783 | { | 1733 | { |
1784 | struct inode *inode = dentry->d_inode; | 1734 | struct inode *inode = dentry->d_inode; |
1785 | struct task_struct *task; | 1735 | struct task_struct *task; |
@@ -1820,7 +1770,7 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat | |||
1820 | * made this apply to all per process world readable and executable | 1770 | * made this apply to all per process world readable and executable |
1821 | * directories. | 1771 | * directories. |
1822 | */ | 1772 | */ |
1823 | static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) | 1773 | int pid_revalidate(struct dentry *dentry, struct nameidata *nd) |
1824 | { | 1774 | { |
1825 | struct inode *inode; | 1775 | struct inode *inode; |
1826 | struct task_struct *task; | 1776 | struct task_struct *task; |
@@ -1862,7 +1812,7 @@ static int pid_delete_dentry(const struct dentry * dentry) | |||
1862 | return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; | 1812 | return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; |
1863 | } | 1813 | } |
1864 | 1814 | ||
1865 | static const struct dentry_operations pid_dentry_operations = | 1815 | const struct dentry_operations pid_dentry_operations = |
1866 | { | 1816 | { |
1867 | .d_revalidate = pid_revalidate, | 1817 | .d_revalidate = pid_revalidate, |
1868 | .d_delete = pid_delete_dentry, | 1818 | .d_delete = pid_delete_dentry, |
@@ -1870,9 +1820,6 @@ static const struct dentry_operations pid_dentry_operations = | |||
1870 | 1820 | ||
1871 | /* Lookups */ | 1821 | /* Lookups */ |
1872 | 1822 | ||
1873 | typedef struct dentry *instantiate_t(struct inode *, struct dentry *, | ||
1874 | struct task_struct *, const void *); | ||
1875 | |||
1876 | /* | 1823 | /* |
1877 | * Fill a directory entry. | 1824 | * Fill a directory entry. |
1878 | * | 1825 | * |
@@ -1885,8 +1832,8 @@ typedef struct dentry *instantiate_t(struct inode *, struct dentry *, | |||
1885 | * reported by readdir in sync with the inode numbers reported | 1832 | * reported by readdir in sync with the inode numbers reported |
1886 | * by stat. | 1833 | * by stat. |
1887 | */ | 1834 | */ |
1888 | static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 1835 | int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
1889 | char *name, int len, | 1836 | const char *name, int len, |
1890 | instantiate_t instantiate, struct task_struct *task, const void *ptr) | 1837 | instantiate_t instantiate, struct task_struct *task, const void *ptr) |
1891 | { | 1838 | { |
1892 | struct dentry *child, *dir = filp->f_path.dentry; | 1839 | struct dentry *child, *dir = filp->f_path.dentry; |
@@ -2820,6 +2767,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2820 | DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations), | 2767 | DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations), |
2821 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), | 2768 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), |
2822 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), | 2769 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), |
2770 | DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations), | ||
2823 | #ifdef CONFIG_NET | 2771 | #ifdef CONFIG_NET |
2824 | DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations), | 2772 | DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations), |
2825 | #endif | 2773 | #endif |
@@ -3168,6 +3116,7 @@ out_no_task: | |||
3168 | static const struct pid_entry tid_base_stuff[] = { | 3116 | static const struct pid_entry tid_base_stuff[] = { |
3169 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), | 3117 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), |
3170 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), | 3118 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), |
3119 | DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations), | ||
3171 | REG("environ", S_IRUSR, proc_environ_operations), | 3120 | REG("environ", S_IRUSR, proc_environ_operations), |
3172 | INF("auxv", S_IRUSR, proc_pid_auxv), | 3121 | INF("auxv", S_IRUSR, proc_pid_auxv), |
3173 | ONE("status", S_IRUGO, proc_pid_status), | 3122 | ONE("status", S_IRUGO, proc_pid_status), |