aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaiGai Kohei <kaigai@ak.jp.nec.com>2006-06-25 08:49:25 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 13:01:25 -0400
commitf6ec29a42d7ac3b309a9cef179b686d23986ab98 (patch)
tree5150d4f403833ac18b468bd0e0e0a9a7cdd9f4be
parent0e4648141af02331f21aabcd34940c70f09a2d04 (diff)
[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.
-rw-r--r--include/linux/acct.h8
-rw-r--r--include/linux/sched.h2
-rw-r--r--kernel/acct.c42
-rw-r--r--kernel/exit.c4
4 files changed, 32 insertions, 24 deletions
diff --git a/include/linux/acct.h b/include/linux/acct.h
index 5bca9b3ef2d7..e86bae7324d2 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -122,16 +122,16 @@ struct super_block;
122extern void acct_auto_close_mnt(struct vfsmount *m); 122extern void acct_auto_close_mnt(struct vfsmount *m);
123extern void acct_auto_close(struct super_block *sb); 123extern void acct_auto_close(struct super_block *sb);
124extern void acct_init_pacct(struct pacct_struct *pacct); 124extern void acct_init_pacct(struct pacct_struct *pacct);
125extern void acct_collect(); 125extern void acct_collect(long exitcode, int group_dead);
126extern void acct_process(long exitcode); 126extern void acct_process(void);
127extern void acct_update_integrals(struct task_struct *tsk); 127extern void acct_update_integrals(struct task_struct *tsk);
128extern void acct_clear_integrals(struct task_struct *tsk); 128extern void acct_clear_integrals(struct task_struct *tsk);
129#else 129#else
130#define acct_auto_close_mnt(x) do { } while (0) 130#define acct_auto_close_mnt(x) do { } while (0)
131#define acct_auto_close(x) do { } while (0) 131#define acct_auto_close(x) do { } while (0)
132#define acct_init_pacct(x) do { } while (0) 132#define acct_init_pacct(x) do { } while (0)
133#define acct_collect() do { } while (0) 133#define acct_collect(x,y) do { } while (0)
134#define acct_process(x) do { } while (0) 134#define acct_process() do { } while (0)
135#define acct_update_integrals(x) do { } while (0) 135#define acct_update_integrals(x) do { } while (0)
136#define acct_clear_integrals(task) do { } while (0) 136#define acct_clear_integrals(task) do { } while (0)
137#endif 137#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index abada7c1d5e4..d8429dc250f0 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -359,6 +359,8 @@ struct sighand_struct {
359}; 359};
360 360
361struct pacct_struct { 361struct pacct_struct {
362 int ac_flag;
363 long ac_exitcode;
362 unsigned long ac_mem; 364 unsigned long ac_mem;
363}; 365};
364 366
diff --git a/kernel/acct.c b/kernel/acct.c
index b35263137824..4c85fdf615da 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -75,7 +75,7 @@ int acct_parm[3] = {4, 2, 30};
75/* 75/*
76 * External references and all of the globals. 76 * External references and all of the globals.
77 */ 77 */
78static void do_acct_process(long, struct file *); 78static void do_acct_process(struct file *);
79 79
80/* 80/*
81 * This structure is used so that all the data protected by lock 81 * This structure is used so that all the data protected by lock
@@ -196,7 +196,7 @@ static void acct_file_reopen(struct file *file)
196 if (old_acct) { 196 if (old_acct) {
197 mnt_unpin(old_acct->f_vfsmnt); 197 mnt_unpin(old_acct->f_vfsmnt);
198 spin_unlock(&acct_globals.lock); 198 spin_unlock(&acct_globals.lock);
199 do_acct_process(0, old_acct); 199 do_acct_process(old_acct);
200 filp_close(old_acct, NULL); 200 filp_close(old_acct, NULL);
201 spin_lock(&acct_globals.lock); 201 spin_lock(&acct_globals.lock);
202 } 202 }
@@ -419,7 +419,7 @@ static u32 encode_float(u64 value)
419/* 419/*
420 * do_acct_process does all actual work. Caller holds the reference to file. 420 * do_acct_process does all actual work. Caller holds the reference to file.
421 */ 421 */
422static void do_acct_process(long exitcode, struct file *file) 422static void do_acct_process(struct file *file)
423{ 423{
424 struct pacct_struct *pacct = &current->signal->pacct; 424 struct pacct_struct *pacct = &current->signal->pacct;
425 acct_t ac; 425 acct_t ac;
@@ -496,17 +496,10 @@ static void do_acct_process(long exitcode, struct file *file)
496 old_encode_dev(tty_devnum(current->signal->tty)) : 0; 496 old_encode_dev(tty_devnum(current->signal->tty)) : 0;
497 read_unlock(&tasklist_lock); 497 read_unlock(&tasklist_lock);
498 498
499 ac.ac_flag = 0;
500 if (current->flags & PF_FORKNOEXEC)
501 ac.ac_flag |= AFORK;
502 if (current->flags & PF_SUPERPRIV)
503 ac.ac_flag |= ASU;
504 if (current->flags & PF_DUMPCORE)
505 ac.ac_flag |= ACORE;
506 if (current->flags & PF_SIGNALED)
507 ac.ac_flag |= AXSIG;
508 spin_lock(&current->sighand->siglock); 499 spin_lock(&current->sighand->siglock);
500 ac.ac_flag = pacct->ac_flag;
509 ac.ac_mem = encode_comp_t(pacct->ac_mem); 501 ac.ac_mem = encode_comp_t(pacct->ac_mem);
502 ac.ac_exitcode = pacct->ac_exitcode;
510 spin_unlock(&current->sighand->siglock); 503 spin_unlock(&current->sighand->siglock);
511 ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ 504 ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */
512 ac.ac_rw = encode_comp_t(ac.ac_io / 1024); 505 ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
@@ -515,7 +508,6 @@ static void do_acct_process(long exitcode, struct file *file)
515 ac.ac_majflt = encode_comp_t(current->signal->maj_flt + 508 ac.ac_majflt = encode_comp_t(current->signal->maj_flt +
516 current->maj_flt); 509 current->maj_flt);
517 ac.ac_swaps = encode_comp_t(0); 510 ac.ac_swaps = encode_comp_t(0);
518 ac.ac_exitcode = exitcode;
519 511
520 /* 512 /*
521 * Kernel segment override to datasegment and write it 513 * Kernel segment override to datasegment and write it
@@ -544,13 +536,15 @@ void acct_init_pacct(struct pacct_struct *pacct)
544 536
545/** 537/**
546 * acct_collect - collect accounting information into pacct_struct 538 * acct_collect - collect accounting information into pacct_struct
539 * @exitcode: task exit code
540 * @group_dead: not 0, if this thread is the last one in the process.
547 */ 541 */
548void acct_collect(void) 542void acct_collect(long exitcode, int group_dead)
549{ 543{
550 struct pacct_struct *pacct = &current->signal->pacct; 544 struct pacct_struct *pacct = &current->signal->pacct;
551 unsigned long vsize = 0; 545 unsigned long vsize = 0;
552 546
553 if (current->mm) { 547 if (group_dead && current->mm) {
554 struct vm_area_struct *vma; 548 struct vm_area_struct *vma;
555 down_read(&current->mm->mmap_sem); 549 down_read(&current->mm->mmap_sem);
556 vma = current->mm->mmap; 550 vma = current->mm->mmap;
@@ -562,7 +556,19 @@ void acct_collect(void)
562 } 556 }
563 557
564 spin_lock(&current->sighand->siglock); 558 spin_lock(&current->sighand->siglock);
565 pacct->ac_mem = vsize / 1024; 559 if (group_dead)
560 pacct->ac_mem = vsize / 1024;
561 if (thread_group_leader(current)) {
562 pacct->ac_exitcode = exitcode;
563 if (current->flags & PF_FORKNOEXEC)
564 pacct->ac_flag |= AFORK;
565 }
566 if (current->flags & PF_SUPERPRIV)
567 pacct->ac_flag |= ASU;
568 if (current->flags & PF_DUMPCORE)
569 pacct->ac_flag |= ACORE;
570 if (current->flags & PF_SIGNALED)
571 pacct->ac_flag |= AXSIG;
566 spin_unlock(&current->sighand->siglock); 572 spin_unlock(&current->sighand->siglock);
567} 573}
568 574
@@ -572,7 +578,7 @@ void acct_collect(void)
572 * 578 *
573 * handles process accounting for an exiting task 579 * handles process accounting for an exiting task
574 */ 580 */
575void acct_process(long exitcode) 581void acct_process()
576{ 582{
577 struct file *file = NULL; 583 struct file *file = NULL;
578 584
@@ -591,7 +597,7 @@ void acct_process(long exitcode)
591 get_file(file); 597 get_file(file);
592 spin_unlock(&acct_globals.lock); 598 spin_unlock(&acct_globals.lock);
593 599
594 do_acct_process(exitcode, file); 600 do_acct_process(file);
595 fput(file); 601 fput(file);
596} 602}
597 603
diff --git a/kernel/exit.c b/kernel/exit.c
index 819d82c2efba..e76bd02e930e 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -894,8 +894,8 @@ fastcall NORET_TYPE void do_exit(long code)
894 if (group_dead) { 894 if (group_dead) {
895 hrtimer_cancel(&tsk->signal->real_timer); 895 hrtimer_cancel(&tsk->signal->real_timer);
896 exit_itimers(tsk->signal); 896 exit_itimers(tsk->signal);
897 acct_collect();
898 } 897 }
898 acct_collect(code, group_dead);
899 if (unlikely(tsk->robust_list)) 899 if (unlikely(tsk->robust_list))
900 exit_robust_list(tsk); 900 exit_robust_list(tsk);
901#if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT) 901#if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT)
@@ -907,7 +907,7 @@ fastcall NORET_TYPE void do_exit(long code)
907 exit_mm(tsk); 907 exit_mm(tsk);
908 908
909 if (group_dead) 909 if (group_dead)
910 acct_process(code); 910 acct_process();
911 exit_sem(tsk); 911 exit_sem(tsk);
912 __exit_files(tsk); 912 __exit_files(tsk);
913 __exit_fs(tsk); 913 __exit_fs(tsk);