|
@@ -1056,16 +1056,18 @@ EXPORT_SYMBOL(install_exec_creds);
|
|
* - the caller must hold current->cred_exec_mutex to protect against
|
|
* - the caller must hold current->cred_exec_mutex to protect against
|
|
* PTRACE_ATTACH
|
|
* PTRACE_ATTACH
|
|
*/
|
|
*/
|
|
-void check_unsafe_exec(struct linux_binprm *bprm)
|
|
|
|
|
|
+int check_unsafe_exec(struct linux_binprm *bprm)
|
|
{
|
|
{
|
|
struct task_struct *p = current, *t;
|
|
struct task_struct *p = current, *t;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
unsigned n_fs, n_sighand;
|
|
unsigned n_fs, n_sighand;
|
|
|
|
+ int res = 0;
|
|
|
|
|
|
bprm->unsafe = tracehook_unsafe_exec(p);
|
|
bprm->unsafe = tracehook_unsafe_exec(p);
|
|
|
|
|
|
n_fs = 1;
|
|
n_fs = 1;
|
|
n_sighand = 1;
|
|
n_sighand = 1;
|
|
|
|
+ write_lock(&p->fs->lock);
|
|
lock_task_sighand(p, &flags);
|
|
lock_task_sighand(p, &flags);
|
|
for (t = next_thread(p); t != p; t = next_thread(t)) {
|
|
for (t = next_thread(p); t != p; t = next_thread(t)) {
|
|
if (t->fs == p->fs)
|
|
if (t->fs == p->fs)
|
|
@@ -1073,11 +1075,19 @@ void check_unsafe_exec(struct linux_binprm *bprm)
|
|
n_sighand++;
|
|
n_sighand++;
|
|
}
|
|
}
|
|
|
|
|
|
- if (atomic_read(&p->fs->count) > n_fs ||
|
|
|
|
- atomic_read(&p->sighand->count) > n_sighand)
|
|
|
|
|
|
+ if (p->fs->users > n_fs ||
|
|
|
|
+ atomic_read(&p->sighand->count) > n_sighand) {
|
|
bprm->unsafe |= LSM_UNSAFE_SHARE;
|
|
bprm->unsafe |= LSM_UNSAFE_SHARE;
|
|
|
|
+ } else {
|
|
|
|
+ if (p->fs->in_exec)
|
|
|
|
+ res = -EAGAIN;
|
|
|
|
+ p->fs->in_exec = 1;
|
|
|
|
+ }
|
|
|
|
|
|
unlock_task_sighand(p, &flags);
|
|
unlock_task_sighand(p, &flags);
|
|
|
|
+ write_unlock(&p->fs->lock);
|
|
|
|
+
|
|
|
|
+ return res;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1296,12 +1306,15 @@ int do_execve(char * filename,
|
|
bprm->cred = prepare_exec_creds();
|
|
bprm->cred = prepare_exec_creds();
|
|
if (!bprm->cred)
|
|
if (!bprm->cred)
|
|
goto out_unlock;
|
|
goto out_unlock;
|
|
- check_unsafe_exec(bprm);
|
|
|
|
|
|
+
|
|
|
|
+ retval = check_unsafe_exec(bprm);
|
|
|
|
+ if (retval)
|
|
|
|
+ goto out_unlock;
|
|
|
|
|
|
file = open_exec(filename);
|
|
file = open_exec(filename);
|
|
retval = PTR_ERR(file);
|
|
retval = PTR_ERR(file);
|
|
if (IS_ERR(file))
|
|
if (IS_ERR(file))
|
|
- goto out_unlock;
|
|
|
|
|
|
+ goto out_unmark;
|
|
|
|
|
|
sched_exec();
|
|
sched_exec();
|
|
|
|
|
|
@@ -1344,6 +1357,9 @@ int do_execve(char * filename,
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
/* execve succeeded */
|
|
/* execve succeeded */
|
|
|
|
+ write_lock(¤t->fs->lock);
|
|
|
|
+ current->fs->in_exec = 0;
|
|
|
|
+ write_unlock(¤t->fs->lock);
|
|
current->in_execve = 0;
|
|
current->in_execve = 0;
|
|
mutex_unlock(¤t->cred_exec_mutex);
|
|
mutex_unlock(¤t->cred_exec_mutex);
|
|
acct_update_integrals(current);
|
|
acct_update_integrals(current);
|
|
@@ -1362,6 +1378,11 @@ out_file:
|
|
fput(bprm->file);
|
|
fput(bprm->file);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+out_unmark:
|
|
|
|
+ write_lock(¤t->fs->lock);
|
|
|
|
+ current->fs->in_exec = 0;
|
|
|
|
+ write_unlock(¤t->fs->lock);
|
|
|
|
+
|
|
out_unlock:
|
|
out_unlock:
|
|
current->in_execve = 0;
|
|
current->in_execve = 0;
|
|
mutex_unlock(¤t->cred_exec_mutex);
|
|
mutex_unlock(¤t->cred_exec_mutex);
|