/* 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