1162271Srwatson/*-
2162271Srwatson * Copyright (c) 2006 nCircle Network Security, Inc.
3172106Srwatson * Copyright (c) 2007 Robert N. M. Watson
4162271Srwatson * All rights reserved.
5162271Srwatson *
6162271Srwatson * This software was developed by Robert N. M. Watson for the TrustedBSD
7162271Srwatson * Project under contract to nCircle Network Security, Inc.
8162271Srwatson *
9162271Srwatson * Redistribution and use in source and binary forms, with or without
10162271Srwatson * modification, are permitted provided that the following conditions
11162271Srwatson * are met:
12162271Srwatson * 1. Redistributions of source code must retain the above copyright
13162271Srwatson *    notice, this list of conditions and the following disclaimer.
14162271Srwatson * 2. Redistributions in binary form must reproduce the above copyright
15162271Srwatson *    notice, this list of conditions and the following disclaimer in the
16162271Srwatson *    documentation and/or other materials provided with the distribution.
17162271Srwatson *
18162271Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19162271Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20162271Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21162271Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
22162271Srwatson * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23162271Srwatson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24162271Srwatson * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25162271Srwatson * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26162271Srwatson * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27162271Srwatson * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28162271Srwatson * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29162271Srwatson *
30162271Srwatson * $FreeBSD$
31162271Srwatson */
32162271Srwatson
33172106Srwatson/*-
34162271Srwatson * Test that raising current resource limits above hard resource limits
35172106Srwatson * requires privilege.  We test three cases:
36162271Srwatson *
37172106Srwatson * - Raise the current above the maximum (privileged).
38172106Srwatson * - Raise the current to the maximum (unprivileged).
39172106Srwatson * - Raise the maximum (privileged).
40162271Srwatson */
41162271Srwatson
42162271Srwatson#include <sys/types.h>
43162271Srwatson#include <sys/time.h>
44162271Srwatson#include <sys/resource.h>
45162271Srwatson
46162271Srwatson#include <err.h>
47162271Srwatson#include <errno.h>
48162271Srwatson#include <unistd.h>
49162271Srwatson
50162271Srwatson#include "main.h"
51162271Srwatson
52172106Srwatsonstatic int initialized;
53172106Srwatsonstatic struct rlimit rl_base;
54172106Srwatsonstatic struct rlimit rl_lowered;
55172106Srwatson
56172106Srwatsonint
57172106Srwatsonpriv_proc_setrlimit_setup(int asroot, int injail, struct test *test)
58162271Srwatson{
59162271Srwatson
60172106Srwatson	if (getrlimit(RLIMIT_DATA, &rl_base) < 0) {
61172106Srwatson		warn("priv_proc_setrlimit_setup: getrlimit");
62172106Srwatson		return (-1);
63172106Srwatson	}
64162271Srwatson
65162271Srwatson	/*
66172106Srwatson	 * Must lower current and limit to make sure there's room to try to
67172106Srwatson	 * raise them during tests.  Set current lower than max so we can
68172106Srwatson	 * raise it later also.
69162271Srwatson	 */
70172106Srwatson	rl_lowered = rl_base;
71172106Srwatson	rl_lowered.rlim_cur -= 20;
72172106Srwatson	rl_lowered.rlim_max -= 10;
73172106Srwatson	if (setrlimit(RLIMIT_DATA, &rl_lowered) < 0) {
74172106Srwatson		warn("priv_proc_setrlimit_setup: setrlimit");
75172106Srwatson		return (-1);
76172106Srwatson	}
77172106Srwatson	initialized = 1;
78172106Srwatson	return (0);
79172106Srwatson}
80162271Srwatson
81172106Srwatson/*
82172106Srwatson * Try increasing the maximum limits on the process, which requires
83172106Srwatson * privilege.
84172106Srwatson */
85172106Srwatsonvoid
86172106Srwatsonpriv_proc_setrlimit_raisemax(int asroot, int injail, struct test *test)
87172106Srwatson{
88172106Srwatson	struct rlimit rl;
89172106Srwatson	int error;
90162271Srwatson
91172106Srwatson	rl = rl_lowered;
92172106Srwatson	rl.rlim_max = rl_base.rlim_max;
93172106Srwatson	error = setrlimit(RLIMIT_DATA, &rl);
94172106Srwatson	if (asroot && injail)
95172106Srwatson		expect("priv_proc_setrlimit_raisemax(asroot, injail)", error,
96172106Srwatson		    0, 0);
97172106Srwatson	if (asroot && !injail)
98172106Srwatson		expect("priv_proc_setrlimit_raisemax(asroot, !injail)",
99172106Srwatson		    error, 0, 0);
100172106Srwatson	if (!asroot && injail)
101172106Srwatson		expect("priv_proc_setrlimit_raisemax(!asroot, injail)",
102172106Srwatson		    error, -1, EPERM);
103172106Srwatson	if (!asroot && !injail)
104172106Srwatson		expect("priv_proc_setrlimit_raisemax(!asroot, !injail)",
105172106Srwatson		    error, -1, EPERM);
106172106Srwatson}
107162271Srwatson
108172106Srwatson/*
109172106Srwatson * Try setting the current limit to the current maximum, which is allowed
110172106Srwatson * without privilege.
111172106Srwatson */
112172106Srwatsonvoid
113172106Srwatsonpriv_proc_setrlimit_raisecur_nopriv(int asroot, int injail,
114172106Srwatson    struct test *test)
115172106Srwatson{
116172106Srwatson	struct rlimit rl;
117172106Srwatson	int error;
118162271Srwatson
119172106Srwatson	rl = rl_lowered;
120172106Srwatson	rl.rlim_cur = rl.rlim_max;
121172106Srwatson	error = setrlimit(RLIMIT_DATA, &rl);
122172106Srwatson	if (asroot && injail)
123172106Srwatson		expect("priv_proc_setrlimit_raiscur_nopriv(asroot, injail)",
124172106Srwatson		    error, 0, 0);
125172106Srwatson	if (asroot && !injail)
126172106Srwatson		expect("priv_proc_setrlimit_raisecur_nopriv(asroot, !injail)",
127172106Srwatson		    error, 0, 0);
128172106Srwatson	if (!asroot && injail)
129172106Srwatson		expect("priv_proc_setrlimit_raisecur_nopriv(!asroot, injail)",
130172106Srwatson		    error, 0, 0);
131172106Srwatson	if (!asroot && !injail)
132172106Srwatson		expect("priv_proc_setrlimit_raisecur_nopriv(!asroot, !injail)",
133172106Srwatson		    error, 0, 0);
134172106Srwatson}
135162271Srwatson
136172106Srwatson/*
137172106Srwatson * Try raising the current limits above the maximum, which requires
138172106Srwatson * privilege.
139172106Srwatson */
140172106Srwatsonvoid
141172106Srwatsonpriv_proc_setrlimit_raisecur(int asroot, int injail, struct test *test)
142172106Srwatson{
143172106Srwatson	struct rlimit rl;
144172106Srwatson	int error;
145162271Srwatson
146172106Srwatson	rl = rl_lowered;
147172106Srwatson	rl.rlim_cur = rl.rlim_max + 10;
148172106Srwatson	error = setrlimit(RLIMIT_DATA, &rl);
149172106Srwatson	if (asroot && injail)
150172106Srwatson		expect("priv_proc_setrlimit_raisecur(asroot, injail)", error,
151172106Srwatson		    0, 0);
152172106Srwatson	if (asroot && !injail)
153172106Srwatson		expect("priv_proc_setrlimit_raisecur(asroot, !injail)",
154172106Srwatson		    error, 0, 0);
155172106Srwatson	if (!asroot && injail)
156172106Srwatson		expect("priv_proc_setrlimit_raisecur(!asroot, injail)",
157172106Srwatson		    error, -1, EPERM);
158172106Srwatson	if (!asroot && !injail)
159172106Srwatson		expect("priv_proc_setrlimit_raisecur(!asroot, !injail)",
160172106Srwatson		    error, -1, EPERM);
161172106Srwatson}
162162271Srwatson
163172106Srwatsonvoid
164172106Srwatsonpriv_proc_setrlimit_cleanup(int asroot, int injail, struct test *test)
165172106Srwatson{
166162271Srwatson
167172106Srwatson	if (initialized)
168172106Srwatson		(void)setrlimit(RLIMIT_DATA, &rl_base);
169172106Srwatson	initialized = 0;
170162271Srwatson}
171