#include <sys/types.h>
#include <sys/cmn_err.h>
#include <sys/sysmacros.h>
#include <sys/proc.h>
#include <sys/rctl.h>
#include <sys/rctl_impl.h>
#include <sys/port_kernel.h>
#include <sys/signal.h>
#include <sys/var.h>
#include <sys/vmparam.h>
#include <sys/machparam.h>
rctl_hndl_t rctlproc_legacy[RLIM_NLIMITS];
uint_t rctlproc_flags[RLIM_NLIMITS] = {
RCTL_LOCAL_SIGNAL,
RCTL_LOCAL_DENY | RCTL_LOCAL_SIGNAL,
RCTL_LOCAL_DENY,
RCTL_LOCAL_DENY,
RCTL_LOCAL_DENY,
RCTL_LOCAL_DENY,
RCTL_LOCAL_DENY
};
int rctlproc_signals[RLIM_NLIMITS] = {
SIGXCPU,
SIGXFSZ,
0, 0, 0, 0, 0
};
rctl_hndl_t rc_process_msgmnb;
rctl_hndl_t rc_process_msgtql;
rctl_hndl_t rc_process_semmsl;
rctl_hndl_t rc_process_semopm;
rctl_hndl_t rc_process_portev;
rctl_hndl_t rc_process_sigqueue;
static int
proc_cpu_time_test(struct rctl *rctl, struct proc *p, rctl_entity_p_t *e,
rctl_val_t *rval, rctl_qty_t inc, uint_t flags)
{
return (inc >= rval->rcv_value);
}
static rctl_ops_t proc_cpu_time_ops = {
rcop_no_action,
rcop_no_usage,
rcop_no_set,
proc_cpu_time_test
};
static int
proc_filesize_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e,
rctl_qty_t nv)
{
if (p->p_model == DATAMODEL_NATIVE)
nv = MIN(nv, rctl->rc_dict_entry->rcd_max_native);
else
nv = MIN(nv, rctl->rc_dict_entry->rcd_max_ilp32);
ASSERT(e->rcep_t == RCENTITY_PROCESS);
e->rcep_p.proc->p_fsz_ctl = nv;
return (0);
}
static rctl_ops_t proc_filesize_ops = {
rcop_no_action,
rcop_no_usage,
proc_filesize_set,
rcop_no_test
};
static int
proc_stack_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e,
rctl_qty_t nv)
{
klwp_t *lwp = ttolwp(curthread);
if (p->p_model == DATAMODEL_NATIVE)
nv = MIN(nv, rctl->rc_dict_entry->rcd_max_native);
else
nv = MIN(nv, rctl->rc_dict_entry->rcd_max_ilp32);
ASSERT(e->rcep_t == RCENTITY_PROCESS);
if (lwp != NULL && lwp->lwp_procp == e->rcep_p.proc &&
lwp->lwp_ustack && lwp->lwp_old_stk_ctl == 0) {
lwp->lwp_old_stk_ctl = (size_t)e->rcep_p.proc->p_stk_ctl;
curthread->t_post_sys = 1;
}
e->rcep_p.proc->p_stk_ctl = nv;
return (0);
}
static rctl_ops_t proc_stack_ops = {
rcop_no_action,
rcop_no_usage,
proc_stack_set,
rcop_no_test
};
static int
proc_nofile_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e, rctl_qty_t nv)
{
ASSERT(e->rcep_t == RCENTITY_PROCESS);
if (p->p_model == DATAMODEL_NATIVE)
nv = MIN(nv, rctl->rc_dict_entry->rcd_max_native);
else
nv = MIN(nv, rctl->rc_dict_entry->rcd_max_ilp32);
e->rcep_p.proc->p_fno_ctl = nv;
return (0);
}
static rctl_ops_t proc_nofile_ops = {
rcop_no_action,
rcop_no_usage,
proc_nofile_set,
rcop_absolute_test
};
static int
proc_vmem_set(rctl_t *rctl, struct proc *p, rctl_entity_p_t *e, rctl_qty_t nv)
{
ASSERT(e->rcep_t == RCENTITY_PROCESS);
if (p->p_model == DATAMODEL_ILP32)
nv = MIN(nv, rctl->rc_dict_entry->rcd_max_ilp32);
else
nv = MIN(nv, rctl->rc_dict_entry->rcd_max_native);
e->rcep_p.proc->p_vmem_ctl = nv;
return (0);
}
static rctl_ops_t proc_vmem_ops = {
rcop_no_action,
rcop_no_usage,
proc_vmem_set,
rcop_no_test
};
void
rctlproc_default_init(struct proc *initp, rctl_alloc_gp_t *gp)
{
struct rlimit64 rlp64;
rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
(void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_CPU], initp, &rlp64, gp,
RCTL_LOCAL_SIGNAL, SIGXCPU, kcred);
rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
(void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_FSIZE], initp, &rlp64, gp,
RCTL_LOCAL_SIGNAL | RCTL_LOCAL_DENY, SIGXFSZ, kcred);
rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
(void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_DATA], initp, &rlp64, gp,
RCTL_LOCAL_DENY, 0, kcred);
#ifdef __sparc
rlp64.rlim_cur = DFLSSIZ;
rlp64.rlim_max = LONG_MAX;
#else
rlp64.rlim_cur = DFLSSIZ;
rlp64.rlim_max = MAXSSIZ;
#endif
(void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_STACK], initp, &rlp64, gp,
RCTL_LOCAL_DENY, 0, kcred);
rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
(void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_CORE], initp, &rlp64, gp,
RCTL_LOCAL_DENY, 0, kcred);
rlp64.rlim_cur = rlim_fd_cur;
rlp64.rlim_max = rlim_fd_max;
(void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_NOFILE], initp, &rlp64,
gp, RCTL_LOCAL_DENY, 0, kcred);
rlp64.rlim_cur = rlp64.rlim_max = RLIM64_INFINITY;
(void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_VMEM], initp, &rlp64, gp,
RCTL_LOCAL_DENY, 0, kcred);
}
void
rctlproc_init(void)
{
rctl_set_t *set;
rctl_alloc_gp_t *gp;
rctl_entity_p_t e;
rctlproc_legacy[RLIMIT_CPU] = rctl_register("process.max-cpu-time",
RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_NEVER |
RCTL_GLOBAL_CPU_TIME | RCTL_GLOBAL_INFINITE | RCTL_GLOBAL_SECONDS,
UINT64_MAX, UINT64_MAX, &proc_cpu_time_ops);
rctlproc_legacy[RLIMIT_FSIZE] = rctl_register("process.max-file-size",
RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_FILE_SIZE | RCTL_GLOBAL_BYTES,
MAXOFFSET_T, MAXOFFSET_T, &proc_filesize_ops);
rctlproc_legacy[RLIMIT_DATA] = rctl_register("process.max-data-size",
RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
ULONG_MAX, UINT32_MAX, &rctl_default_ops);
#ifdef _LP64
#ifdef __sparc
rctlproc_legacy[RLIMIT_STACK] = rctl_register("process.max-stack-size",
RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
LONG_MAX, INT32_MAX, &proc_stack_ops);
#else
rctlproc_legacy[RLIMIT_STACK] = rctl_register("process.max-stack-size",
RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
MAXSSIZ, USRSTACK32 - PAGESIZE, &proc_stack_ops);
#endif
#else
rctlproc_legacy[RLIMIT_STACK] = rctl_register("process.max-stack-size",
RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
USRSTACK - PAGESIZE, USRSTACK - PAGESIZE, &proc_stack_ops);
#endif
rctlproc_legacy[RLIMIT_CORE] = rctl_register("process.max-core-size",
RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
MIN(MAXOFFSET_T, ULONG_MAX), UINT32_MAX, &rctl_default_ops);
rctlproc_legacy[RLIMIT_NOFILE] = rctl_register(
"process.max-file-descriptor", RCENTITY_PROCESS,
RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_COUNT, INT32_MAX, INT32_MAX, &proc_nofile_ops);
rctlproc_legacy[RLIMIT_VMEM] =
rctl_register("process.max-address-space", RCENTITY_PROCESS,
RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_SIGNAL_NEVER | RCTL_GLOBAL_BYTES,
ULONG_MAX, UINT32_MAX, &proc_vmem_ops);
rc_process_semmsl = rctl_register("process.max-sem-nsems",
RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_COUNT,
SHRT_MAX, SHRT_MAX, &rctl_absolute_ops);
rctl_add_legacy_limit("process.max-sem-nsems", "semsys",
"seminfo_semmsl", 512, SHRT_MAX);
rc_process_semopm = rctl_register("process.max-sem-ops",
RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_COUNT,
INT_MAX, INT_MAX, &rctl_absolute_ops);
rctl_add_legacy_limit("process.max-sem-ops", "semsys",
"seminfo_semopm", 512, INT_MAX);
rc_process_msgmnb = rctl_register("process.max-msg-qbytes",
RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_BYTES,
ULONG_MAX, ULONG_MAX, &rctl_absolute_ops);
rctl_add_legacy_limit("process.max-msg-qbytes", "msgsys",
"msginfo_msgmnb", 65536, ULONG_MAX);
rc_process_msgtql = rctl_register("process.max-msg-messages",
RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_COUNT,
UINT_MAX, UINT_MAX, &rctl_absolute_ops);
rctl_add_legacy_limit("process.max-msg-messages", "msgsys",
"msginfo_msgtql", 8192, UINT_MAX);
rc_process_portev = rctl_register("process.max-port-events",
RCENTITY_PROCESS, RCTL_GLOBAL_DENY_ALWAYS | RCTL_GLOBAL_COUNT,
PORT_MAX_EVENTS, PORT_MAX_EVENTS, &rctl_absolute_ops);
rctl_add_default_limit("process.max-port-events", PORT_DEFAULT_EVENTS,
RCPRIV_PRIVILEGED, RCTL_LOCAL_DENY);
rc_process_sigqueue = rctl_register("process.max-sigqueue-size",
RCENTITY_PROCESS, RCTL_GLOBAL_LOWERABLE | RCTL_GLOBAL_DENY_ALWAYS |
RCTL_GLOBAL_COUNT, MAX(v.v_maxup, 8192), MAX(v.v_maxup, 8192),
&rctl_absolute_ops);
rctl_add_default_limit("process.max-sigqueue-size",
_SIGQUEUE_SIZE_BASIC, RCPRIV_BASIC, RCTL_LOCAL_DENY);
rctl_add_default_limit("process.max-sigqueue-size",
_SIGQUEUE_SIZE_PRIVILEGED, RCPRIV_PRIVILEGED, RCTL_LOCAL_DENY);
set = rctl_set_create();
gp = rctl_set_init_prealloc(RCENTITY_PROCESS);
mutex_enter(&curproc->p_lock);
e.rcep_p.proc = curproc;
e.rcep_t = RCENTITY_PROCESS;
curproc->p_rctls = rctl_set_init(RCENTITY_PROCESS, curproc, &e,
set, gp);
mutex_exit(&curproc->p_lock);
rctl_prealloc_destroy(gp);
}