Commit f6ec29a4 authored by KaiGai Kohei's avatar KaiGai Kohei Committed by Linus Torvalds

[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.
parent 0e464814
...@@ -122,16 +122,16 @@ struct super_block; ...@@ -122,16 +122,16 @@ struct super_block;
extern void acct_auto_close_mnt(struct vfsmount *m); extern void acct_auto_close_mnt(struct vfsmount *m);
extern void acct_auto_close(struct super_block *sb); extern void acct_auto_close(struct super_block *sb);
extern void acct_init_pacct(struct pacct_struct *pacct); extern void acct_init_pacct(struct pacct_struct *pacct);
extern void acct_collect(); extern void acct_collect(long exitcode, int group_dead);
extern void acct_process(long exitcode); extern void acct_process(void);
extern void acct_update_integrals(struct task_struct *tsk); extern void acct_update_integrals(struct task_struct *tsk);
extern void acct_clear_integrals(struct task_struct *tsk); extern void acct_clear_integrals(struct task_struct *tsk);
#else #else
#define acct_auto_close_mnt(x) do { } while (0) #define acct_auto_close_mnt(x) do { } while (0)
#define acct_auto_close(x) do { } while (0) #define acct_auto_close(x) do { } while (0)
#define acct_init_pacct(x) do { } while (0) #define acct_init_pacct(x) do { } while (0)
#define acct_collect() do { } while (0) #define acct_collect(x,y) do { } while (0)
#define acct_process(x) do { } while (0) #define acct_process() do { } while (0)
#define acct_update_integrals(x) do { } while (0) #define acct_update_integrals(x) do { } while (0)
#define acct_clear_integrals(task) do { } while (0) #define acct_clear_integrals(task) do { } while (0)
#endif #endif
......
...@@ -359,6 +359,8 @@ struct sighand_struct { ...@@ -359,6 +359,8 @@ struct sighand_struct {
}; };
struct pacct_struct { struct pacct_struct {
int ac_flag;
long ac_exitcode;
unsigned long ac_mem; unsigned long ac_mem;
}; };
......
...@@ -75,7 +75,7 @@ int acct_parm[3] = {4, 2, 30}; ...@@ -75,7 +75,7 @@ int acct_parm[3] = {4, 2, 30};
/* /*
* External references and all of the globals. * 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 * 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,7 +196,7 @@ static void acct_file_reopen(struct file *file)
if (old_acct) { if (old_acct) {
mnt_unpin(old_acct->f_vfsmnt); mnt_unpin(old_acct->f_vfsmnt);
spin_unlock(&acct_globals.lock); spin_unlock(&acct_globals.lock);
do_acct_process(0, old_acct); do_acct_process(old_acct);
filp_close(old_acct, NULL); filp_close(old_acct, NULL);
spin_lock(&acct_globals.lock); spin_lock(&acct_globals.lock);
} }
...@@ -419,7 +419,7 @@ static u32 encode_float(u64 value) ...@@ -419,7 +419,7 @@ static u32 encode_float(u64 value)
/* /*
* do_acct_process does all actual work. Caller holds the reference to file. * 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 = &current->signal->pacct; struct pacct_struct *pacct = &current->signal->pacct;
acct_t ac; acct_t ac;
...@@ -496,17 +496,10 @@ static void do_acct_process(long exitcode, struct file *file) ...@@ -496,17 +496,10 @@ static void do_acct_process(long exitcode, struct file *file)
old_encode_dev(tty_devnum(current->signal->tty)) : 0; old_encode_dev(tty_devnum(current->signal->tty)) : 0;
read_unlock(&tasklist_lock); 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(&current->sighand->siglock); spin_lock(&current->sighand->siglock);
ac.ac_flag = pacct->ac_flag;
ac.ac_mem = encode_comp_t(pacct->ac_mem); ac.ac_mem = encode_comp_t(pacct->ac_mem);
ac.ac_exitcode = pacct->ac_exitcode;
spin_unlock(&current->sighand->siglock); spin_unlock(&current->sighand->siglock);
ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */ ac.ac_io = encode_comp_t(0 /* current->io_usage */); /* %% */
ac.ac_rw = encode_comp_t(ac.ac_io / 1024); 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,7 +508,6 @@ static void do_acct_process(long exitcode, struct file *file)
ac.ac_majflt = encode_comp_t(current->signal->maj_flt + ac.ac_majflt = encode_comp_t(current->signal->maj_flt +
current->maj_flt); current->maj_flt);
ac.ac_swaps = encode_comp_t(0); ac.ac_swaps = encode_comp_t(0);
ac.ac_exitcode = exitcode;
/* /*
* Kernel segment override to datasegment and write it * Kernel segment override to datasegment and write it
...@@ -544,13 +536,15 @@ void acct_init_pacct(struct pacct_struct *pacct) ...@@ -544,13 +536,15 @@ void acct_init_pacct(struct pacct_struct *pacct)
/** /**
* acct_collect - collect accounting information into pacct_struct * 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 = &current->signal->pacct; struct pacct_struct *pacct = &current->signal->pacct;
unsigned long vsize = 0; unsigned long vsize = 0;
if (current->mm) { if (group_dead && current->mm) {
struct vm_area_struct *vma; struct vm_area_struct *vma;
down_read(&current->mm->mmap_sem); down_read(&current->mm->mmap_sem);
vma = current->mm->mmap; vma = current->mm->mmap;
...@@ -562,7 +556,19 @@ void acct_collect(void) ...@@ -562,7 +556,19 @@ void acct_collect(void)
} }
spin_lock(&current->sighand->siglock); spin_lock(&current->sighand->siglock);
if (group_dead)
pacct->ac_mem = vsize / 1024; 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(&current->sighand->siglock); spin_unlock(&current->sighand->siglock);
} }
...@@ -572,7 +578,7 @@ void acct_collect(void) ...@@ -572,7 +578,7 @@ void acct_collect(void)
* *
* handles process accounting for an exiting task * handles process accounting for an exiting task
*/ */
void acct_process(long exitcode) void acct_process()
{ {
struct file *file = NULL; struct file *file = NULL;
...@@ -591,7 +597,7 @@ void acct_process(long exitcode) ...@@ -591,7 +597,7 @@ void acct_process(long exitcode)
get_file(file); get_file(file);
spin_unlock(&acct_globals.lock); spin_unlock(&acct_globals.lock);
do_acct_process(exitcode, file); do_acct_process(file);
fput(file); fput(file);
} }
......
...@@ -894,8 +894,8 @@ fastcall NORET_TYPE void do_exit(long code) ...@@ -894,8 +894,8 @@ fastcall NORET_TYPE void do_exit(long code)
if (group_dead) { if (group_dead) {
hrtimer_cancel(&tsk->signal->real_timer); hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal); exit_itimers(tsk->signal);
acct_collect();
} }
acct_collect(code, group_dead);
if (unlikely(tsk->robust_list)) if (unlikely(tsk->robust_list))
exit_robust_list(tsk); exit_robust_list(tsk);
#if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT) #if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT)
...@@ -907,7 +907,7 @@ fastcall NORET_TYPE void do_exit(long code) ...@@ -907,7 +907,7 @@ fastcall NORET_TYPE void do_exit(long code)
exit_mm(tsk); exit_mm(tsk);
if (group_dead) if (group_dead)
acct_process(code); acct_process();
exit_sem(tsk); exit_sem(tsk);
__exit_files(tsk); __exit_files(tsk);
__exit_fs(tsk); __exit_fs(tsk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment