xorl %eax, %eax

OpenBSD ELF Auxiliary Vector Information Leak

leave a comment »

On the ChangeLog of OpenBSD 6.0 release there was this interesting low impact vulnerability. The susceptible code is part of sys/kern/exec_elf.c file and specifically in exec_elf_fixup() function. You can see the exact code snippet below.

/*
 * Phase II of load. It is now safe to load the interpreter. Info collected
 * when loading the program is available for setup of the interpreter.
 */
int
exec_elf_fixup(struct proc *p, struct exec_package *epp)
{
	char	*interp;
	int	error = 0;
	struct	elf_args *ap;
	AuxInfo ai[ELF_AUX_ENTRIES], *a;
    ...
	/*
	 * Push extra arguments on the stack needed by dynamically
	 * linked binaries
	 */
	if (error == 0) {
		a = ai;

		a->au_id = AUX_phdr;
		a->au_v = ap->arg_phaddr;
		a++;

		a->au_id = AUX_phent;
		a->au_v = ap->arg_phentsize;
		a++;

		a->au_id = AUX_phnum;
		a->au_v = ap->arg_phnum;
		a++;

		a->au_id = AUX_pagesz;
		a->au_v = PAGE_SIZE;
		a++;

		a->au_id = AUX_base;
		a->au_v = ap->arg_interp;
		a++;

		a->au_id = AUX_flags;
		a->au_v = 0;
		a++;

		a->au_id = AUX_entry;
		a->au_v = ap->arg_entry;
		a++;

		a->au_id = AUX_null;
		a->au_v = 0;
		a++;

		error = copyout(ai, epp->ep_emul_argp, sizeof ai);
	}
    ...
}

It is important to have a basic understanding of ELF auxiliary vectors to understand this vulnerability. ELF auxiliary vectors are used to copy specific information from the kernel to the user-space. Those are dynamic information such as system call entry points (in memory), and this is what the above code does via “ai” structure. It initializes it and then uses copyout() to copy it back to the user-space. You can see the AuxInfo structure as defined in sys/sys/exec_elf.h header file below (for 32-bit architectures).

#define AuxInfo		Aux32Info
   ...
typedef struct {
	Elf32_Sword	au_id;				/* 32-bit id */
	Elf32_Word	au_v;				/* 32-bit value */
} Aux32Info;

The problem with the initialization code in exec_elf_fixup() was that it was not zeroed out before the copy to the user-space. This means that if “ai” is not exactly the same size as the ELF auxiliary vectors to be copied to the user-space, it will result in passing kernel memory through this structure to the user-space. This information leak vulnerability was resolved by making sure that the entire “ai” structure is zeroed out before starting the initialization. You can see the patch below.

 	 * linked binaries
 	 */
 	if (error == 0) {
+		memset(&ai, 0, sizeof ai);
 		a = ai;

Written by xorl

November 22, 2017 at 22:58

Posted in vulnerabilities

Leave a comment