diff options
author | KaiGai Kohei <kaigai@ak.jp.nec.com> | 2006-06-25 05:49:25 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 10:01:25 -0700 |
commit | f6ec29a42d7ac3b309a9cef179b686d23986ab98 (patch) | |
tree | 5150d4f403833ac18b468bd0e0e0a9a7cdd9f4be /kernel | |
parent | 0e4648141af02331f21aabcd34940c70f09a2d04 (diff) | |
download | op-kernel-dev-f6ec29a42d7ac3b309a9cef179b686d23986ab98.zip op-kernel-dev-f6ec29a42d7ac3b309a9cef179b686d23986ab98.tar.gz |
[PATCH] pacct: avoidance to refer the last thread as a representation of the process
When pacct facility generate an 'ac_flag' field in accounting record, it
refers a task_struct of the thread which died last in the process. But any
other task_structs are ignored.
Therefore, pacct facility drops ASU flag even if root-privilege operations are
used by any other threads except the last one. In addition, AFORK flag is
always set when the thread of group-leader didn't die last, although this
process has called execve() after fork().
We have a same matter in ac_exitcode. The recorded ac_exitcode is an exit
code of the last thread in the process. There is a possibility this exitcode
is not the group leader's one.
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/acct.c | 42 | ||||
-rw-r--r-- | kernel/exit.c | 4 |
2 files changed, 26 insertions, 20 deletions
diff --git a/kernel/acct.c b/kernel/acct.c index b352631..4c85fdf 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -75,7 +75,7 @@ int acct_parm[3] = {4, 2, 30}; /* * External references and all of the globals. */ -static void do_acct_process(long, struct file *); +static void do_acct_process(struct file *); /* * This structure is used so that all the data protected by lock @@ -196,7 +196,7 @@ static void acct_file_reopen(struct file *file) if (old_acct) { mnt_unpin(old_acct->f_vfsmnt); spin_unlock(&acct_globals.lock); - do_acct_process(0, old_acct); + do_acct_process(old_acct); filp_close(old_acct, NULL); spin_lock(&acct_globals.lock); } @@ -419,7 +419,7 @@ static u32 encode_float(u64 value) /* * do_acct_process does all actual work. Caller holds the reference to file. */ -static void do_acct_process(long exitcode, struct file *file) +static void do_acct_process(struct file *file) { struct pacct_struct *pacct = ¤t->signal->pacct; acct_t ac; @@ -496,17 +496,10 @@ static void do_acct_process(long exitcode, struct file *file) old_encode_dev(tty_devnum(current->signal->tty)) : 0; read_unlock(&tasklist_lock); - ac.ac_flag = 0; - if (current->flags & PF_FORKNOEXEC) - ac.ac_flag |= AFORK; - if (current->flags & PF_SUPERPRIV) - ac.ac_flag |= ASU; - if (current->flags & PF_DUMPCORE) - ac.ac_flag |= ACORE; - if (current->flags & PF_SIGNALED) - ac.ac_flag |= AXSIG; spin_lock(¤t->sighand->siglock); + ac.ac_flag = pacct->ac_flag; ac.ac_mem = encode_comp_t(pacct->ac_mem); + ac.ac_exitcode = pacct->ac_exitcode; spin_unlock(¤t->sighand->siglock); ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ ac.ac_rw = encode_comp_t(ac.ac_io / 1024); @@ -515,7 +508,6 @@ static void do_acct_process(long exitcode, struct file *file) ac.ac_majflt = encode_comp_t(current->signal->maj_flt + current->maj_flt); ac.ac_swaps = encode_comp_t(0); - ac.ac_exitcode = exitcode; /* * Kernel segment override to datasegment and write it @@ -544,13 +536,15 @@ void acct_init_pacct(struct pacct_struct *pacct) /** * acct_collect - collect accounting information into pacct_struct + * @exitcode: task exit code + * @group_dead: not 0, if this thread is the last one in the process. */ -void acct_collect(void) +void acct_collect(long exitcode, int group_dead) { struct pacct_struct *pacct = ¤t->signal->pacct; unsigned long vsize = 0; - if (current->mm) { + if (group_dead && current->mm) { struct vm_area_struct *vma; down_read(¤t->mm->mmap_sem); vma = current->mm->mmap; @@ -562,7 +556,19 @@ void acct_collect(void) } spin_lock(¤t->sighand->siglock); - pacct->ac_mem = vsize / 1024; + if (group_dead) + pacct->ac_mem = vsize / 1024; + if (thread_group_leader(current)) { + pacct->ac_exitcode = exitcode; + if (current->flags & PF_FORKNOEXEC) + pacct->ac_flag |= AFORK; + } + if (current->flags & PF_SUPERPRIV) + pacct->ac_flag |= ASU; + if (current->flags & PF_DUMPCORE) + pacct->ac_flag |= ACORE; + if (current->flags & PF_SIGNALED) + pacct->ac_flag |= AXSIG; spin_unlock(¤t->sighand->siglock); } @@ -572,7 +578,7 @@ void acct_collect(void) * * handles process accounting for an exiting task */ -void acct_process(long exitcode) +void acct_process() { struct file *file = NULL; @@ -591,7 +597,7 @@ void acct_process(long exitcode) get_file(file); spin_unlock(&acct_globals.lock); - do_acct_process(exitcode, file); + do_acct_process(file); fput(file); } diff --git a/kernel/exit.c b/kernel/exit.c index 819d82c..e76bd02 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -894,8 +894,8 @@ fastcall NORET_TYPE void do_exit(long code) if (group_dead) { hrtimer_cancel(&tsk->signal->real_timer); exit_itimers(tsk->signal); - acct_collect(); } + acct_collect(code, group_dead); if (unlikely(tsk->robust_list)) exit_robust_list(tsk); #if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT) @@ -907,7 +907,7 @@ fastcall NORET_TYPE void do_exit(long code) exit_mm(tsk); if (group_dead) - acct_process(code); + acct_process(); exit_sem(tsk); __exit_files(tsk); __exit_fs(tsk); |