aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/Kconfig4
-rw-r--r--fs/proc/base.c111
-rw-r--r--fs/proc/proc_sysctl.c1
-rw-r--r--fs/proc/root.c1
-rw-r--r--fs/proc/task_mmu.c1
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
35config PROC_VMCORE 35config 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;
1087err_sighand:
1068 unlock_task_sighand(task, &flags); 1088 unlock_task_sighand(task, &flags);
1089err_task_lock:
1090 task_unlock(task);
1069 put_task_struct(task); 1091 put_task_struct(task);
1070 1092out:
1071 return count; 1093 return err < 0 ? err : count;
1072} 1094}
1073 1095
1074static const struct file_operations proc_oom_adjust_operations = { 1096static 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;
1187err_sighand:
1146 unlock_task_sighand(task, &flags); 1188 unlock_task_sighand(task, &flags);
1189err_task_lock:
1190 task_unlock(task);
1147 put_task_struct(task); 1191 put_task_struct(task);
1148 return count; 1192out:
1193 return err < 0 ? err : count;
1149} 1194}
1150 1195
1151static const struct file_operations proc_oom_score_adj_operations = { 1196static 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,
2039static const struct file_operations proc_fdinfo_file_operations = { 2085static 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
2044static const struct file_operations proc_fd_operations = { 2091static 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)
2112static const struct file_operations proc_fdinfo_operations = { 2160static 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,
2343static const struct file_operations proc_attr_dir_operations = { 2392static 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
2348static struct dentry *proc_attr_dir_lookup(struct inode *dir, 2398static 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,
2751static const struct file_operations proc_tgid_base_operations = { 2801static 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
2756static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ 2807static 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
3088static const struct file_operations proc_tid_base_operations = { 3139static 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
3093static const struct inode_operations proc_tid_base_inode_operations = { 3145static const struct inode_operations proc_tid_base_inode_operations = {
@@ -3324,4 +3376,5 @@ static const struct inode_operations proc_task_inode_operations = {
3324static const struct file_operations proc_task_operations = { 3376static 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
364static const struct file_operations proc_sys_file_operations = { 364static 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
369static const struct file_operations proc_sys_dir_file_operations = { 370static 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,
179static const struct file_operations proc_root_operations = { 179static 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
540const struct file_operations proc_clear_refs_operations = { 540const 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
544struct pagemapread { 545struct pagemapread {