Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -122,16 +122,16 @@ struct super_block;
extern void acct_auto_close_mnt(struct vfsmount *m);
extern void acct_auto_close(struct super_block *sb);
extern void acct_init_pacct(struct pacct_struct *pacct);
extern void acct_collect();
extern void acct_process(long exitcode);
extern void acct_collect(long exitcode, int group_dead);
extern void acct_process(void);
extern void acct_update_integrals(struct task_struct *tsk);
extern void acct_clear_integrals(struct task_struct *tsk);
#else
#define acct_auto_close_mnt(x)	do { } while (0)
#define acct_auto_close(x)	do { } while (0)
#define acct_init_pacct(x)	do { } while (0)
#define acct_collect()		do { } while (0)
#define acct_process(x)		do { } while (0)
#define acct_collect(x,y)	do { } while (0)
#define acct_process()		do { } while (0)
#define acct_update_integrals(x)		do { } while (0)
#define acct_clear_integrals(task)	do { } while (0)
#endif
+2 −0
Original line number Diff line number Diff line
@@ -359,6 +359,8 @@ struct sighand_struct {
};

struct pacct_struct {
	int			ac_flag;
	long			ac_exitcode;
	unsigned long		ac_mem;
};

+24 −18
Original line number Diff line number Diff line
@@ -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 = &current->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(&current->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(&current->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 = &current->signal->pacct;
	unsigned long vsize = 0;

	if (current->mm) {
	if (group_dead && current->mm) {
		struct vm_area_struct *vma;
		down_read(&current->mm->mmap_sem);
		vma = current->mm->mmap;
@@ -562,7 +556,19 @@ void acct_collect(void)
	}

	spin_lock(&current->sighand->siglock);
	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(&current->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);
}

+2 −2
Original line number Diff line number Diff line
@@ -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);