1/*-
2 * Copyright (c) 2016 Mariusz Zaborski <oshogbo@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#ifndef _CAPSICUM_HELPERS_H_
30#define	_CAPSICUM_HELPERS_H_
31
32#include <sys/param.h>
33#include <sys/capsicum.h>
34#include <sys/ioctl.h>
35
36#include <errno.h>
37#include <nl_types.h>
38#include <termios.h>
39#include <time.h>
40#include <unistd.h>
41
42#include <libcasper.h>
43
44#define	CAPH_IGNORE_EBADF	0x0001
45#define	CAPH_READ		0x0002
46#define	CAPH_WRITE		0x0004
47#define	CAPH_LOOKUP		0x0008
48
49__BEGIN_DECLS
50
51static const unsigned long caph_stream_cmds[] =
52    {
53#ifdef TIOCGETA
54	TIOCGETA,
55#endif
56#ifdef TIOCGWINSZ
57	TIOCGWINSZ,
58#endif
59#ifdef FIODTYPE
60	FIODTYPE,
61#endif
62    };
63static const uint32_t caph_stream_fcntls = CAP_FCNTL_GETFL;
64
65static __inline void
66caph_stream_rights(cap_rights_t *rights, int flags)
67{
68
69	cap_rights_init(rights, CAP_EVENT, CAP_FCNTL, CAP_FSTAT,
70	    CAP_IOCTL, CAP_SEEK);
71
72	if ((flags & CAPH_READ) != 0)
73		cap_rights_set(rights, CAP_READ);
74	if ((flags & CAPH_WRITE) != 0)
75		cap_rights_set(rights, CAP_WRITE);
76	if ((flags & CAPH_LOOKUP) != 0)
77		cap_rights_set(rights, CAP_LOOKUP);
78}
79
80static __inline int
81caph_limit_stream(int fd, int flags)
82{
83	cap_rights_t rights;
84
85	caph_stream_rights(&rights, flags);
86	if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) {
87		if (errno == EBADF && (flags & CAPH_IGNORE_EBADF) != 0)
88			return (0);
89		return (-1);
90	}
91
92	if (cap_ioctls_limit(fd, caph_stream_cmds,
93	    nitems(caph_stream_cmds)) < 0 && errno != ENOSYS)
94		return (-1);
95
96	if (cap_fcntls_limit(fd, caph_stream_fcntls) < 0 && errno != ENOSYS)
97		return (-1);
98
99	return (0);
100}
101
102static __inline int
103caph_limit_stdin(void)
104{
105
106	return (caph_limit_stream(STDIN_FILENO, CAPH_READ));
107}
108
109static __inline int
110caph_limit_stderr(void)
111{
112
113	return (caph_limit_stream(STDERR_FILENO, CAPH_WRITE));
114}
115
116static __inline int
117caph_limit_stdout(void)
118{
119
120	return (caph_limit_stream(STDOUT_FILENO, CAPH_WRITE));
121}
122
123static __inline int
124caph_limit_stdio(void)
125{
126	const int iebadf = CAPH_IGNORE_EBADF;
127
128	if (caph_limit_stream(STDIN_FILENO, CAPH_READ | iebadf) == -1 ||
129	    caph_limit_stream(STDOUT_FILENO, CAPH_WRITE | iebadf) == -1 ||
130	    caph_limit_stream(STDERR_FILENO, CAPH_WRITE | iebadf) == -1)
131		return (-1);
132	return (0);
133}
134
135static __inline void
136caph_cache_tzdata(void)
137{
138
139	tzset();
140}
141
142static __inline void
143caph_cache_catpages(void)
144{
145
146	(void)catopen("libc", NL_CAT_LOCALE);
147}
148
149static __inline int
150caph_enter(void)
151{
152
153	if (cap_enter() < 0 && errno != ENOSYS)
154		return (-1);
155
156	return (0);
157}
158
159static __inline int
160caph_rights_limit(int fd, const cap_rights_t *rights)
161{
162
163	if (cap_rights_limit(fd, rights) < 0 && errno != ENOSYS)
164		return (-1);
165
166	return (0);
167}
168
169static __inline int
170caph_ioctls_limit(int fd, const unsigned long *cmds, size_t ncmds)
171{
172
173	if (cap_ioctls_limit(fd, cmds, ncmds) < 0 && errno != ENOSYS)
174		return (-1);
175
176	return (0);
177}
178
179static __inline int
180caph_fcntls_limit(int fd, uint32_t fcntlrights)
181{
182
183	if (cap_fcntls_limit(fd, fcntlrights) < 0 && errno != ENOSYS)
184		return (-1);
185
186	return (0);
187}
188
189static __inline int
190caph_enter_casper(void)
191{
192
193	return (CASPER_SUPPORT == 0 ? 0 : caph_enter());
194}
195
196__END_DECLS
197
198#endif /* _CAPSICUM_HELPERS_H_ */
199