diff options
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/Kconfig | 4 | ||||
-rw-r--r-- | fs/proc/base.c | 111 | ||||
-rw-r--r-- | fs/proc/proc_sysctl.c | 1 | ||||
-rw-r--r-- | fs/proc/root.c | 1 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 1 |
5 files changed, 87 insertions, 31 deletions
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig index 50f8f0600f06..6a0068841d96 100644 --- a/fs/proc/Kconfig +++ b/fs/proc/Kconfig | |||
@@ -33,8 +33,8 @@ config PROC_KCORE | |||
33 | depends on PROC_FS && MMU | 33 | depends on PROC_FS && MMU |
34 | 34 | ||
35 | config PROC_VMCORE | 35 | config PROC_VMCORE |
36 | bool "/proc/vmcore support (EXPERIMENTAL)" | 36 | bool "/proc/vmcore support" |
37 | depends on PROC_FS && CRASH_DUMP | 37 | depends on PROC_FS && CRASH_DUMP |
38 | default y | 38 | default y |
39 | help | 39 | help |
40 | Exports the dump image of crashed kernel in ELF format. | 40 | Exports the dump image of crashed kernel in ELF format. |
diff --git a/fs/proc/base.c b/fs/proc/base.c index a1c43e7c8a7b..53dc8ad40ae6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1023,28 +1023,47 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1023 | memset(buffer, 0, sizeof(buffer)); | 1023 | memset(buffer, 0, sizeof(buffer)); |
1024 | if (count > sizeof(buffer) - 1) | 1024 | if (count > sizeof(buffer) - 1) |
1025 | count = sizeof(buffer) - 1; | 1025 | count = sizeof(buffer) - 1; |
1026 | if (copy_from_user(buffer, buf, count)) | 1026 | if (copy_from_user(buffer, buf, count)) { |
1027 | return -EFAULT; | 1027 | err = -EFAULT; |
1028 | goto out; | ||
1029 | } | ||
1028 | 1030 | ||
1029 | err = strict_strtol(strstrip(buffer), 0, &oom_adjust); | 1031 | err = strict_strtol(strstrip(buffer), 0, &oom_adjust); |
1030 | if (err) | 1032 | if (err) |
1031 | return -EINVAL; | 1033 | goto out; |
1032 | if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && | 1034 | if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && |
1033 | oom_adjust != OOM_DISABLE) | 1035 | oom_adjust != OOM_DISABLE) { |
1034 | return -EINVAL; | 1036 | err = -EINVAL; |
1037 | goto out; | ||
1038 | } | ||
1035 | 1039 | ||
1036 | task = get_proc_task(file->f_path.dentry->d_inode); | 1040 | task = get_proc_task(file->f_path.dentry->d_inode); |
1037 | if (!task) | 1041 | if (!task) { |
1038 | return -ESRCH; | 1042 | err = -ESRCH; |
1043 | goto out; | ||
1044 | } | ||
1045 | |||
1046 | task_lock(task); | ||
1047 | if (!task->mm) { | ||
1048 | err = -EINVAL; | ||
1049 | goto err_task_lock; | ||
1050 | } | ||
1051 | |||
1039 | if (!lock_task_sighand(task, &flags)) { | 1052 | if (!lock_task_sighand(task, &flags)) { |
1040 | put_task_struct(task); | 1053 | err = -ESRCH; |
1041 | return -ESRCH; | 1054 | goto err_task_lock; |
1042 | } | 1055 | } |
1043 | 1056 | ||
1044 | if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) { | 1057 | if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) { |
1045 | unlock_task_sighand(task, &flags); | 1058 | err = -EACCES; |
1046 | put_task_struct(task); | 1059 | goto err_sighand; |
1047 | return -EACCES; | 1060 | } |
1061 | |||
1062 | if (oom_adjust != task->signal->oom_adj) { | ||
1063 | if (oom_adjust == OOM_DISABLE) | ||
1064 | atomic_inc(&task->mm->oom_disable_count); | ||
1065 | if (task->signal->oom_adj == OOM_DISABLE) | ||
1066 | atomic_dec(&task->mm->oom_disable_count); | ||
1048 | } | 1067 | } |
1049 | 1068 | ||
1050 | /* | 1069 | /* |
@@ -1065,10 +1084,13 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1065 | else | 1084 | else |
1066 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / | 1085 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / |
1067 | -OOM_DISABLE; | 1086 | -OOM_DISABLE; |
1087 | err_sighand: | ||
1068 | unlock_task_sighand(task, &flags); | 1088 | unlock_task_sighand(task, &flags); |
1089 | err_task_lock: | ||
1090 | task_unlock(task); | ||
1069 | put_task_struct(task); | 1091 | put_task_struct(task); |
1070 | 1092 | out: | |
1071 | return count; | 1093 | return err < 0 ? err : count; |
1072 | } | 1094 | } |
1073 | 1095 | ||
1074 | static const struct file_operations proc_oom_adjust_operations = { | 1096 | static const struct file_operations proc_oom_adjust_operations = { |
@@ -1109,30 +1131,49 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1109 | memset(buffer, 0, sizeof(buffer)); | 1131 | memset(buffer, 0, sizeof(buffer)); |
1110 | if (count > sizeof(buffer) - 1) | 1132 | if (count > sizeof(buffer) - 1) |
1111 | count = sizeof(buffer) - 1; | 1133 | count = sizeof(buffer) - 1; |
1112 | if (copy_from_user(buffer, buf, count)) | 1134 | if (copy_from_user(buffer, buf, count)) { |
1113 | return -EFAULT; | 1135 | err = -EFAULT; |
1136 | goto out; | ||
1137 | } | ||
1114 | 1138 | ||
1115 | err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); | 1139 | err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); |
1116 | if (err) | 1140 | if (err) |
1117 | return -EINVAL; | 1141 | goto out; |
1118 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || | 1142 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || |
1119 | oom_score_adj > OOM_SCORE_ADJ_MAX) | 1143 | oom_score_adj > OOM_SCORE_ADJ_MAX) { |
1120 | return -EINVAL; | 1144 | err = -EINVAL; |
1145 | goto out; | ||
1146 | } | ||
1121 | 1147 | ||
1122 | task = get_proc_task(file->f_path.dentry->d_inode); | 1148 | task = get_proc_task(file->f_path.dentry->d_inode); |
1123 | if (!task) | 1149 | if (!task) { |
1124 | return -ESRCH; | 1150 | err = -ESRCH; |
1151 | goto out; | ||
1152 | } | ||
1153 | |||
1154 | task_lock(task); | ||
1155 | if (!task->mm) { | ||
1156 | err = -EINVAL; | ||
1157 | goto err_task_lock; | ||
1158 | } | ||
1159 | |||
1125 | if (!lock_task_sighand(task, &flags)) { | 1160 | if (!lock_task_sighand(task, &flags)) { |
1126 | put_task_struct(task); | 1161 | err = -ESRCH; |
1127 | return -ESRCH; | 1162 | goto err_task_lock; |
1128 | } | 1163 | } |
1164 | |||
1129 | if (oom_score_adj < task->signal->oom_score_adj && | 1165 | if (oom_score_adj < task->signal->oom_score_adj && |
1130 | !capable(CAP_SYS_RESOURCE)) { | 1166 | !capable(CAP_SYS_RESOURCE)) { |
1131 | unlock_task_sighand(task, &flags); | 1167 | err = -EACCES; |
1132 | put_task_struct(task); | 1168 | goto err_sighand; |
1133 | return -EACCES; | ||
1134 | } | 1169 | } |
1135 | 1170 | ||
1171 | if (oom_score_adj != task->signal->oom_score_adj) { | ||
1172 | if (oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
1173 | atomic_inc(&task->mm->oom_disable_count); | ||
1174 | if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
1175 | atomic_dec(&task->mm->oom_disable_count); | ||
1176 | } | ||
1136 | task->signal->oom_score_adj = oom_score_adj; | 1177 | task->signal->oom_score_adj = oom_score_adj; |
1137 | /* | 1178 | /* |
1138 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is | 1179 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is |
@@ -1143,14 +1184,19 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1143 | else | 1184 | else |
1144 | task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / | 1185 | task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / |
1145 | OOM_SCORE_ADJ_MAX; | 1186 | OOM_SCORE_ADJ_MAX; |
1187 | err_sighand: | ||
1146 | unlock_task_sighand(task, &flags); | 1188 | unlock_task_sighand(task, &flags); |
1189 | err_task_lock: | ||
1190 | task_unlock(task); | ||
1147 | put_task_struct(task); | 1191 | put_task_struct(task); |
1148 | return count; | 1192 | out: |
1193 | return err < 0 ? err : count; | ||
1149 | } | 1194 | } |
1150 | 1195 | ||
1151 | static const struct file_operations proc_oom_score_adj_operations = { | 1196 | static const struct file_operations proc_oom_score_adj_operations = { |
1152 | .read = oom_score_adj_read, | 1197 | .read = oom_score_adj_read, |
1153 | .write = oom_score_adj_write, | 1198 | .write = oom_score_adj_write, |
1199 | .llseek = default_llseek, | ||
1154 | }; | 1200 | }; |
1155 | 1201 | ||
1156 | #ifdef CONFIG_AUDITSYSCALL | 1202 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2039,11 +2085,13 @@ static ssize_t proc_fdinfo_read(struct file *file, char __user *buf, | |||
2039 | static const struct file_operations proc_fdinfo_file_operations = { | 2085 | static const struct file_operations proc_fdinfo_file_operations = { |
2040 | .open = nonseekable_open, | 2086 | .open = nonseekable_open, |
2041 | .read = proc_fdinfo_read, | 2087 | .read = proc_fdinfo_read, |
2088 | .llseek = no_llseek, | ||
2042 | }; | 2089 | }; |
2043 | 2090 | ||
2044 | static const struct file_operations proc_fd_operations = { | 2091 | static const struct file_operations proc_fd_operations = { |
2045 | .read = generic_read_dir, | 2092 | .read = generic_read_dir, |
2046 | .readdir = proc_readfd, | 2093 | .readdir = proc_readfd, |
2094 | .llseek = default_llseek, | ||
2047 | }; | 2095 | }; |
2048 | 2096 | ||
2049 | /* | 2097 | /* |
@@ -2112,6 +2160,7 @@ static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir) | |||
2112 | static const struct file_operations proc_fdinfo_operations = { | 2160 | static const struct file_operations proc_fdinfo_operations = { |
2113 | .read = generic_read_dir, | 2161 | .read = generic_read_dir, |
2114 | .readdir = proc_readfdinfo, | 2162 | .readdir = proc_readfdinfo, |
2163 | .llseek = default_llseek, | ||
2115 | }; | 2164 | }; |
2116 | 2165 | ||
2117 | /* | 2166 | /* |
@@ -2343,6 +2392,7 @@ static int proc_attr_dir_readdir(struct file * filp, | |||
2343 | static const struct file_operations proc_attr_dir_operations = { | 2392 | static const struct file_operations proc_attr_dir_operations = { |
2344 | .read = generic_read_dir, | 2393 | .read = generic_read_dir, |
2345 | .readdir = proc_attr_dir_readdir, | 2394 | .readdir = proc_attr_dir_readdir, |
2395 | .llseek = default_llseek, | ||
2346 | }; | 2396 | }; |
2347 | 2397 | ||
2348 | static struct dentry *proc_attr_dir_lookup(struct inode *dir, | 2398 | static struct dentry *proc_attr_dir_lookup(struct inode *dir, |
@@ -2675,7 +2725,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2675 | INF("auxv", S_IRUSR, proc_pid_auxv), | 2725 | INF("auxv", S_IRUSR, proc_pid_auxv), |
2676 | ONE("status", S_IRUGO, proc_pid_status), | 2726 | ONE("status", S_IRUGO, proc_pid_status), |
2677 | ONE("personality", S_IRUSR, proc_pid_personality), | 2727 | ONE("personality", S_IRUSR, proc_pid_personality), |
2678 | INF("limits", S_IRUSR, proc_pid_limits), | 2728 | INF("limits", S_IRUGO, proc_pid_limits), |
2679 | #ifdef CONFIG_SCHED_DEBUG | 2729 | #ifdef CONFIG_SCHED_DEBUG |
2680 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), | 2730 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
2681 | #endif | 2731 | #endif |
@@ -2751,6 +2801,7 @@ static int proc_tgid_base_readdir(struct file * filp, | |||
2751 | static const struct file_operations proc_tgid_base_operations = { | 2801 | static const struct file_operations proc_tgid_base_operations = { |
2752 | .read = generic_read_dir, | 2802 | .read = generic_read_dir, |
2753 | .readdir = proc_tgid_base_readdir, | 2803 | .readdir = proc_tgid_base_readdir, |
2804 | .llseek = default_llseek, | ||
2754 | }; | 2805 | }; |
2755 | 2806 | ||
2756 | static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ | 2807 | static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ |
@@ -3011,7 +3062,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
3011 | INF("auxv", S_IRUSR, proc_pid_auxv), | 3062 | INF("auxv", S_IRUSR, proc_pid_auxv), |
3012 | ONE("status", S_IRUGO, proc_pid_status), | 3063 | ONE("status", S_IRUGO, proc_pid_status), |
3013 | ONE("personality", S_IRUSR, proc_pid_personality), | 3064 | ONE("personality", S_IRUSR, proc_pid_personality), |
3014 | INF("limits", S_IRUSR, proc_pid_limits), | 3065 | INF("limits", S_IRUGO, proc_pid_limits), |
3015 | #ifdef CONFIG_SCHED_DEBUG | 3066 | #ifdef CONFIG_SCHED_DEBUG |
3016 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), | 3067 | REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), |
3017 | #endif | 3068 | #endif |
@@ -3088,6 +3139,7 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den | |||
3088 | static const struct file_operations proc_tid_base_operations = { | 3139 | static const struct file_operations proc_tid_base_operations = { |
3089 | .read = generic_read_dir, | 3140 | .read = generic_read_dir, |
3090 | .readdir = proc_tid_base_readdir, | 3141 | .readdir = proc_tid_base_readdir, |
3142 | .llseek = default_llseek, | ||
3091 | }; | 3143 | }; |
3092 | 3144 | ||
3093 | static const struct inode_operations proc_tid_base_inode_operations = { | 3145 | static const struct inode_operations proc_tid_base_inode_operations = { |
@@ -3324,4 +3376,5 @@ static const struct inode_operations proc_task_inode_operations = { | |||
3324 | static const struct file_operations proc_task_operations = { | 3376 | static const struct file_operations proc_task_operations = { |
3325 | .read = generic_read_dir, | 3377 | .read = generic_read_dir, |
3326 | .readdir = proc_task_readdir, | 3378 | .readdir = proc_task_readdir, |
3379 | .llseek = default_llseek, | ||
3327 | }; | 3380 | }; |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 5be436ea088e..2fc52552271d 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -364,6 +364,7 @@ static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct | |||
364 | static const struct file_operations proc_sys_file_operations = { | 364 | static const struct file_operations proc_sys_file_operations = { |
365 | .read = proc_sys_read, | 365 | .read = proc_sys_read, |
366 | .write = proc_sys_write, | 366 | .write = proc_sys_write, |
367 | .llseek = default_llseek, | ||
367 | }; | 368 | }; |
368 | 369 | ||
369 | static const struct file_operations proc_sys_dir_file_operations = { | 370 | static const struct file_operations proc_sys_dir_file_operations = { |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 4258384ed22d..93d99b316325 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -179,6 +179,7 @@ static int proc_root_readdir(struct file * filp, | |||
179 | static const struct file_operations proc_root_operations = { | 179 | static const struct file_operations proc_root_operations = { |
180 | .read = generic_read_dir, | 180 | .read = generic_read_dir, |
181 | .readdir = proc_root_readdir, | 181 | .readdir = proc_root_readdir, |
182 | .llseek = default_llseek, | ||
182 | }; | 183 | }; |
183 | 184 | ||
184 | /* | 185 | /* |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 1dbca4e8cc16..871e25ed0069 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -539,6 +539,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, | |||
539 | 539 | ||
540 | const struct file_operations proc_clear_refs_operations = { | 540 | const struct file_operations proc_clear_refs_operations = { |
541 | .write = clear_refs_write, | 541 | .write = clear_refs_write, |
542 | .llseek = noop_llseek, | ||
542 | }; | 543 | }; |
543 | 544 | ||
544 | struct pagemapread { | 545 | struct pagemapread { |