xref: /freebsd/lib/libveriexec/veriexec_check.c (revision a2f733abcff64628b7771a47089628b7327a88bd)
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