aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-03-30 07:20:30 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-03-31 23:00:26 -0400
commit498052bba55ecaff58db6a1436b0e25bfd75a7ff (patch)
treebd3644ac60737e3733995a203acebd70cfd1b21b /fs/exec.c
parent3e93cd671813e204c258f1e6c797959920cf7772 (diff)
New locking/refcounting for fs_struct
* all changes of current->fs are done under task_lock and write_lock of old fs->lock * refcount is not atomic anymore (same protection) * its decrements are done when removing reference from current; at the same time we decide whether to free it. * put_fs_struct() is gone * new field - ->in_exec. Set by check_unsafe_exec() if we are trying to do execve() and only subthreads share fs_struct. Cleared when finishing exec (success and failure alike). Makes CLONE_FS fail with -EAGAIN if set. * check_unsafe_exec() may fail with -EAGAIN if another execve() from subthread is in progress. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/fs/exec.c b/fs/exec.c
index c5128fbc9165..07a059664b73 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1056,16 +1056,18 @@ EXPORT_SYMBOL(install_exec_creds);
1056 * - the caller must hold current->cred_exec_mutex to protect against 1056 * - the caller must hold current->cred_exec_mutex to protect against
1057 * PTRACE_ATTACH 1057 * PTRACE_ATTACH
1058 */ 1058 */
1059void check_unsafe_exec(struct linux_binprm *bprm) 1059int check_unsafe_exec(struct linux_binprm *bprm)
1060{ 1060{
1061 struct task_struct *p = current, *t; 1061 struct task_struct *p = current, *t;
1062 unsigned long flags; 1062 unsigned long flags;
1063 unsigned n_fs, n_sighand; 1063 unsigned n_fs, n_sighand;
1064 int res = 0;
1064 1065
1065 bprm->unsafe = tracehook_unsafe_exec(p); 1066 bprm->unsafe = tracehook_unsafe_exec(p);
1066 1067
1067 n_fs = 1; 1068 n_fs = 1;
1068 n_sighand = 1; 1069 n_sighand = 1;
1070 write_lock(&p->fs->lock);
1069 lock_task_sighand(p, &flags); 1071 lock_task_sighand(p, &flags);
1070 for (t = next_thread(p); t != p; t = next_thread(t)) { 1072 for (t = next_thread(p); t != p; t = next_thread(t)) {
1071 if (t->fs == p->fs) 1073 if (t->fs == p->fs)
@@ -1073,11 +1075,19 @@ void check_unsafe_exec(struct linux_binprm *bprm)
1073 n_sighand++; 1075 n_sighand++;
1074 } 1076 }
1075 1077
1076 if (atomic_read(&p->fs->count) > n_fs || 1078 if (p->fs->users > n_fs ||
1077 atomic_read(&p->sighand->count) > n_sighand) 1079 atomic_read(&p->sighand->count) > n_sighand) {
1078 bprm->unsafe |= LSM_UNSAFE_SHARE; 1080 bprm->unsafe |= LSM_UNSAFE_SHARE;
1081 } else {
1082 if (p->fs->in_exec)
1083 res = -EAGAIN;
1084 p->fs->in_exec = 1;
1085 }
1079 1086
1080 unlock_task_sighand(p, &flags); 1087 unlock_task_sighand(p, &flags);
1088 write_unlock(&p->fs->lock);
1089
1090 return res;
1081} 1091}
1082 1092
1083/* 1093/*
@@ -1296,12 +1306,15 @@ int do_execve(char * filename,
1296 bprm->cred = prepare_exec_creds(); 1306 bprm->cred = prepare_exec_creds();
1297 if (!bprm->cred) 1307 if (!bprm->cred)
1298 goto out_unlock; 1308 goto out_unlock;
1299 check_unsafe_exec(bprm); 1309
1310 retval = check_unsafe_exec(bprm);
1311 if (retval)
1312 goto out_unlock;
1300 1313
1301 file = open_exec(filename); 1314 file = open_exec(filename);
1302 retval = PTR_ERR(file); 1315 retval = PTR_ERR(file);
1303 if (IS_ERR(file)) 1316 if (IS_ERR(file))
1304 goto out_unlock; 1317 goto out_unmark;
1305 1318
1306 sched_exec(); 1319 sched_exec();
1307 1320
@@ -1344,6 +1357,9 @@ int do_execve(char * filename,
1344 goto out; 1357 goto out;
1345 1358
1346 /* execve succeeded */ 1359 /* execve succeeded */
1360 write_lock(&current->fs->lock);
1361 current->fs->in_exec = 0;
1362 write_unlock(&current->fs->lock);
1347 current->in_execve = 0; 1363 current->in_execve = 0;
1348 mutex_unlock(&current->cred_exec_mutex); 1364 mutex_unlock(&current->cred_exec_mutex);
1349 acct_update_integrals(current); 1365 acct_update_integrals(current);
@@ -1362,6 +1378,11 @@ out_file:
1362 fput(bprm->file); 1378 fput(bprm->file);
1363 } 1379 }
1364 1380
1381out_unmark:
1382 write_lock(&current->fs->lock);
1383 current->fs->in_exec = 0;
1384 write_unlock(&current->fs->lock);
1385
1365out_unlock: 1386out_unlock:
1366 current->in_execve = 0; 1387 current->in_execve = 0;
1367 mutex_unlock(&current->cred_exec_mutex); 1388 mutex_unlock(&current->cred_exec_mutex);