[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.
This commit is contained in:
parent
0e4648141a
commit
f6ec29a42d
4 changed files with 32 additions and 24 deletions
|
@ -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 {
|
||||||
};
|
};
|
||||||
|
|
||||||
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};
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
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)
|
||||||
/*
|
/*
|
||||||
* 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 = ¤t->signal->pacct;
|
struct pacct_struct *pacct = ¤t->signal->pacct;
|
||||||
acct_t ac;
|
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;
|
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(¤t->sighand->siglock);
|
spin_lock(¤t->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(¤t->sighand->siglock);
|
spin_unlock(¤t->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)
|
||||||
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)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 = ¤t->signal->pacct;
|
struct pacct_struct *pacct = ¤t->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(¤t->mm->mmap_sem);
|
down_read(¤t->mm->mmap_sem);
|
||||||
vma = current->mm->mmap;
|
vma = current->mm->mmap;
|
||||||
|
@ -562,7 +556,19 @@ void acct_collect(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(¤t->sighand->siglock);
|
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);
|
spin_unlock(¤t->sighand->siglock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue