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