diff options
author | Alex Wilson <alex.wilson@joyent.com> | 2015-08-17 16:26:13 -0700 |
---|---|---|
committer | Alex Wilson <alex.wilson@joyent.com> | 2015-08-18 09:24:08 -0700 |
commit | abaee2673042ff817f068c8401f34b8316e8962c (patch) | |
tree | 2b227500369f4cc934ca6db40b3aa1642ffbfd00 /usr | |
parent | 29170abe7b69701c0f95839235131541fd3fb2e5 (diff) | |
download | illumos-joyent-abaee2673042ff817f068c8401f34b8316e8962c.tar.gz |
OS-3916 lxbrand support /proc/sys/kernel/core_pattern
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Diffstat (limited to 'usr')
-rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_proc.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_prsubr.c | 113 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_prvnops.c | 106 |
3 files changed, 223 insertions, 0 deletions
diff --git a/usr/src/uts/common/brand/lx/procfs/lx_proc.h b/usr/src/uts/common/brand/lx/procfs/lx_proc.h index 4822ef1c0c..27e03b54b2 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_proc.h +++ b/usr/src/uts/common/brand/lx/procfs/lx_proc.h @@ -198,6 +198,7 @@ typedef enum lxpr_nodetype { LXPR_SYS_FS_INOTIFY_MAX_USER_WATCHES, /* inotify/max_user_watches */ LXPR_SYS_KERNELDIR, /* /proc/sys/kernel/ */ LXPR_SYS_KERNEL_CAPLCAP, /* /proc/sys/kernel/cap_last_cap */ + LXPR_SYS_KERNEL_COREPATT, /* /proc/sys/kernel/core_pattern */ LXPR_SYS_KERNEL_HOSTNAME, /* /proc/sys/kernel/hostname */ LXPR_SYS_KERNEL_MSGMNI, /* /proc/sys/kernel/msgmni */ LXPR_SYS_KERNEL_NGROUPS_MAX, /* /proc/sys/kernel/ngroups_max */ @@ -302,6 +303,9 @@ extern void lxpr_uiobuf_write(lxpr_uiobuf_t *, const char *, size_t); extern void lxpr_uiobuf_printf(lxpr_uiobuf_t *, const char *, ...); extern void lxpr_uiobuf_seterr(lxpr_uiobuf_t *, int); +extern void lxpr_core_path_l2s(const char *, char *); +extern void lxpr_core_path_s2l(const char *, char *); + proc_t *lxpr_lock(pid_t); void lxpr_unlock(proc_t *); diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prsubr.c b/usr/src/uts/common/brand/lx/procfs/lx_prsubr.c index f7e4998229..75c70a8261 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_prsubr.c +++ b/usr/src/uts/common/brand/lx/procfs/lx_prsubr.c @@ -529,6 +529,7 @@ lxpr_getnode(vnode_t *dp, lxpr_nodetype_t type, proc_t *p, int desc) case LXPR_PID_OOM_SCR_ADJ: case LXPR_PID_TID_OOM_SCR_ADJ: + case LXPR_SYS_KERNEL_COREPATT: case LXPR_SYS_NET_CORE_SOMAXCON: case LXPR_SYS_VM_OVERCOMMIT_MEM: case LXPR_SYS_VM_SWAPPINESS: @@ -572,3 +573,115 @@ lxpr_freenode(lxpr_node_t *lxpnp) */ kmem_cache_free(lxpr_node_cache, lxpnp); } + +/* + * Translate a Linux core_pattern path to a native Illumos one, by replacing + * the appropriate % escape sequences. + * + * Any % escape sequences that are not recognised are double-escaped so that + * they will be inserted literally into the path (to mimic Linux). + */ +void +lxpr_core_path_l2s(const char *inp, char *outp) +{ + int i = 0, j = 0; + char x; + + while (i < MAXPATHLEN && j < MAXPATHLEN - 1) { + x = inp[i++]; + if (x == '\0') + break; + if (x != '%') { + outp[j++] = x; + continue; + } + + x = inp[i++]; + switch (x) { + case 'E': + outp[j++] = '%'; + outp[j++] = 'd'; + outp[j++] = '%'; + outp[j++] = 'f'; + break; + case 'e': + outp[j++] = '%'; + outp[j++] = 'f'; + break; + case 'p': + case 'g': + case 'u': + case 't': + case '%': + outp[j++] = '%'; + outp[j++] = x; + break; + case 'h': + outp[j++] = '%'; + outp[j++] = 'n'; + break; + default: + /* No translation, make it literal. */ + outp[j++] = '%'; + outp[j++] = '%'; + outp[j++] = x; + break; + } + } + + outp[j] = '\0'; +} + +/* + * Translate an Illumos core pattern path back to Linux format. + */ +void +lxpr_core_path_s2l(const char *inp, char *outp) +{ + int i = 0, j = 0; + char x; + + while (i < MAXPATHLEN && j < MAXPATHLEN - 1) { + x = inp[i++]; + if (x == '\0') + break; + if (x != '%') { + outp[j++] = x; + continue; + } + + x = inp[i++]; + switch (x) { + case 'd': + /* No Linux equivalent unless it's %d%f. */ + if (inp[i] == '%' && inp[i + 1] == 'f') { + i += 2; + outp[j++] = '%'; + outp[j++] = 'E'; + } + break; + case 'f': + outp[j++] = '%'; + outp[j++] = 'e'; + break; + case 'p': + case 'P': + case 'g': + case 'u': + case 't': + case '%': + outp[j++] = '%'; + outp[j++] = (x == 'P' ? 'p' : x); + break; + case 'n': + outp[j++] = '%'; + outp[j++] = 'h'; + break; + default: + /* No translation. */ + break; + } + } + + outp[j] = '\0'; +} diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c index 870884cc49..b574992967 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c +++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c @@ -65,6 +65,7 @@ #include <sys/brand.h> #include <sys/cred_impl.h> #include <sys/tihdr.h> +#include <sys/corectl.h> #include <inet/ip.h> #include <inet/ip_ire.h> #include <inet/ip6.h> @@ -210,6 +211,7 @@ static void lxpr_read_sys_fs_inotify_max_user_instances(lxpr_node_t *, static void lxpr_read_sys_fs_inotify_max_user_watches(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_caplcap(lxpr_node_t *, lxpr_uiobuf_t *); +static void lxpr_read_sys_kernel_corepatt(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_hostname(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_msgmni(lxpr_node_t *, lxpr_uiobuf_t *); static void lxpr_read_sys_kernel_ngroups_max(lxpr_node_t *, lxpr_uiobuf_t *); @@ -226,6 +228,8 @@ static void lxpr_read_sys_vm_swappiness(lxpr_node_t *, lxpr_uiobuf_t *); static int lxpr_write_sys_net_core_somaxc(lxpr_node_t *, uio_t *, cred_t *, caller_context_t *); +static int lxpr_write_sys_kernel_corepatt(lxpr_node_t *, uio_t *, cred_t *, + caller_context_t *); /* * Simple conversion @@ -452,6 +456,7 @@ static lxpr_dirent_t sys_fs_inotifydir[] = { */ static lxpr_dirent_t sys_kerneldir[] = { { LXPR_SYS_KERNEL_CAPLCAP, "cap_last_cap" }, + { LXPR_SYS_KERNEL_COREPATT, "core_pattern" }, { LXPR_SYS_KERNEL_HOSTNAME, "hostname" }, { LXPR_SYS_KERNEL_MSGMNI, "msgmni" }, { LXPR_SYS_KERNEL_NGROUPS_MAX, "ngroups_max" }, @@ -521,6 +526,7 @@ lxpr_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) switch (type) { case LXPR_PID_OOM_SCR_ADJ: case LXPR_PID_TID_OOM_SCR_ADJ: + case LXPR_SYS_KERNEL_COREPATT: case LXPR_SYS_NET_CORE_SOMAXCON: case LXPR_SYS_VM_OVERCOMMIT_MEM: case LXPR_SYS_VM_SWAPPINESS: @@ -685,6 +691,7 @@ static void (*lxpr_read_function[LXPR_NFILES])() = { lxpr_read_sys_fs_inotify_max_user_watches, /* max_user_watches */ lxpr_read_invalid, /* /proc/sys/kernel */ lxpr_read_sys_kernel_caplcap, /* /proc/sys/kernel/cap_last_cap */ + lxpr_read_sys_kernel_corepatt, /* /proc/sys/kernel/core_pattern */ lxpr_read_sys_kernel_hostname, /* /proc/sys/kernel/hostname */ lxpr_read_sys_kernel_msgmni, /* /proc/sys/kernel/msgmni */ lxpr_read_sys_kernel_ngroups_max, /* /proc/sys/kernel/ngroups_max */ @@ -802,6 +809,7 @@ static vnode_t *(*lxpr_lookup_function[LXPR_NFILES])() = { lxpr_lookup_not_a_dir, /* .../inotify/max_user_watches */ lxpr_lookup_sys_kerneldir, /* /proc/sys/kernel */ lxpr_lookup_not_a_dir, /* /proc/sys/kernel/cap_last_cap */ + lxpr_lookup_not_a_dir, /* /proc/sys/kernel/core_pattern */ lxpr_lookup_not_a_dir, /* /proc/sys/kernel/hostname */ lxpr_lookup_not_a_dir, /* /proc/sys/kernel/msgmni */ lxpr_lookup_not_a_dir, /* /proc/sys/kernel/ngroups_max */ @@ -919,6 +927,7 @@ static int (*lxpr_readdir_function[LXPR_NFILES])() = { lxpr_readdir_not_a_dir, /* .../inotify/max_user_watches */ lxpr_readdir_sys_kerneldir, /* /proc/sys/kernel */ lxpr_readdir_not_a_dir, /* /proc/sys/kernel/cap_last_cap */ + lxpr_readdir_not_a_dir, /* /proc/sys/kernel/core_pattern */ lxpr_readdir_not_a_dir, /* /proc/sys/kernel/hostname */ lxpr_readdir_not_a_dir, /* /proc/sys/kernel/msgmni */ lxpr_readdir_not_a_dir, /* /proc/sys/kernel/ngroups_max */ @@ -3893,6 +3902,38 @@ lxpr_read_sys_kernel_caplcap(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) } static void +lxpr_read_sys_kernel_corepatt(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) +{ + zone_t *zone = curproc->p_zone; + struct core_globals *cg; + refstr_t *rp; + corectl_path_t *ccp; + char tr[MAXPATHLEN]; + + ASSERT(lxpnp->lxpr_type == LXPR_SYS_KERNEL_COREPATT); + + cg = zone_getspecific(core_zone_key, zone); + ASSERT(cg != NULL); + + /* If core dumps are disabled, return an empty string. */ + if ((cg->core_options & CC_PROCESS_PATH) == 0) { + lxpr_uiobuf_printf(uiobuf, "\n"); + return; + } + + ccp = cg->core_default_path; + mutex_enter(&ccp->ccp_mtx); + if ((rp = ccp->ccp_path) != NULL) + refstr_hold(rp); + mutex_exit(&ccp->ccp_mtx); + + lxpr_core_path_s2l(refstr_value(rp), tr); + refstr_rele(rp); + + lxpr_uiobuf_printf(uiobuf, "%s\n", tr); +} + +static void lxpr_read_sys_kernel_hostname(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) { ASSERT(lxpnp->lxpr_type == LXPR_SYS_KERNEL_HOSTNAME); @@ -4503,6 +4544,7 @@ lxpr_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct) switch (type) { case LXPR_PID_OOM_SCR_ADJ: case LXPR_PID_TID_OOM_SCR_ADJ: + case LXPR_SYS_KERNEL_COREPATT: case LXPR_SYS_NET_CORE_SOMAXCON: case LXPR_SYS_VM_OVERCOMMIT_MEM: case LXPR_SYS_VM_SWAPPINESS: @@ -5781,6 +5823,63 @@ lxpr_write_sys_net_core_somaxc(lxpr_node_t *lxpnp, struct uio *uio, return (res); } +/* ARGSUSED */ +static int +lxpr_write_sys_kernel_corepatt(lxpr_node_t *lxpnp, struct uio *uio, + struct cred *cr, caller_context_t *ct) +{ + zone_t *zone = curproc->p_zone; + struct core_globals *cg; + refstr_t *rp, *nrp; + corectl_path_t *ccp; + char val[MAXPATHLEN]; + char valtr[MAXPATHLEN]; + size_t olen; + int error; + + ASSERT(lxpnp->lxpr_type == LXPR_SYS_KERNEL_COREPATT); + + cg = zone_getspecific(core_zone_key, zone); + ASSERT(cg != NULL); + + if (secpolicy_coreadm(cr) != 0) + return (EPERM); + + if (uio->uio_loffset != 0) + return (EINVAL); + + if (uio->uio_resid == 0) + return (0); + + olen = uio->uio_resid; + if (olen > sizeof (val) - 1) + return (EINVAL); + + bzero(val, sizeof (val)); + error = uiomove(val, olen, UIO_WRITE, uio); + if (error != 0) + return (error); + + if (val[olen - 1] == '\n') + val[olen - 1] = '\0'; + + lxpr_core_path_l2s(val, valtr); + + nrp = refstr_alloc(valtr); + + ccp = cg->core_default_path; + mutex_enter(&ccp->ccp_mtx); + rp = ccp->ccp_path; + refstr_hold((ccp->ccp_path = nrp)); + cg->core_options |= CC_PROCESS_PATH; + mutex_exit(&ccp->ccp_mtx); + + if (rp != NULL) + refstr_rele(rp); + + return (0); +} + /* * lxpr_readlink(): Vnode operation for VOP_READLINK() */ @@ -5974,6 +6073,8 @@ lxpr_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, lxpr_nodetype_t type = lxpnp->lxpr_type; switch (type) { + case LXPR_SYS_KERNEL_COREPATT: + return (lxpr_write_sys_kernel_corepatt(lxpnp, uiop, cr, ct)); case LXPR_SYS_NET_CORE_SOMAXCON: return (lxpr_write_sys_net_core_somaxc(lxpnp, uiop, cr, ct)); @@ -6021,6 +6122,7 @@ lxpr_create(struct vnode *dvp, char *nm, struct vattr *vap, * We're currently restricting O_CREAT to: * - /proc/<pid>/oom_score_adj * - /proc/<pid>/task/<tid>/oom_score_adj + * - /proc/sys/kernel/core_pattern * - /proc/sys/net/core/somaxconn * - /proc/sys/vm/overcommit_memory * - /proc/sys/vm/swappiness @@ -6038,6 +6140,10 @@ lxpr_create(struct vnode *dvp, char *nm, struct vattr *vap, strcmp(nm, "somaxconn") == 0) { vp = lxpr_lookup_common(dvp, nm, NULL, sys_net_coredir, SYS_NET_COREDIRFILES); + } else if (type == LXPR_SYS_KERNELDIR && + strcmp(nm, "core_pattern") == 0) { + vp = lxpr_lookup_common(dvp, nm, NULL, sys_kerneldir, + SYS_KERNELDIRFILES); } else if (type == LXPR_SYS_VMDIR && (strcmp(nm, "overcommit_memory") == 0 || strcmp(nm, "swappiness") == 0)) { |