How do I access the auxiliary info vector in CheriBSD?¶
What is the auxiliary information vector (auxvec) for? What information does it contain? On Unix systems like CheriBSD, the auxiliary vector (auxvec) passes runtime metadata from the kernel to the process when it starts up.
Running man auxv
on a CheriBSD shell will give you some details
about fields in the auxiliary vector, but this information is not
exhaustive!
For more detail, we need to look at relevant OS header files.
How do we access the auxvec?¶
The simplest way is to use the getauxval
routine
from <sys/auxv.h>
as a key/value query function
but some fields can’t be
accessed like this; they seem to be zeroed out.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/auxv.h> // for elf_aux_info
#include <errno.h> // for errno
#include <string.h> // for strerror
#include <elf.h> // for elfinfo
int main(void) {
int ncpus;
int result;
// AT_NCPUS is FreeBSD-specific and gives the number of CPUs available
result = elf_aux_info(AT_NCPUS, &ncpus, sizeof(ncpus));
if (result != 0) {
printf(stderr, "elf_aux_info failed: %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Number of CPUs: %d\n", ncpus);
return EXIT_SUCCESS;
}
Use the __auxvec global variable¶
Alternatively, we can make use of the
__auxvec
global variable directly.
Note the code below Works with clang-morello running natively on CheriBSD, but it doesn’t work with a cross-compiler.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/auxv.h> // for elf_aux_info
#include <errno.h> // for errno
#include <string.h> // for strerror
#include <elf.h> // for elfinfo
extern void *__auxargs;
int main(void) {
printf("Aux pointer: %#p\n", (void *)__auxargs);
for (Elf_Auxinfo *auxp = __auxargs; auxp->a_type != AT_NULL; auxp++) {
if (auxp->a_type == AT_ARGV) {
printf("argv is %#p\n", (char **)auxp->a_un.a_ptr);
} else if (auxp->a_type == AT_ARGC) {
printf("argc is %d\n", (int)auxp->a_un.a_val);
} else if (auxp->a_type == AT_ENTRY) {
printf("entry is %#p\n", (void *)auxp->a_un.a_ptr);
} else if (auxp->a_type == AT_PHDR) {
printf("phdr is %#p\n", (void *)auxp->a_un.a_ptr);
}
}
return EXIT_SUCCESS;
}
Use case¶
The PHDR value is a useful capability for scanning ELF .data sections for root set pointers, in a garbage collection.