1*b6b5dcf2SStephen J. Kiernan /* 2*b6b5dcf2SStephen J. Kiernan * $FreeBSD$ 3*b6b5dcf2SStephen J. Kiernan * 4*b6b5dcf2SStephen J. Kiernan * Copyright (c) 2011, 2012, 2013, 2015, Juniper Networks, Inc. 5*b6b5dcf2SStephen J. Kiernan * All rights reserved. 6*b6b5dcf2SStephen J. Kiernan * 7*b6b5dcf2SStephen J. Kiernan * Redistribution and use in source and binary forms, with or without 8*b6b5dcf2SStephen J. Kiernan * modification, are permitted provided that the following conditions 9*b6b5dcf2SStephen J. Kiernan * are met: 10*b6b5dcf2SStephen J. Kiernan * 1. Redistributions of source code must retain the above copyright 11*b6b5dcf2SStephen J. Kiernan * notice, this list of conditions and the following disclaimer. 12*b6b5dcf2SStephen J. Kiernan * 2. Redistributions in binary form must reproduce the above copyright 13*b6b5dcf2SStephen J. Kiernan * notice, this list of conditions and the following disclaimer in the 14*b6b5dcf2SStephen J. Kiernan * documentation and/or other materials provided with the distribution. 15*b6b5dcf2SStephen J. Kiernan * 16*b6b5dcf2SStephen J. Kiernan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17*b6b5dcf2SStephen J. Kiernan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18*b6b5dcf2SStephen J. Kiernan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19*b6b5dcf2SStephen J. Kiernan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20*b6b5dcf2SStephen J. Kiernan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21*b6b5dcf2SStephen J. Kiernan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22*b6b5dcf2SStephen J. Kiernan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23*b6b5dcf2SStephen J. Kiernan * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24*b6b5dcf2SStephen J. Kiernan * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*b6b5dcf2SStephen J. Kiernan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*b6b5dcf2SStephen J. Kiernan * SUCH DAMAGE. 27*b6b5dcf2SStephen J. Kiernan */ 28*b6b5dcf2SStephen J. Kiernan 29*b6b5dcf2SStephen J. Kiernan #include <sys/cdefs.h> 30*b6b5dcf2SStephen J. Kiernan #include <sys/types.h> 31*b6b5dcf2SStephen J. Kiernan #include <sys/errno.h> 32*b6b5dcf2SStephen J. Kiernan #include <sys/mac.h> 33*b6b5dcf2SStephen J. Kiernan #include <sys/stat.h> 34*b6b5dcf2SStephen J. Kiernan 35*b6b5dcf2SStephen J. Kiernan #include <stdio.h> 36*b6b5dcf2SStephen J. Kiernan #include <string.h> 37*b6b5dcf2SStephen J. Kiernan #include <unistd.h> 38*b6b5dcf2SStephen J. Kiernan #include <fcntl.h> 39*b6b5dcf2SStephen J. Kiernan #include <paths.h> 40*b6b5dcf2SStephen J. Kiernan 41*b6b5dcf2SStephen J. Kiernan #include <security/mac_veriexec/mac_veriexec.h> 42*b6b5dcf2SStephen J. Kiernan 43*b6b5dcf2SStephen J. Kiernan #include "libveriexec.h" 44*b6b5dcf2SStephen J. Kiernan 45*b6b5dcf2SStephen J. Kiernan 46*b6b5dcf2SStephen J. Kiernan static int 47*b6b5dcf2SStephen J. Kiernan check_fd_mode(int fd, unsigned int mask) 48*b6b5dcf2SStephen J. Kiernan { 49*b6b5dcf2SStephen J. Kiernan struct stat st; 50*b6b5dcf2SStephen J. Kiernan 51*b6b5dcf2SStephen J. Kiernan if (fstat(fd, &st) < 0) 52*b6b5dcf2SStephen J. Kiernan return errno; 53*b6b5dcf2SStephen J. Kiernan 54*b6b5dcf2SStephen J. Kiernan if ((st.st_mode & mask) == 0) 55*b6b5dcf2SStephen J. Kiernan return EAUTH; 56*b6b5dcf2SStephen J. Kiernan 57*b6b5dcf2SStephen J. Kiernan return 0; 58*b6b5dcf2SStephen J. Kiernan } 59*b6b5dcf2SStephen J. Kiernan 60*b6b5dcf2SStephen J. Kiernan int 61*b6b5dcf2SStephen J. Kiernan veriexec_check_fd_mode(int fd, unsigned int mask) 62*b6b5dcf2SStephen J. Kiernan { 63*b6b5dcf2SStephen J. Kiernan int error; 64*b6b5dcf2SStephen J. Kiernan 65*b6b5dcf2SStephen J. Kiernan if (fd < 0) { 66*b6b5dcf2SStephen J. Kiernan errno = EINVAL; 67*b6b5dcf2SStephen J. Kiernan return -1; 68*b6b5dcf2SStephen J. Kiernan } 69*b6b5dcf2SStephen J. Kiernan 70*b6b5dcf2SStephen J. Kiernan error = mac_syscall(MAC_VERIEXEC_NAME, MAC_VERIEXEC_CHECK_FD_SYSCALL, 71*b6b5dcf2SStephen J. Kiernan (void *)(intptr_t)fd); 72*b6b5dcf2SStephen J. Kiernan if (error == -1) { 73*b6b5dcf2SStephen J. Kiernan switch (errno) { 74*b6b5dcf2SStephen J. Kiernan case ENOSYS: /* veriexec not loaded */ 75*b6b5dcf2SStephen J. Kiernan error = 0; /* ignore */ 76*b6b5dcf2SStephen J. Kiernan break; 77*b6b5dcf2SStephen J. Kiernan } 78*b6b5dcf2SStephen J. Kiernan } 79*b6b5dcf2SStephen J. Kiernan if (mask && error == 0) 80*b6b5dcf2SStephen J. Kiernan error = check_fd_mode(fd, mask); 81*b6b5dcf2SStephen J. Kiernan 82*b6b5dcf2SStephen J. Kiernan return (error); 83*b6b5dcf2SStephen J. Kiernan } 84*b6b5dcf2SStephen J. Kiernan 85*b6b5dcf2SStephen J. Kiernan int 86*b6b5dcf2SStephen J. Kiernan veriexec_check_path_mode(const char *file, unsigned int mask) 87*b6b5dcf2SStephen J. Kiernan { 88*b6b5dcf2SStephen J. Kiernan int error; 89*b6b5dcf2SStephen J. Kiernan 90*b6b5dcf2SStephen J. Kiernan if (!file) { 91*b6b5dcf2SStephen J. Kiernan errno = EINVAL; 92*b6b5dcf2SStephen J. Kiernan return -1; 93*b6b5dcf2SStephen J. Kiernan } 94*b6b5dcf2SStephen J. Kiernan 95*b6b5dcf2SStephen J. Kiernan if (mask) { 96*b6b5dcf2SStephen J. Kiernan int fd; 97*b6b5dcf2SStephen J. Kiernan 98*b6b5dcf2SStephen J. Kiernan if ((fd = open(file, O_RDONLY)) < 0) 99*b6b5dcf2SStephen J. Kiernan return errno; 100*b6b5dcf2SStephen J. Kiernan 101*b6b5dcf2SStephen J. Kiernan error = veriexec_check_fd_mode(fd, mask); 102*b6b5dcf2SStephen J. Kiernan close(fd); 103*b6b5dcf2SStephen J. Kiernan return error; 104*b6b5dcf2SStephen J. Kiernan } 105*b6b5dcf2SStephen J. Kiernan 106*b6b5dcf2SStephen J. Kiernan error = mac_syscall(MAC_VERIEXEC_NAME, MAC_VERIEXEC_CHECK_PATH_SYSCALL, 107*b6b5dcf2SStephen J. Kiernan __DECONST(void *, file)); 108*b6b5dcf2SStephen J. Kiernan if (error == -1) { 109*b6b5dcf2SStephen J. Kiernan switch (errno) { 110*b6b5dcf2SStephen J. Kiernan case ENOSYS: /* veriexec not loaded */ 111*b6b5dcf2SStephen J. Kiernan error = 0; /* ignore */ 112*b6b5dcf2SStephen J. Kiernan break; 113*b6b5dcf2SStephen J. Kiernan } 114*b6b5dcf2SStephen J. Kiernan } 115*b6b5dcf2SStephen J. Kiernan return (error); 116*b6b5dcf2SStephen J. Kiernan } 117*b6b5dcf2SStephen J. Kiernan 118*b6b5dcf2SStephen J. Kiernan int 119*b6b5dcf2SStephen J. Kiernan veriexec_check_fd(int fd) 120*b6b5dcf2SStephen J. Kiernan { 121*b6b5dcf2SStephen J. Kiernan return veriexec_check_fd_mode(fd, 0); 122*b6b5dcf2SStephen J. Kiernan } 123*b6b5dcf2SStephen J. Kiernan 124*b6b5dcf2SStephen J. Kiernan int 125*b6b5dcf2SStephen J. Kiernan veriexec_check_path(const char *file) 126*b6b5dcf2SStephen J. Kiernan { 127*b6b5dcf2SStephen J. Kiernan return veriexec_check_path_mode(file, 0); 128*b6b5dcf2SStephen J. Kiernan } 129*b6b5dcf2SStephen J. Kiernan 130*b6b5dcf2SStephen J. Kiernan #if defined(MAIN) || defined(UNIT_TEST) 131*b6b5dcf2SStephen J. Kiernan int 132*b6b5dcf2SStephen J. Kiernan main(int argc __unused, char *argv[] __unused) 133*b6b5dcf2SStephen J. Kiernan { 134*b6b5dcf2SStephen J. Kiernan int error; 135*b6b5dcf2SStephen J. Kiernan int rc = 0; 136*b6b5dcf2SStephen J. Kiernan 137*b6b5dcf2SStephen J. Kiernan while (*++argv) { 138*b6b5dcf2SStephen J. Kiernan error = veriexec_check_path(*argv); 139*b6b5dcf2SStephen J. Kiernan if (error == -1) { 140*b6b5dcf2SStephen J. Kiernan rc = 1; 141*b6b5dcf2SStephen J. Kiernan warn("%s", *argv); 142*b6b5dcf2SStephen J. Kiernan } 143*b6b5dcf2SStephen J. Kiernan } 144*b6b5dcf2SStephen J. Kiernan exit(rc); 145*b6b5dcf2SStephen J. Kiernan } 146*b6b5dcf2SStephen J. Kiernan #endif 147