diff options
author | KaiGai Kohei <kaigai@ak.jp.nec.com> | 2006-06-25 08:49:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:01:25 -0400 |
commit | f6ec29a42d7ac3b309a9cef179b686d23986ab98 (patch) | |
tree | 5150d4f403833ac18b468bd0e0e0a9a7cdd9f4be | |
parent | 0e4648141af02331f21aabcd34940c70f09a2d04 (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.h | 8 | ||||
-rw-r--r-- | include/linux/sched.h | 2 | ||||
-rw-r--r-- | kernel/acct.c | 42 | ||||
-rw-r--r-- | kernel/exit.c | 4 |
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; | |||
122 | extern void acct_auto_close_mnt(struct vfsmount *m); | 122 | extern void acct_auto_close_mnt(struct vfsmount *m); |
123 | extern void acct_auto_close(struct super_block *sb); | 123 | extern void acct_auto_close(struct super_block *sb); |
124 | extern void acct_init_pacct(struct pacct_struct *pacct); | 124 | extern void acct_init_pacct(struct pacct_struct *pacct); |
125 | extern void acct_collect(); | 125 | extern void acct_collect(long exitcode, int group_dead); |
126 | extern void acct_process(long exitcode); | 126 | extern void acct_process(void); |
127 | extern void acct_update_integrals(struct task_struct *tsk); | 127 | extern void acct_update_integrals(struct task_struct *tsk); |
128 | extern void acct_clear_integrals(struct task_struct *tsk); | 128 | extern 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 | ||
361 | struct pacct_struct { | 361 | struct 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 | */ |
78 | static void do_acct_process(long, struct file *); | 78 | static 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 | */ |
422 | static void do_acct_process(long exitcode, struct file *file) | 422 | static void do_acct_process(struct file *file) |
423 | { | 423 | { |
424 | struct pacct_struct *pacct = ¤t->signal->pacct; | 424 | struct pacct_struct *pacct = ¤t->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(¤t->sighand->siglock); | 499 | spin_lock(¤t->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(¤t->sighand->siglock); | 503 | spin_unlock(¤t->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 | */ |
548 | void acct_collect(void) | 542 | void acct_collect(long exitcode, int group_dead) |
549 | { | 543 | { |
550 | struct pacct_struct *pacct = ¤t->signal->pacct; | 544 | struct pacct_struct *pacct = ¤t->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(¤t->mm->mmap_sem); | 549 | down_read(¤t->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(¤t->sighand->siglock); | 558 | spin_lock(¤t->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(¤t->sighand->siglock); | 572 | spin_unlock(¤t->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 | */ |
575 | void acct_process(long exitcode) | 581 | void 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); |