diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,7 @@ #include #include #include +#include static MALLOC_DEFINE(M_PLIMIT, "plimit", "plimit structures"); static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures"); @@ -804,6 +806,119 @@ return (error); } +static int +getrlimitusage_one(struct proc *p, u_int which, int flags, rlim_t *res) +{ + struct thread *td; + struct uidinfo *ui; + struct vmspace *vm; + uid_t uid; + int error; + + error = 0; + PROC_LOCK(p); + uid = (flags & GETRLIMITUSAGE_EUID) == 0 ? p->p_ucred->cr_ruid : + p->p_ucred->cr_uid; + PROC_UNLOCK(p); + + ui = uifind(uid); + vm = vmspace_acquire_ref(p); + + switch (which) { + case RLIMIT_CPU: + PROC_LOCK(p); + PROC_STATLOCK(p); + FOREACH_THREAD_IN_PROC(p, td) + ruxagg(p, td); + *res = p->p_rux.rux_runtime; + PROC_STATUNLOCK(p); + PROC_UNLOCK(p); + *res /= cpu_tickrate(); + break; + case RLIMIT_FSIZE: + error = ENXIO; + break; + case RLIMIT_DATA: + if (vm == NULL) + error = ENXIO; + else + *res = vm->vm_dsize * PAGE_SIZE; + break; + case RLIMIT_STACK: + if (vm == NULL) + error = ENXIO; + else + *res = vm->vm_ssize * PAGE_SIZE; + break; + case RLIMIT_CORE: + error = ENXIO; + break; + case RLIMIT_RSS: + if (vm == NULL) + error = ENXIO; + else + *res = vmspace_resident_count(vm) * PAGE_SIZE; + break; + case RLIMIT_MEMLOCK: + if (vm == NULL) + error = ENXIO; + else + *res = pmap_wired_count(vmspace_pmap(vm)) * PAGE_SIZE; + break; + case RLIMIT_NPROC: + *res = ui->ui_proccnt; + break; + case RLIMIT_NOFILE: + *res = proc_nfiles(p); + break; + case RLIMIT_SBSIZE: + *res = ui->ui_sbsize; + break; + case RLIMIT_VMEM: + if (vm == NULL) + error = ENXIO; + else + *res = vm->vm_map.size; + break; + case RLIMIT_NPTS: + *res = ui->ui_ptscnt; + break; + case RLIMIT_SWAP: + *res = ui->ui_vmsize; + break; + case RLIMIT_KQUEUES: + *res = ui->ui_kqcnt; + break; + case RLIMIT_UMTXP: + *res = ui->ui_umtxcnt; + break; + case RLIMIT_PIPEBUF: + *res = ui->ui_pipecnt; + break; + default: + error = EINVAL; + break; + } + + vmspace_free(vm); + uifree(ui); + return (error); +} + +int +sys_getrlimitusage(struct thread *td, struct getrlimitusage_args *uap) +{ + rlim_t res; + int error; + + if ((uap->flags & ~(GETRLIMITUSAGE_EUID)) != 0) + return (EINVAL); + error = getrlimitusage_one(curproc, uap->which, uap->flags, &res); + if (error == 0) + error = copyout(&res, uap->res, sizeof(res)); + return (error); +} + /* * Transform the running time and tick information for children of proc p * into user and system time usage. diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -3333,5 +3333,12 @@ uintptr_t idx2 ); } +589 AUE_NULL STD|CAPENABLED { + int getrlimitusage( + u_int which, + int flags, + _Out_ rlim_t *res + ); + } ; vim: syntax=off diff --git a/sys/sys/resource.h b/sys/sys/resource.h --- a/sys/sys/resource.h +++ b/sys/sys/resource.h @@ -171,6 +171,9 @@ #define CP_IDLE 4 #define CPUSTATES 5 +/* getrlimitusage flags */ +#define GETRLIMITUSAGE_EUID 0x0001 + #endif /* __BSD_VISIBLE */ #ifdef _KERNEL