143412Snewton/*-
243412Snewton * Copyright (c) 1998 The NetBSD Foundation, Inc.
343412Snewton * All rights reserved.
443412Snewton *
543412Snewton * This code is derived from software contributed to The NetBSD Foundation
643412Snewton * by Christos Zoulas.
743412Snewton *
843412Snewton * Redistribution and use in source and binary forms, with or without
943412Snewton * modification, are permitted provided that the following conditions
1043412Snewton * are met:
1143412Snewton * 1. Redistributions of source code must retain the above copyright
1243412Snewton *    notice, this list of conditions and the following disclaimer.
1343412Snewton * 2. Redistributions in binary form must reproduce the above copyright
1443412Snewton *    notice, this list of conditions and the following disclaimer in the
1543412Snewton *    documentation and/or other materials provided with the distribution.
1643412Snewton *
1743412Snewton * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1843412Snewton * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1943412Snewton * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2043412Snewton * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2143412Snewton * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2243412Snewton * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2343412Snewton * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2443412Snewton * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2543412Snewton * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2643412Snewton * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2743412Snewton * POSSIBILITY OF SUCH DAMAGE.
2843412Snewton */
29139743Simp/*-
3043412Snewton * Portions of this software have been derived from software contributed
3143412Snewton * to the FreeBSD Project by Mark Newton.
3243412Snewton *
3343412Snewton * Copyright (c) 1999 Mark Newton
3443412Snewton * All rights reserved.
3543412Snewton *
3643412Snewton * Redistribution and use in source and binary forms, with or without
3743412Snewton * modification, are permitted provided that the following conditions
3843412Snewton * are met:
3943412Snewton * 1. Redistributions of source code must retain the above copyright
4043412Snewton *    notice, this list of conditions and the following disclaimer.
4143412Snewton * 2. Redistributions in binary form must reproduce the above copyright
4243412Snewton *    notice, this list of conditions and the following disclaimer in the
4343412Snewton *    documentation and/or other materials provided with the distribution.
4443412Snewton * 3. The name of the author may not be used to endorse or promote products
4543412Snewton *    derived from this software without specific prior written permission
4643412Snewton *
4743412Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4843412Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4943412Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5043412Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
5143412Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5243412Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5343412Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5443412Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5543412Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5643412Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57116174Sobrien *
58116174Sobrien * Derived from: $NetBSD: svr4_resource.c,v 1.3 1998/12/13 18:00:52 christos Exp $
5943412Snewton */
6043412Snewton
61116174Sobrien#include <sys/cdefs.h>
62116174Sobrien__FBSDID("$FreeBSD: releng/11.0/sys/compat/svr4/svr4_resource.c 284215 2015-06-10 10:48:12Z mjg $");
63116174Sobrien
6443412Snewton#include <sys/param.h>
6543412Snewton#include <sys/systm.h>
6676166Smarkm#include <sys/file.h>
6784811Sjhb#include <sys/lock.h>
6876166Smarkm#include <sys/mutex.h>
6943412Snewton#include <sys/proc.h>
7043412Snewton#include <sys/resource.h>
7143412Snewton#include <sys/resourcevar.h>
72139739Sjhb#include <sys/syscallsubr.h>
7343412Snewton
7465302Sobrien#include <compat/svr4/svr4.h>
7565302Sobrien#include <compat/svr4/svr4_types.h>
7665302Sobrien#include <compat/svr4/svr4_resource.h>
7765302Sobrien#include <compat/svr4/svr4_signal.h>
7865302Sobrien#include <compat/svr4/svr4_proto.h>
7965302Sobrien#include <compat/svr4/svr4_util.h>
8043412Snewton
8192761Salfredstatic __inline int svr4_to_native_rl(int);
8243412Snewton
8343412Snewtonstatic __inline int
8443412Snewtonsvr4_to_native_rl(rl)
8543412Snewton	int rl;
8643412Snewton{
8743412Snewton	switch (rl) {
8843412Snewton	case SVR4_RLIMIT_CPU:
8943412Snewton		return RLIMIT_CPU;
9043412Snewton	case SVR4_RLIMIT_FSIZE:
9143412Snewton		return RLIMIT_FSIZE;
9243412Snewton	case SVR4_RLIMIT_DATA:
9343412Snewton		return RLIMIT_DATA;
9443412Snewton	case SVR4_RLIMIT_STACK:
9543412Snewton		return RLIMIT_STACK;
9643412Snewton	case SVR4_RLIMIT_CORE:
9743412Snewton		return RLIMIT_CORE;
9843412Snewton	case SVR4_RLIMIT_NOFILE:
9943412Snewton		return RLIMIT_NOFILE;
10043412Snewton	case SVR4_RLIMIT_VMEM:
101102630Sdillon		return RLIMIT_VMEM;
10243412Snewton	default:
10343412Snewton		return -1;
10443412Snewton	}
10543412Snewton}
10643412Snewton
10743412Snewton/*
10843412Snewton * Check if the resource limit fits within the BSD range and it is not
10943412Snewton * one of the magic SVR4 limit values
11043412Snewton */
11143412Snewton#define OKLIMIT(l) (((int32_t)(l)) >= 0 && ((int32_t)(l)) < 0x7fffffff && \
11243412Snewton	((svr4_rlim_t)(l)) != SVR4_RLIM_INFINITY && \
11343412Snewton	((svr4_rlim_t)(l)) != SVR4_RLIM_SAVED_CUR && \
11443412Snewton	((svr4_rlim_t)(l)) != SVR4_RLIM_SAVED_MAX)
11543412Snewton
11643412Snewton#define OKLIMIT64(l) (((rlim_t)(l)) >= 0 && ((rlim_t)(l)) < RLIM_INFINITY && \
11743412Snewton	((svr4_rlim64_t)(l)) != SVR4_RLIM64_INFINITY && \
11843412Snewton	((svr4_rlim64_t)(l)) != SVR4_RLIM64_SAVED_CUR && \
11943412Snewton	((svr4_rlim64_t)(l)) != SVR4_RLIM64_SAVED_MAX)
12043412Snewton
12143412Snewtonint
12283366Sjuliansvr4_sys_getrlimit(td, uap)
123193014Sdelphij	struct thread *td;
12443412Snewton	struct svr4_sys_getrlimit_args *uap;
12543412Snewton{
126107849Salfred	int rl = svr4_to_native_rl(uap->which);
12743412Snewton	struct rlimit blim;
12843412Snewton	struct svr4_rlimit slim;
12943412Snewton
13043412Snewton	if (rl == -1)
13143412Snewton		return EINVAL;
13243412Snewton
133284215Smjg	lim_rlimit(td, rl, &blim);
13443412Snewton
13543412Snewton	/*
13643412Snewton	 * Our infinity, is their maxfiles.
13743412Snewton	 */
13843412Snewton	if (rl == RLIMIT_NOFILE && blim.rlim_max == RLIM_INFINITY)
13943412Snewton		blim.rlim_max = maxfiles;
14043412Snewton
14143412Snewton	/*
14243412Snewton	 * If the limit can be be represented, it is returned.
14343412Snewton	 * Otherwise, if rlim_cur == rlim_max, return RLIM_SAVED_MAX
14443412Snewton	 * else return RLIM_SAVED_CUR
14543412Snewton	 */
14643412Snewton	if (blim.rlim_max == RLIM_INFINITY)
14743412Snewton		slim.rlim_max = SVR4_RLIM_INFINITY;
14843412Snewton	else if (OKLIMIT(blim.rlim_max))
14943412Snewton		slim.rlim_max = (svr4_rlim_t) blim.rlim_max;
15043412Snewton	else
15143412Snewton		slim.rlim_max = SVR4_RLIM_SAVED_MAX;
15243412Snewton
15343412Snewton	if (blim.rlim_cur == RLIM_INFINITY)
15443412Snewton		slim.rlim_cur = SVR4_RLIM_INFINITY;
15543412Snewton	else if (OKLIMIT(blim.rlim_cur))
15643412Snewton		slim.rlim_cur = (svr4_rlim_t) blim.rlim_cur;
15743412Snewton	else if (blim.rlim_max == blim.rlim_cur)
15843412Snewton		slim.rlim_cur = SVR4_RLIM_SAVED_MAX;
15943412Snewton	else
16043412Snewton		slim.rlim_cur = SVR4_RLIM_SAVED_CUR;
16143412Snewton
162107849Salfred	return copyout(&slim, uap->rlp, sizeof(*uap->rlp));
16343412Snewton}
16443412Snewton
16543412Snewton
16643412Snewtonint
16783366Sjuliansvr4_sys_setrlimit(td, uap)
168193014Sdelphij	struct thread *td;
16943412Snewton	struct svr4_sys_setrlimit_args *uap;
17043412Snewton{
171107849Salfred	int rl = svr4_to_native_rl(uap->which);
172125454Sjhb	struct rlimit blim, curlim;
17343412Snewton	struct svr4_rlimit slim;
17443412Snewton	int error;
17543412Snewton
17643412Snewton	if (rl == -1)
17743412Snewton		return EINVAL;
17843412Snewton
179107849Salfred	if ((error = copyin(uap->rlp, &slim, sizeof(slim))) != 0)
18043412Snewton		return error;
18143412Snewton
182284215Smjg	lim_rlimit(td, rl, &curlim);
183125454Sjhb
18443412Snewton	/*
18543412Snewton	 * if the limit is SVR4_RLIM_INFINITY, then we set it to our
18643412Snewton	 * unlimited.
18743412Snewton	 * We should also: If it is SVR4_RLIM_SAVED_MAX, we should set the
18843412Snewton	 * new limit to the corresponding saved hard limit, and if
18943412Snewton	 * it is equal to SVR4_RLIM_SAVED_CUR, we should set it to the
19043412Snewton	 * corresponding saved soft limit.
19143412Snewton	 *
19243412Snewton	 */
19343412Snewton	if (slim.rlim_max == SVR4_RLIM_INFINITY)
19443412Snewton		blim.rlim_max = RLIM_INFINITY;
19543412Snewton	else if (OKLIMIT(slim.rlim_max))
19643412Snewton		blim.rlim_max = (rlim_t) slim.rlim_max;
19743412Snewton	else if (slim.rlim_max == SVR4_RLIM_SAVED_MAX)
198125454Sjhb		blim.rlim_max = curlim.rlim_max;
19943412Snewton	else if (slim.rlim_max == SVR4_RLIM_SAVED_CUR)
200125454Sjhb		blim.rlim_max = curlim.rlim_cur;
20143412Snewton
20243412Snewton	if (slim.rlim_cur == SVR4_RLIM_INFINITY)
20343412Snewton		blim.rlim_cur = RLIM_INFINITY;
20443412Snewton	else if (OKLIMIT(slim.rlim_cur))
20543412Snewton		blim.rlim_cur = (rlim_t) slim.rlim_cur;
20643412Snewton	else if (slim.rlim_cur == SVR4_RLIM_SAVED_MAX)
207125454Sjhb		blim.rlim_cur = curlim.rlim_max;
20843412Snewton	else if (slim.rlim_cur == SVR4_RLIM_SAVED_CUR)
209125454Sjhb		blim.rlim_cur = curlim.rlim_cur;
21043412Snewton
211125454Sjhb	return (kern_setrlimit(td, rl, &blim));
21243412Snewton}
21343412Snewton
21443412Snewton
21543412Snewtonint
21683366Sjuliansvr4_sys_getrlimit64(td, uap)
217193014Sdelphij	struct thread *td;
21843412Snewton	struct svr4_sys_getrlimit64_args *uap;
21943412Snewton{
220107849Salfred	int rl = svr4_to_native_rl(uap->which);
22143412Snewton	struct rlimit blim;
22243412Snewton	struct svr4_rlimit64 slim;
22343412Snewton
22443412Snewton	if (rl == -1)
22543412Snewton		return EINVAL;
22643412Snewton
227284215Smjg	lim_rlimit(td, rl, &blim);
22843412Snewton
22943412Snewton	/*
23043412Snewton	 * Our infinity, is their maxfiles.
23143412Snewton	 */
23243412Snewton	if (rl == RLIMIT_NOFILE && blim.rlim_max == RLIM_INFINITY)
23343412Snewton		blim.rlim_max = maxfiles;
23443412Snewton
23543412Snewton	/*
23643412Snewton	 * If the limit can be be represented, it is returned.
23743412Snewton	 * Otherwise, if rlim_cur == rlim_max, return SVR4_RLIM_SAVED_MAX
23843412Snewton	 * else return SVR4_RLIM_SAVED_CUR
23943412Snewton	 */
24043412Snewton	if (blim.rlim_max == RLIM_INFINITY)
24143412Snewton		slim.rlim_max = SVR4_RLIM64_INFINITY;
24243412Snewton	else if (OKLIMIT64(blim.rlim_max))
24343412Snewton		slim.rlim_max = (svr4_rlim64_t) blim.rlim_max;
24443412Snewton	else
24543412Snewton		slim.rlim_max = SVR4_RLIM64_SAVED_MAX;
24643412Snewton
24743412Snewton	if (blim.rlim_cur == RLIM_INFINITY)
24843412Snewton		slim.rlim_cur = SVR4_RLIM64_INFINITY;
24943412Snewton	else if (OKLIMIT64(blim.rlim_cur))
25043412Snewton		slim.rlim_cur = (svr4_rlim64_t) blim.rlim_cur;
25143412Snewton	else if (blim.rlim_max == blim.rlim_cur)
25243412Snewton		slim.rlim_cur = SVR4_RLIM64_SAVED_MAX;
25343412Snewton	else
25443412Snewton		slim.rlim_cur = SVR4_RLIM64_SAVED_CUR;
25543412Snewton
256107849Salfred	return copyout(&slim, uap->rlp, sizeof(*uap->rlp));
25743412Snewton}
25843412Snewton
25943412Snewton
26043412Snewtonint
26183366Sjuliansvr4_sys_setrlimit64(td, uap)
262193014Sdelphij	struct thread *td;
26343412Snewton	struct svr4_sys_setrlimit64_args *uap;
26443412Snewton{
265107849Salfred	int rl = svr4_to_native_rl(uap->which);
266125454Sjhb	struct rlimit blim, curlim;
26743412Snewton	struct svr4_rlimit64 slim;
26843412Snewton	int error;
26943412Snewton
27043412Snewton	if (rl == -1)
27143412Snewton		return EINVAL;
27243412Snewton
273107849Salfred	if ((error = copyin(uap->rlp, &slim, sizeof(slim))) != 0)
27443412Snewton		return error;
27543412Snewton
276284215Smjg	lim_rlimit(td, rl, &curlim);
277125454Sjhb
27843412Snewton	/*
27943412Snewton	 * if the limit is SVR4_RLIM64_INFINITY, then we set it to our
28043412Snewton	 * unlimited.
28143412Snewton	 * We should also: If it is SVR4_RLIM64_SAVED_MAX, we should set the
28243412Snewton	 * new limit to the corresponding saved hard limit, and if
28343412Snewton	 * it is equal to SVR4_RLIM64_SAVED_CUR, we should set it to the
28443412Snewton	 * corresponding saved soft limit.
28543412Snewton	 *
28643412Snewton	 */
28743412Snewton	if (slim.rlim_max == SVR4_RLIM64_INFINITY)
28843412Snewton		blim.rlim_max = RLIM_INFINITY;
28943412Snewton	else if (OKLIMIT64(slim.rlim_max))
29043412Snewton		blim.rlim_max = (rlim_t) slim.rlim_max;
29143412Snewton	else if (slim.rlim_max == SVR4_RLIM64_SAVED_MAX)
292125454Sjhb		blim.rlim_max = curlim.rlim_max;
29343412Snewton	else if (slim.rlim_max == SVR4_RLIM64_SAVED_CUR)
294125454Sjhb		blim.rlim_max = curlim.rlim_cur;
29543412Snewton
29643412Snewton	if (slim.rlim_cur == SVR4_RLIM64_INFINITY)
29743412Snewton		blim.rlim_cur = RLIM_INFINITY;
29843412Snewton	else if (OKLIMIT64(slim.rlim_cur))
29943412Snewton		blim.rlim_cur = (rlim_t) slim.rlim_cur;
30043412Snewton	else if (slim.rlim_cur == SVR4_RLIM64_SAVED_MAX)
301125454Sjhb		blim.rlim_cur = curlim.rlim_max;
30243412Snewton	else if (slim.rlim_cur == SVR4_RLIM64_SAVED_CUR)
303125454Sjhb		blim.rlim_cur = curlim.rlim_cur;
30443412Snewton
305125454Sjhb	return (kern_setrlimit(td, rl, &blim));
30643412Snewton}
307