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.c119
1 files changed, 88 insertions, 31 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 8e4addaa5424..f3d02ca461ec 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -226,7 +226,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
226{ 226{
227 struct mm_struct *mm; 227 struct mm_struct *mm;
228 228
229 if (mutex_lock_killable(&task->cred_guard_mutex)) 229 if (mutex_lock_killable(&task->signal->cred_guard_mutex))
230 return NULL; 230 return NULL;
231 231
232 mm = get_task_mm(task); 232 mm = get_task_mm(task);
@@ -235,7 +235,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
235 mmput(mm); 235 mmput(mm);
236 mm = NULL; 236 mm = NULL;
237 } 237 }
238 mutex_unlock(&task->cred_guard_mutex); 238 mutex_unlock(&task->signal->cred_guard_mutex);
239 239
240 return mm; 240 return mm;
241} 241}
@@ -771,6 +771,8 @@ static const struct file_operations proc_single_file_operations = {
771static int mem_open(struct inode* inode, struct file* file) 771static int mem_open(struct inode* inode, struct file* file)
772{ 772{
773 file->private_data = (void*)((long)current->self_exec_id); 773 file->private_data = (void*)((long)current->self_exec_id);
774 /* OK to pass negative loff_t, we can catch out-of-range */
775 file->f_mode |= FMODE_UNSIGNED_OFFSET;
774 return 0; 776 return 0;
775} 777}
776 778
@@ -1023,28 +1025,47 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
1023 memset(buffer, 0, sizeof(buffer)); 1025 memset(buffer, 0, sizeof(buffer));
1024 if (count > sizeof(buffer) - 1) 1026 if (count > sizeof(buffer) - 1)
1025 count = sizeof(buffer) - 1; 1027 count = sizeof(buffer) - 1;
1026 if (copy_from_user(buffer, buf, count)) 1028 if (copy_from_user(buffer, buf, count)) {
1027 return -EFAULT; 1029 err = -EFAULT;
1030 goto out;
1031 }
1028 1032
1029 err = strict_strtol(strstrip(buffer), 0, &oom_adjust); 1033 err = strict_strtol(strstrip(buffer), 0, &oom_adjust);
1030 if (err) 1034 if (err)
1031 return -EINVAL; 1035 goto out;
1032 if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && 1036 if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) &&
1033 oom_adjust != OOM_DISABLE) 1037 oom_adjust != OOM_DISABLE) {
1034 return -EINVAL; 1038 err = -EINVAL;
1039 goto out;
1040 }
1035 1041
1036 task = get_proc_task(file->f_path.dentry->d_inode); 1042 task = get_proc_task(file->f_path.dentry->d_inode);
1037 if (!task) 1043 if (!task) {
1038 return -ESRCH; 1044 err = -ESRCH;
1045 goto out;
1046 }
1047
1048 task_lock(task);
1049 if (!task->mm) {
1050 err = -EINVAL;
1051 goto err_task_lock;
1052 }
1053
1039 if (!lock_task_sighand(task, &flags)) { 1054 if (!lock_task_sighand(task, &flags)) {
1040 put_task_struct(task); 1055 err = -ESRCH;
1041 return -ESRCH; 1056 goto err_task_lock;
1042 } 1057 }
1043 1058
1044 if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) { 1059 if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) {
1045 unlock_task_sighand(task, &flags); 1060 err = -EACCES;
1046 put_task_struct(task); 1061 goto err_sighand;
1047 return -EACCES; 1062 }
1063
1064 if (oom_adjust != task->signal->oom_adj) {
1065 if (oom_adjust == OOM_DISABLE)
1066 atomic_inc(&task->mm->oom_disable_count);
1067 if (task->signal->oom_adj == OOM_DISABLE)
1068 atomic_dec(&task->mm->oom_disable_count);
1048 } 1069 }
1049 1070
1050 /* 1071 /*
@@ -1065,10 +1086,13 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
1065 else 1086 else
1066 task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / 1087 task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) /
1067 -OOM_DISABLE; 1088 -OOM_DISABLE;
1089err_sighand:
1068 unlock_task_sighand(task, &flags); 1090 unlock_task_sighand(task, &flags);
1091err_task_lock:
1092 task_unlock(task);
1069 put_task_struct(task); 1093 put_task_struct(task);
1070 1094out:
1071 return count; 1095 return err < 0 ? err : count;
1072} 1096}
1073 1097
1074static const struct file_operations proc_oom_adjust_operations = { 1098static const struct file_operations proc_oom_adjust_operations = {
@@ -1109,30 +1133,49 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
1109 memset(buffer, 0, sizeof(buffer)); 1133 memset(buffer, 0, sizeof(buffer));
1110 if (count > sizeof(buffer) - 1) 1134 if (count > sizeof(buffer) - 1)
1111 count = sizeof(buffer) - 1; 1135 count = sizeof(buffer) - 1;
1112 if (copy_from_user(buffer, buf, count)) 1136 if (copy_from_user(buffer, buf, count)) {
1113 return -EFAULT; 1137 err = -EFAULT;
1138 goto out;
1139 }
1114 1140
1115 err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); 1141 err = strict_strtol(strstrip(buffer), 0, &oom_score_adj);
1116 if (err) 1142 if (err)
1117 return -EINVAL; 1143 goto out;
1118 if (oom_score_adj < OOM_SCORE_ADJ_MIN || 1144 if (oom_score_adj < OOM_SCORE_ADJ_MIN ||
1119 oom_score_adj > OOM_SCORE_ADJ_MAX) 1145 oom_score_adj > OOM_SCORE_ADJ_MAX) {
1120 return -EINVAL; 1146 err = -EINVAL;
1147 goto out;
1148 }
1121 1149
1122 task = get_proc_task(file->f_path.dentry->d_inode); 1150 task = get_proc_task(file->f_path.dentry->d_inode);
1123 if (!task) 1151 if (!task) {
1124 return -ESRCH; 1152 err = -ESRCH;
1153 goto out;
1154 }
1155
1156 task_lock(task);
1157 if (!task->mm) {
1158 err = -EINVAL;
1159 goto err_task_lock;
1160 }
1161
1125 if (!lock_task_sighand(task, &flags)) { 1162 if (!lock_task_sighand(task, &flags)) {
1126 put_task_struct(task); 1163 err = -ESRCH;
1127 return -ESRCH; 1164 goto err_task_lock;
1128 } 1165 }
1166
1129 if (oom_score_adj < task->signal->oom_score_adj && 1167 if (oom_score_adj < task->signal->oom_score_adj &&
1130 !capable(CAP_SYS_RESOURCE)) { 1168 !capable(CAP_SYS_RESOURCE)) {
1131 unlock_task_sighand(task, &flags); 1169 err = -EACCES;
1132 put_task_struct(task); 1170 goto err_sighand;
1133 return -EACCES;
1134 } 1171 }
1135 1172
1173 if (oom_score_adj != task->signal->oom_score_adj) {
1174 if (oom_score_adj == OOM_SCORE_ADJ_MIN)
1175 atomic_inc(&task->mm->oom_disable_count);
1176 if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
1177 atomic_dec(&task->mm->oom_disable_count);
1178 }
1136 task->signal->oom_score_adj = oom_score_adj; 1179 task->signal->oom_score_adj = oom_score_adj;
1137 /* 1180 /*
1138 * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is 1181 * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is
@@ -1143,14 +1186,19 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
1143 else 1186 else
1144 task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / 1187 task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) /
1145 OOM_SCORE_ADJ_MAX; 1188 OOM_SCORE_ADJ_MAX;
1189err_sighand:
1146 unlock_task_sighand(task, &flags); 1190 unlock_task_sighand(task, &flags);
1191err_task_lock:
1192 task_unlock(task);
1147 put_task_struct(task); 1193 put_task_struct(task);
1148 return count; 1194out:
1195 return err < 0 ? err : count;
1149} 1196}
1150 1197
1151static const struct file_operations proc_oom_score_adj_operations = { 1198static const struct file_operations proc_oom_score_adj_operations = {
1152 .read = oom_score_adj_read, 1199 .read = oom_score_adj_read,
1153 .write = oom_score_adj_write, 1200 .write = oom_score_adj_write,
1201 .llseek = default_llseek,
1154}; 1202};
1155 1203
1156#ifdef CONFIG_AUDITSYSCALL 1204#ifdef CONFIG_AUDITSYSCALL
@@ -1600,6 +1648,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
1600 1648
1601 /* Common stuff */ 1649 /* Common stuff */
1602 ei = PROC_I(inode); 1650 ei = PROC_I(inode);
1651 inode->i_ino = get_next_ino();
1603 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 1652 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1604 inode->i_op = &proc_def_inode_operations; 1653 inode->i_op = &proc_def_inode_operations;
1605 1654
@@ -2039,11 +2088,13 @@ static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
2039static const struct file_operations proc_fdinfo_file_operations = { 2088static const struct file_operations proc_fdinfo_file_operations = {
2040 .open = nonseekable_open, 2089 .open = nonseekable_open,
2041 .read = proc_fdinfo_read, 2090 .read = proc_fdinfo_read,
2091 .llseek = no_llseek,
2042}; 2092};
2043 2093
2044static const struct file_operations proc_fd_operations = { 2094static const struct file_operations proc_fd_operations = {
2045 .read = generic_read_dir, 2095 .read = generic_read_dir,
2046 .readdir = proc_readfd, 2096 .readdir = proc_readfd,
2097 .llseek = default_llseek,
2047}; 2098};
2048 2099
2049/* 2100/*
@@ -2112,6 +2163,7 @@ static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
2112static const struct file_operations proc_fdinfo_operations = { 2163static const struct file_operations proc_fdinfo_operations = {
2113 .read = generic_read_dir, 2164 .read = generic_read_dir,
2114 .readdir = proc_readfdinfo, 2165 .readdir = proc_readfdinfo,
2166 .llseek = default_llseek,
2115}; 2167};
2116 2168
2117/* 2169/*
@@ -2302,14 +2354,14 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
2302 goto out_free; 2354 goto out_free;
2303 2355
2304 /* Guard against adverse ptrace interaction */ 2356 /* Guard against adverse ptrace interaction */
2305 length = mutex_lock_interruptible(&task->cred_guard_mutex); 2357 length = mutex_lock_interruptible(&task->signal->cred_guard_mutex);
2306 if (length < 0) 2358 if (length < 0)
2307 goto out_free; 2359 goto out_free;
2308 2360
2309 length = security_setprocattr(task, 2361 length = security_setprocattr(task,
2310 (char*)file->f_path.dentry->d_name.name, 2362 (char*)file->f_path.dentry->d_name.name,
2311 (void*)page, count); 2363 (void*)page, count);
2312 mutex_unlock(&task->cred_guard_mutex); 2364 mutex_unlock(&task->signal->cred_guard_mutex);
2313out_free: 2365out_free:
2314 free_page((unsigned long) page); 2366 free_page((unsigned long) page);
2315out: 2367out:
@@ -2343,6 +2395,7 @@ static int proc_attr_dir_readdir(struct file * filp,
2343static const struct file_operations proc_attr_dir_operations = { 2395static const struct file_operations proc_attr_dir_operations = {
2344 .read = generic_read_dir, 2396 .read = generic_read_dir,
2345 .readdir = proc_attr_dir_readdir, 2397 .readdir = proc_attr_dir_readdir,
2398 .llseek = default_llseek,
2346}; 2399};
2347 2400
2348static struct dentry *proc_attr_dir_lookup(struct inode *dir, 2401static struct dentry *proc_attr_dir_lookup(struct inode *dir,
@@ -2542,6 +2595,7 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
2542 2595
2543 /* Initialize the inode */ 2596 /* Initialize the inode */
2544 ei = PROC_I(inode); 2597 ei = PROC_I(inode);
2598 inode->i_ino = get_next_ino();
2545 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 2599 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
2546 2600
2547 /* 2601 /*
@@ -2751,6 +2805,7 @@ static int proc_tgid_base_readdir(struct file * filp,
2751static const struct file_operations proc_tgid_base_operations = { 2805static const struct file_operations proc_tgid_base_operations = {
2752 .read = generic_read_dir, 2806 .read = generic_read_dir,
2753 .readdir = proc_tgid_base_readdir, 2807 .readdir = proc_tgid_base_readdir,
2808 .llseek = default_llseek,
2754}; 2809};
2755 2810
2756static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ 2811static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
@@ -3088,6 +3143,7 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den
3088static const struct file_operations proc_tid_base_operations = { 3143static const struct file_operations proc_tid_base_operations = {
3089 .read = generic_read_dir, 3144 .read = generic_read_dir,
3090 .readdir = proc_tid_base_readdir, 3145 .readdir = proc_tid_base_readdir,
3146 .llseek = default_llseek,
3091}; 3147};
3092 3148
3093static const struct inode_operations proc_tid_base_inode_operations = { 3149static const struct inode_operations proc_tid_base_inode_operations = {
@@ -3324,4 +3380,5 @@ static const struct inode_operations proc_task_inode_operations = {
3324static const struct file_operations proc_task_operations = { 3380static const struct file_operations proc_task_operations = {
3325 .read = generic_read_dir, 3381 .read = generic_read_dir,
3326 .readdir = proc_task_readdir, 3382 .readdir = proc_task_readdir,
3383 .llseek = default_llseek,
3327}; 3384};