diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-03-30 07:20:30 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-03-31 23:00:26 -0400 |
commit | 498052bba55ecaff58db6a1436b0e25bfd75a7ff (patch) | |
tree | bd3644ac60737e3733995a203acebd70cfd1b21b /fs/compat.c | |
parent | 3e93cd671813e204c258f1e6c797959920cf7772 (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/compat.c')
-rw-r--r-- | fs/compat.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/fs/compat.c b/fs/compat.c index 55efdfebdf5a..baabf203b847 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/poll.h> | 51 | #include <linux/poll.h> |
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/eventpoll.h> | 53 | #include <linux/eventpoll.h> |
54 | #include <linux/fs_struct.h> | ||
54 | 55 | ||
55 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
56 | #include <asm/mmu_context.h> | 57 | #include <asm/mmu_context.h> |
@@ -1441,12 +1442,15 @@ int compat_do_execve(char * filename, | |||
1441 | bprm->cred = prepare_exec_creds(); | 1442 | bprm->cred = prepare_exec_creds(); |
1442 | if (!bprm->cred) | 1443 | if (!bprm->cred) |
1443 | goto out_unlock; | 1444 | goto out_unlock; |
1444 | check_unsafe_exec(bprm); | 1445 | |
1446 | retval = check_unsafe_exec(bprm); | ||
1447 | if (retval) | ||
1448 | goto out_unlock; | ||
1445 | 1449 | ||
1446 | file = open_exec(filename); | 1450 | file = open_exec(filename); |
1447 | retval = PTR_ERR(file); | 1451 | retval = PTR_ERR(file); |
1448 | if (IS_ERR(file)) | 1452 | if (IS_ERR(file)) |
1449 | goto out_unlock; | 1453 | goto out_unmark; |
1450 | 1454 | ||
1451 | sched_exec(); | 1455 | sched_exec(); |
1452 | 1456 | ||
@@ -1488,6 +1492,9 @@ int compat_do_execve(char * filename, | |||
1488 | goto out; | 1492 | goto out; |
1489 | 1493 | ||
1490 | /* execve succeeded */ | 1494 | /* execve succeeded */ |
1495 | write_lock(¤t->fs->lock); | ||
1496 | current->fs->in_exec = 0; | ||
1497 | write_unlock(¤t->fs->lock); | ||
1491 | current->in_execve = 0; | 1498 | current->in_execve = 0; |
1492 | mutex_unlock(¤t->cred_exec_mutex); | 1499 | mutex_unlock(¤t->cred_exec_mutex); |
1493 | acct_update_integrals(current); | 1500 | acct_update_integrals(current); |
@@ -1506,6 +1513,11 @@ out_file: | |||
1506 | fput(bprm->file); | 1513 | fput(bprm->file); |
1507 | } | 1514 | } |
1508 | 1515 | ||
1516 | out_unmark: | ||
1517 | write_lock(¤t->fs->lock); | ||
1518 | current->fs->in_exec = 0; | ||
1519 | write_unlock(¤t->fs->lock); | ||
1520 | |||
1509 | out_unlock: | 1521 | out_unlock: |
1510 | current->in_execve = 0; | 1522 | current->in_execve = 0; |
1511 | mutex_unlock(¤t->cred_exec_mutex); | 1523 | mutex_unlock(¤t->cred_exec_mutex); |