diff options
author | dchagin <dchagin@FreeBSD.org> | 2016-04-10 07:11:29 +0000 |
---|---|---|
committer | dchagin <dchagin@FreeBSD.org> | 2016-04-10 07:11:29 +0000 |
commit | aac70308f6035bbde1587853967f26e436371d63 (patch) | |
tree | b2231df5458fe0107d803a4827d24d122a72e3f4 | |
parent | f04f5692d14c5ca5d0ca7d4c875c6e1eca28c5d4 (diff) | |
download | FreeBSD-src-aac70308f6035bbde1587853967f26e436371d63.zip FreeBSD-src-aac70308f6035bbde1587853967f26e436371d63.tar.gz |
More complete implementation of /proc/self/limits.
Fix the way the code accesses process limits struct - pointed out by mjg@.
PR: 207386
Reviewed by: no objection form des@
MFC after: 3 weeks
-rw-r--r-- | sys/compat/linprocfs/linprocfs.c | 111 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.h | 7 |
2 files changed, 76 insertions, 42 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 86c4b05..12bc3c46a 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -1370,65 +1370,92 @@ linprocfs_dofdescfs(PFS_FILL_ARGS) /* * Filler function for proc/pid/limits */ - -#define RLIM_NONE -1 - -static const struct limit_info { +static const struct linux_rlimit_ident { const char *desc; const char *unit; - unsigned long long rlim_id; -} limits_info[] = { - { "Max cpu time", "seconds", RLIMIT_CPU }, - { "Max file size", "bytes", RLIMIT_FSIZE }, - { "Max data size", "bytes", RLIMIT_DATA }, - { "Max stack size", "bytes", RLIMIT_STACK }, - { "Max core file size", "bytes", RLIMIT_CORE }, - { "Max resident set", "bytes", RLIMIT_RSS }, - { "Max processes", "processes", RLIMIT_NPROC }, - { "Max open files", "files", RLIMIT_NOFILE }, - { "Max locked memory", "bytes", RLIMIT_MEMLOCK }, - { "Max address space", "bytes", RLIMIT_AS }, - { "Max file locks", "locks", RLIM_INFINITY }, - { "Max pending signals", "signals", RLIM_INFINITY }, - { "Max msgqueue size", "bytes", RLIM_NONE }, - { "Max nice priority", "", RLIM_NONE }, - { "Max realtime priority", "", RLIM_NONE }, - { "Max realtime timeout", "us", RLIM_INFINITY }, + unsigned int rlim_id; +} linux_rlimits_ident[] = { + { "Max cpu time", "seconds", RLIMIT_CPU }, + { "Max file size", "bytes", RLIMIT_FSIZE }, + { "Max data size", "bytes", RLIMIT_DATA }, + { "Max stack size", "bytes", RLIMIT_STACK }, + { "Max core file size", "bytes", RLIMIT_CORE }, + { "Max resident set", "bytes", RLIMIT_RSS }, + { "Max processes", "processes", RLIMIT_NPROC }, + { "Max open files", "files", RLIMIT_NOFILE }, + { "Max locked memory", "bytes", RLIMIT_MEMLOCK }, + { "Max address space", "bytes", RLIMIT_AS }, + { "Max file locks", "locks", LINUX_RLIMIT_LOCKS }, + { "Max pending signals", "signals", LINUX_RLIMIT_SIGPENDING }, + { "Max msgqueue size", "bytes", LINUX_RLIMIT_MSGQUEUE }, + { "Max nice priority", "", LINUX_RLIMIT_NICE }, + { "Max realtime priority", "", LINUX_RLIMIT_RTPRIO }, + { "Max realtime timeout", "us", LINUX_RLIMIT_RTTIME }, { 0, 0, 0 } }; static int linprocfs_doproclimits(PFS_FILL_ARGS) { - const struct limit_info *li; - struct rlimit li_rlimits; - struct plimit *cur_proc_lim; + const struct linux_rlimit_ident *li; + struct plimit *limp; + struct rlimit rl; + ssize_t size; + int res, error; - cur_proc_lim = lim_alloc(); - lim_copy(cur_proc_lim, p->p_limit); - sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n", "Limit", "Soft Limit", + PROC_LOCK(p); + limp = lim_hold(p->p_limit); + PROC_UNLOCK(p); + size = sizeof(res); + sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit", "Hard Limit", "Units"); - for (li = limits_info; li->desc != NULL; ++li) { - if (li->rlim_id != RLIM_INFINITY && li->rlim_id != RLIM_NONE) - li_rlimits = cur_proc_lim->pl_rlimit[li->rlim_id]; - else { - li_rlimits.rlim_cur = 0; - li_rlimits.rlim_max = 0; + for (li = linux_rlimits_ident; li->desc != NULL; ++li) { + switch (li->rlim_id) + { + case LINUX_RLIMIT_LOCKS: + /* FALLTHROUGH */ + case LINUX_RLIMIT_RTTIME: + rl.rlim_cur = RLIM_INFINITY; + break; + case LINUX_RLIMIT_SIGPENDING: + error = kernel_sysctlbyname(td, + "kern.sigqueue.max_pending_per_proc", + &res, &size, 0, 0, 0, 0); + if (error != 0) + break; + rl.rlim_cur = res; + rl.rlim_max = res; + break; + case LINUX_RLIMIT_MSGQUEUE: + error = kernel_sysctlbyname(td, + "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0); + if (error != 0) + break; + rl.rlim_cur = res; + rl.rlim_max = res; + break; + case LINUX_RLIMIT_NICE: + /* FALLTHROUGH */ + case LINUX_RLIMIT_RTPRIO: + rl.rlim_cur = 0; + rl.rlim_max = 0; + break; + default: + rl = limp->pl_rlimit[li->rlim_id]; + break; } - if (li->rlim_id == RLIM_INFINITY || - li_rlimits.rlim_cur == RLIM_INFINITY) + if (rl.rlim_cur == RLIM_INFINITY) sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n", li->desc, "unlimited", "unlimited", li->unit); else - sbuf_printf(sb, "%-26s%-21ld%-21ld%-10s\n", - li->desc, (long)li_rlimits.rlim_cur, - (long)li_rlimits.rlim_max, li->unit); + sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n", + li->desc, (unsigned long long)rl.rlim_cur, + (unsigned long long)rl.rlim_max, li->unit); } - lim_free(cur_proc_lim); - return (0); + lim_free(limp); + return (error); } - /* * Filler function for proc/sys/kernel/random/uuid */ diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h index 08bc85f..0d2d86c 100644 --- a/sys/compat/linux/linux_misc.h +++ b/sys/compat/linux/linux_misc.h @@ -143,6 +143,13 @@ extern int stclohz; #define LINUX_P_PID 1 #define LINUX_P_PGID 2 +#define LINUX_RLIMIT_LOCKS RLIM_NLIMITS + 1 +#define LINUX_RLIMIT_SIGPENDING RLIM_NLIMITS + 2 +#define LINUX_RLIMIT_MSGQUEUE RLIM_NLIMITS + 3 +#define LINUX_RLIMIT_NICE RLIM_NLIMITS + 4 +#define LINUX_RLIMIT_RTPRIO RLIM_NLIMITS + 5 +#define LINUX_RLIMIT_RTTIME RLIM_NLIMITS + 6 + #define LINUX_RLIM_INFINITY (~0UL) int linux_common_wait(struct thread *td, int pid, int *status, |