1 /*-
2  * Copyright (c) 2006 nCircle Network Security, Inc.
3  * Copyright (c) 2007 Robert N. M. Watson
4  * All rights reserved.
5  *
6  * This software was developed by Robert N. M. Watson for the TrustedBSD
7  * Project under contract to nCircle Network Security, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
22  * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /*-
32  * Test that raising current resource limits above hard resource limits
33  * requires privilege.  We test three cases:
34  *
35  * - Raise the current above the maximum (privileged).
36  * - Raise the current to the maximum (unprivileged).
37  * - Raise the maximum (privileged).
38  */
39 
40 #include <sys/types.h>
41 #include <sys/time.h>
42 #include <sys/resource.h>
43 
44 #include <err.h>
45 #include <errno.h>
46 #include <unistd.h>
47 
48 #include "main.h"
49 
50 static int initialized;
51 static struct rlimit rl_base;
52 static struct rlimit rl_lowered;
53 
54 int
55 priv_proc_setrlimit_setup(int asroot, int injail, struct test *test)
56 {
57 
58 	if (getrlimit(RLIMIT_DATA, &rl_base) < 0) {
59 		warn("priv_proc_setrlimit_setup: getrlimit");
60 		return (-1);
61 	}
62 
63 	/*
64 	 * Must lower current and limit to make sure there's room to try to
65 	 * raise them during tests.  Set current lower than max so we can
66 	 * raise it later also.
67 	 */
68 	rl_lowered = rl_base;
69 	rl_lowered.rlim_cur -= 20;
70 	rl_lowered.rlim_max -= 10;
71 	if (setrlimit(RLIMIT_DATA, &rl_lowered) < 0) {
72 		warn("priv_proc_setrlimit_setup: setrlimit");
73 		return (-1);
74 	}
75 	initialized = 1;
76 	return (0);
77 }
78 
79 /*
80  * Try increasing the maximum limits on the process, which requires
81  * privilege.
82  */
83 void
84 priv_proc_setrlimit_raisemax(int asroot, int injail, struct test *test)
85 {
86 	struct rlimit rl;
87 	int error;
88 
89 	rl = rl_lowered;
90 	rl.rlim_max = rl_base.rlim_max;
91 	error = setrlimit(RLIMIT_DATA, &rl);
92 	if (asroot && injail)
93 		expect("priv_proc_setrlimit_raisemax(asroot, injail)", error,
94 		    0, 0);
95 	if (asroot && !injail)
96 		expect("priv_proc_setrlimit_raisemax(asroot, !injail)",
97 		    error, 0, 0);
98 	if (!asroot && injail)
99 		expect("priv_proc_setrlimit_raisemax(!asroot, injail)",
100 		    error, -1, EPERM);
101 	if (!asroot && !injail)
102 		expect("priv_proc_setrlimit_raisemax(!asroot, !injail)",
103 		    error, -1, EPERM);
104 }
105 
106 /*
107  * Try setting the current limit to the current maximum, which is allowed
108  * without privilege.
109  */
110 void
111 priv_proc_setrlimit_raisecur_nopriv(int asroot, int injail,
112     struct test *test)
113 {
114 	struct rlimit rl;
115 	int error;
116 
117 	rl = rl_lowered;
118 	rl.rlim_cur = rl.rlim_max;
119 	error = setrlimit(RLIMIT_DATA, &rl);
120 	if (asroot && injail)
121 		expect("priv_proc_setrlimit_raiscur_nopriv(asroot, injail)",
122 		    error, 0, 0);
123 	if (asroot && !injail)
124 		expect("priv_proc_setrlimit_raisecur_nopriv(asroot, !injail)",
125 		    error, 0, 0);
126 	if (!asroot && injail)
127 		expect("priv_proc_setrlimit_raisecur_nopriv(!asroot, injail)",
128 		    error, 0, 0);
129 	if (!asroot && !injail)
130 		expect("priv_proc_setrlimit_raisecur_nopriv(!asroot, !injail)",
131 		    error, 0, 0);
132 }
133 
134 /*
135  * Try raising the current limits above the maximum, which requires
136  * privilege.
137  */
138 void
139 priv_proc_setrlimit_raisecur(int asroot, int injail, struct test *test)
140 {
141 	struct rlimit rl;
142 	int error;
143 
144 	rl = rl_lowered;
145 	rl.rlim_cur = rl.rlim_max + 10;
146 	error = setrlimit(RLIMIT_DATA, &rl);
147 	if (asroot && injail)
148 		expect("priv_proc_setrlimit_raisecur(asroot, injail)", error,
149 		    0, 0);
150 	if (asroot && !injail)
151 		expect("priv_proc_setrlimit_raisecur(asroot, !injail)",
152 		    error, 0, 0);
153 	if (!asroot && injail)
154 		expect("priv_proc_setrlimit_raisecur(!asroot, injail)",
155 		    error, -1, EPERM);
156 	if (!asroot && !injail)
157 		expect("priv_proc_setrlimit_raisecur(!asroot, !injail)",
158 		    error, -1, EPERM);
159 }
160 
161 void
162 priv_proc_setrlimit_cleanup(int asroot, int injail, struct test *test)
163 {
164 
165 	if (initialized)
166 		(void)setrlimit(RLIMIT_DATA, &rl_base);
167 	initialized = 0;
168 }
169