/*
paxctl-ng.c: this file is part of the elfix package
Copyright (C) 2011 Anthony G. Basile
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef PTPAX
#include
#endif
#ifdef NEED_PAX_DECLS
#define PT_PAX_FLAGS 0x65041580 /* Indicates PaX flag markings */
#define PF_PAGEEXEC (1 << 4) /* Enable PAGEEXEC */
#define PF_NOPAGEEXEC (1 << 5) /* Disable PAGEEXEC */
#define PF_SEGMEXEC (1 << 6) /* Enable SEGMEXEC */
#define PF_NOSEGMEXEC (1 << 7) /* Disable SEGMEXEC */
#define PF_MPROTECT (1 << 8) /* Enable MPROTECT */
#define PF_NOMPROTECT (1 << 9) /* Disable MPROTECT */
#define PF_RANDEXEC (1 << 10) /* DEPRECATED: Enable RANDEXEC */
#define PF_NORANDEXEC (1 << 11) /* DEPRECATED: Disable RANDEXEC */
#define PF_EMUTRAMP (1 << 12) /* Enable EMUTRAMP */
#define PF_NOEMUTRAMP (1 << 13) /* Disable EMUTRAMP */
#define PF_RANDMMAP (1 << 14) /* Enable RANDMMAP */
#define PF_NORANDMMAP (1 << 15) /* Disable RANDMMAP */
#endif
#ifdef XTPAX
#include
#ifndef ENOATTR
#define ENOATTR ENODATA
#endif
#define PAX_NAMESPACE "user.pax.flags"
#define CREATE_XT_FLAGS_SECURE 1
#define CREATE_XT_FLAGS_DEFAULT 2
#define DELETE_XT_FLAGS 3
#endif
#if defined(PTPAX) && defined(XTPAX)
#define COPY_PT_TO_XT_FLAGS 4
#define COPY_XT_TO_PT_FLAGS 5
#endif
#define LIMIT_TO_PT_FLAGS 6
#define LIMIT_TO_XT_FLAGS 7
#define FLAGS_SIZE 6
#include
void
print_help_exit(char *v)
{
printf(
"\n"
"Package Name : " PACKAGE_STRING "\n"
"Bug Reports : " PACKAGE_BUGREPORT "\n"
"Program Name : %s\n"
"Description : Get or set pax flags on an ELF object\n\n"
#if defined(PTPAX) && defined(XTPAX)
"Usage : %s -PpEeMmRrSs|-Z|-z [-L|-l] [-v] ELF\n"
#else
"Usage : %s -PpEeMmRrSs|-Z|-z [-v] ELF\n"
#endif
#ifdef XTPAX
" : %s -C|-c|-d [-v] ELF\n"
#endif
#if defined(PTPAX) && defined(XTPAX)
" : %s -F|-f [-v] ELF\n"
#endif
" : %s -v ELF\n"
" : %s -L|-l\n"
" : %s [-h]\n\n"
"Options : -P enable PAGEEXEC\t-p disable PAGEEXEC\n"
" : -E enable EMUTRAMP\t-e disable EMUTRAMP\n"
" : -M enable MPROTECT\t-m disable MPROTECT\n"
" : -R enable RANDMMAP\t-r disable RANDMMAP\n"
" : -S enable SEGMEXEC\t-s disable SEGMEXEC\n"
" : -Z all secure settings\t-z all default settings\n"
#if defined(PTPAX) && defined(XTPAX)
" : -L set only PT_PAX flags\t-l set only XATTR_PAX flags\n"
#endif
" :\n"
#ifdef XTPAX
" : -C create XATTR_PAX with most secure setting\n"
" : -c create XATTR_PAX all default settings\n"
" : -d delete XATTR_PAX field\n"
#endif
#if defined(PTPAX) && defined(XTPAX)
" : -F copy PT_PAX to XATTR_PAX\n"
" : -f copy XATTR_PAX to PT_PAX\n"
#endif
#ifdef PTPAX
" : -L when given alone, EXIT_SUCCESS (PT_PAX is supported)\n"
#else
" : -L when given alone, EXIT_FAILURE (PT_PAX is not supported)\n"
#endif
#ifdef XTPAX
" : -l when given alone, EXIT_SUCCESS (XATTR_PAX is supported)\n"
#else
" : -l when given alone, EXIT_FAILURE (XATTR_PAX is not supported)\n"
#endif
" : -v view the flags, along with any accompanying operation\n"
" : -h print out this help\n\n"
"Note : If both enabling and disabling flags are set, the default - is used\n\n",
basename(v),
basename(v),
#ifdef XTPAX
basename(v),
#endif
#if defined(PTPAX) && defined(XTPAX)
basename(v),
#endif
basename(v),
basename(v),
basename(v)
);
exit(EXIT_SUCCESS);
}
void
parse_cmd_args(int argc, char *argv[], uint16_t *pax_flags, int *verbose, int *cp_flags,
int *limit, int *begin, int *end)
{
int i, oc;
int setflags, solflags, limitflags, solitaire;
setflags = 0;
solflags = 0;
limitflags = 0;
solitaire = 0;
*pax_flags = 0;
*verbose = 0;
*cp_flags = 0;
#if defined(PTPAX) && defined(XTPAX)
while((oc = getopt(argc, argv,":PpEeMmRrSsZzCcdFfLlvh")) != -1)
#elif defined(XTPAX) && !defined(PTPAX)
while((oc = getopt(argc, argv,":PpEeMmRrSsZzCcdLlvh")) != -1)
#else
while((oc = getopt(argc, argv,":PpEeMmRrSsZzLlvh")) != -1)
#endif
{
switch(oc)
{
case 'P':
*pax_flags |= PF_PAGEEXEC;
setflags |= 1;
break;
case 'p':
*pax_flags |= PF_NOPAGEEXEC;
setflags |= 1;
break ;
case 'E':
*pax_flags |= PF_EMUTRAMP;
setflags |= 1;
break;
case 'e':
*pax_flags |= PF_NOEMUTRAMP;
setflags |= 1;
break ;
case 'M':
*pax_flags |= PF_MPROTECT;
setflags |= 1;
break;
case 'm':
*pax_flags |= PF_NOMPROTECT;
setflags |= 1;
break ;
case 'R':
*pax_flags |= PF_RANDMMAP;
setflags |= 1;
break;
case 'r':
*pax_flags |= PF_NORANDMMAP;
setflags |= 1;
break ;
case 'S':
*pax_flags |= PF_SEGMEXEC;
setflags |= 1;
break;
case 's':
*pax_flags |= PF_NOSEGMEXEC;
setflags |= 1;
break ;
case 'Z':
*pax_flags = PF_PAGEEXEC | PF_SEGMEXEC | PF_MPROTECT |
PF_NOEMUTRAMP | PF_RANDMMAP ;
solflags += 1;
break ;
case 'z':
*pax_flags = PF_PAGEEXEC | PF_NOPAGEEXEC | PF_SEGMEXEC | PF_NOSEGMEXEC |
PF_MPROTECT | PF_NOMPROTECT | PF_EMUTRAMP | PF_NOEMUTRAMP |
PF_RANDMMAP | PF_NORANDMMAP ;
solflags += 1;
break;
#ifdef XTPAX
case 'C':
solitaire += 1;
*cp_flags = CREATE_XT_FLAGS_SECURE;
break;
case 'c':
solitaire += 1;
*cp_flags = CREATE_XT_FLAGS_DEFAULT;
break;
case 'd':
solitaire += 1;
*cp_flags = DELETE_XT_FLAGS;
break;
#ifdef PTPAX
case 'F':
solitaire += 1;
*cp_flags = COPY_PT_TO_XT_FLAGS;
break;
case 'f':
solitaire += 1;
*cp_flags = COPY_XT_TO_PT_FLAGS;
break;
#endif
#endif
case 'L':
limitflags += 1;
*limit = LIMIT_TO_PT_FLAGS;
break;
case 'l':
limitflags += 1;
*limit = LIMIT_TO_XT_FLAGS;
break;
case 'v':
*verbose = 1;
break;
case 'h':
print_help_exit(argv[0]);
break;
case '?':
default:
errx(EXIT_FAILURE, "option -%c is invalid: ignored.", optopt ) ;
}
}
if(
(setflags == 0 && solflags == 0 && limitflags == 1 && solitaire == 0)
&& *verbose == 0
&& argv[optind] == NULL // -L|-l
)
{
#ifdef PTPAX
if(*limit == LIMIT_TO_PT_FLAGS)
exit(EXIT_SUCCESS);
#endif
#ifdef XTPAX
if(*limit == LIMIT_TO_XT_FLAGS)
exit(EXIT_SUCCESS);
#endif
exit(EXIT_FAILURE);
}
if(
(
(setflags == 1 && solflags == 0 && limitflags <= 1 && solitaire == 0) //-PpEeMmRrSs [-L|-l] [-v] ELF
|| (setflags == 0 && solflags == 1 && limitflags <= 1 && solitaire == 0) //-Z|-z [-L|-l] [-v] ELF
|| (setflags == 0 && solflags == 0 && limitflags == 0 && solitaire == 1) //-C|-c|-d|-F|-f [-v] ELF
|| (setflags == 0 && solflags == 0 && limitflags == 0 && solitaire == 0 && *verbose == 1) // -v ELF
)
&& argv[optind] != NULL
)
{
*begin = optind;
*end = argc;
}
else
print_help_exit(argv[0]);
}
#ifdef PTPAX
uint16_t
get_pt_flags(int fd, int verbose)
{
Elf *elf;
GElf_Phdr phdr;
size_t i, phnum;
uint16_t pt_flags = UINT16_MAX;
if(elf_version(EV_CURRENT) == EV_NONE)
{
if(verbose)
printf("\tELF ERROR: Library out of date.\n");
return pt_flags;
}
if((elf = elf_begin(fd, ELF_C_READ_MMAP, NULL)) == NULL)
{
if(verbose)
printf("\tELF ERROR: elf_begin() fail: %s\n", elf_errmsg(elf_errno()));
return pt_flags;
}
if(elf_kind(elf) != ELF_K_ELF)
{
elf_end(elf);
if(verbose)
printf("\tELF ERROR: elf_kind() fail: this is not an elf file.\n");
return pt_flags;
}
elf_getphdrnum(elf, &phnum);
for(i=0; i