1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/****************************************************************
* *
* Copyright (c) 2001-2018 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include <sys/types.h>
#include <setjmp.h>
#include <errno.h>
#include "gtm_string.h"
#include "unistd.h"
#include "gtm_stdlib.h"
#include "gtm_stdio.h"
#include "invocation_mode.h"
#include "gtmimagename.h"
#include "error.h"
#include "send_msg.h"
#include "have_crit.h"
#include "eintr_wrappers.h"
#define COREDUMPFILTERFN "/proc/%i/coredump_filter"
#define FILTERPARMSIZE (8 + 2 + 1) /* 8 bytes for number (normally 7), 2 bytes for 0x, and 1 null terminator */
#define FILTERENABLEBITS 0x0000073 /* Bits 0, 1, 4, 5, 6 - 32-bit can only handle 10 bytes total */
GBLREF enum gtmImageTypes image_type;
GBLDEF char **gtmenvp;
error_def(ERR_SYSCALL);
/* 1. Allocate a basic initial condition handler stack that can be expanded later if necessary.
* 2. On Linux, make sure bits 0,1, 4, 5, and 6 are set in /proc/PID/coredump_filter so dumps the sections that GT.M
* cores need to have in them.
*/
void err_init(void (*x)())
{
# ifdef __linux__
int rc;
unsigned int filterbits;
char procfn[SIZEOF(COREDUMPFILTERFN) + MAX_DIGITS_IN_INT]; /* File name of file to update */
char filter[FILTERPARMSIZE], *filterend; /* Value read in & written out */
char *rcc, *bytes_buf;
FILE *filterstrm; /* filter stream file block */
# endif
chnd = (condition_handler *)malloc((CONDSTK_INITIAL_INCR + CONDSTK_RESERVE) * SIZEOF(condition_handler));
chnd[0].ch_active = FALSE;
chnd[0].save_active_ch = NULL;
active_ch = ctxt = &chnd[0];
ctxt->ch = x;
chnd_end = &chnd[CONDSTK_INITIAL_INCR]; /* chnd_end is the end of the condition handler stack */
chnd_incr = CONDSTK_INITIAL_INCR * 2;
# ifdef __linux__
/* Read the coredump_filter value from /proc for this process, update the value if necessary so we have the proper
* flags set to get the info we (and gtmpcat) need to properly process a core file. Note any errors we encounter just
* send a message to the operator log and return as nothing here should prevent GT.M from running.
*
* Note "man 5 core" on x86-64 Linux (Ubuntu 12.04) notes that the /proc/PID/coredump_filter file is only provided when
* the Linux kernel is built with the CONFIG_ELF_CORE configuration option. This *seems* to control whether or not the
* kernel supports the ELF loader or not. To date, all Linux flavors GT.M supports use ELF so we regard this as largely
* mandatory though in the future it may happen that GT.M works yet runs with something other than ELF. In that case,
* we'd need to change the below to avoid the operator log messages every time GT.M initializes.
*
* Note use simple basic methods since this early in initialization not everything is necessarily setup to
* be able to properly use the *print*() wrapper functions.
*
*/
bytes_buf = GETENV("gtm_coredump_filter");
if ((NULL == bytes_buf) || (0 != strncmp("-1", bytes_buf, 3)))
{
rc = snprintf(procfn, SIZEOF(procfn), COREDUMPFILTERFN, getpid());
if (0 > rc)
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("snprintf()"), CALLFROM, rc);
return;
}
if (NULL == bytes_buf)
{
/* If $gtm_coredump_filter is not defined, set the filter to provide a full dump including huge pages */
Fopen(filterstrm, procfn, "r");
if (NULL == filterstrm)
{
rc = errno;
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
RTS_ERROR_LITERAL("fopen()"), CALLFROM, rc);
return;
}
rcc = fgets(filter, SIZEOF(filter), filterstrm);
if (NULL == rcc)
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
RTS_ERROR_LITERAL("fgets()"), CALLFROM, rc);
return;
}
FCLOSE(filterstrm, rc);
if (0 > rc)
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5,
RTS_ERROR_LITERAL("fclose()"), CALLFROM, rc);
return;
}
filterend = filter + SIZEOF(filter);
filterbits = (unsigned int)strtol(filter, &filterend, 16);
if (FILTERENABLEBITS != (filterbits & FILTERENABLEBITS))
{ /* At least one flag was missing - reset them */
filterbits = filterbits | FILTERENABLEBITS;
}
snprintf(filter, FILTERPARMSIZE, "0x%07x", filterbits);
bytes_buf = filter;
}
Fopen(filterstrm, procfn, "w");
if (NULL == filterstrm)
{
rc = errno;
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fopen()"),
CALLFROM, rc);
return;
}
rc = fprintf(filterstrm, "%s", bytes_buf);
if (0 > rc)
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fprintf"),
CALLFROM, rc);
return;
}
FCLOSE(filterstrm, rc);
if (0 > rc)
{
send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("fclose()"),
CALLFROM, rc);
return;
}
}
# endif
}
|