summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorAlex Wilson <alex.wilson@joyent.com>2015-08-17 16:26:13 -0700
committerAlex Wilson <alex.wilson@joyent.com>2015-08-18 09:24:08 -0700
commitabaee2673042ff817f068c8401f34b8316e8962c (patch)
tree2b227500369f4cc934ca6db40b3aa1642ffbfd00 /usr
parent29170abe7b69701c0f95839235131541fd3fb2e5 (diff)
downloadillumos-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.h4
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_prsubr.c113
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_prvnops.c106
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)) {