Issue #103: Child process cleanup under PAM session
* Added signal handling in PAM session process. Now SIGHUP signals are forward to child process, which is the actual service. Launcher process uses this type of signals to terminate service on http connection timeout.
This commit is contained in:
parent
eb2968b1d0
commit
b828574899
1 changed files with 41 additions and 9 deletions
|
@ -139,9 +139,6 @@ int execle(const char *, const char *, ...);
|
|||
extern int pthread_once(pthread_once_t *, void (*)(void))__attribute__((weak));
|
||||
#endif
|
||||
|
||||
// From shellinabox/shellinaboxd.c
|
||||
extern int enableUtmpLogging;
|
||||
|
||||
// If PAM support is available, take advantage of it. Otherwise, silently fall
|
||||
// back on legacy operations for session management.
|
||||
#if defined(HAVE_SECURITY_PAM_APPL_H) && defined(HAVE_DLOPEN)
|
||||
|
@ -175,6 +172,13 @@ static int (*x_misc_conv)(int, const struct pam_message **,
|
|||
static int launcher = -1;
|
||||
static uid_t restricted;
|
||||
|
||||
// From shellinabox/shellinaboxd.c
|
||||
extern int enableUtmpLogging;
|
||||
|
||||
#if defined(HAVE_SECURITY_PAM_APPL_H)
|
||||
static int pamSessionSighupFlag;
|
||||
#endif
|
||||
|
||||
// MacOS X has a somewhat unusual definition of getgrouplist() which can
|
||||
// trigger a compile warning.
|
||||
#if defined(HAVE_GETGROUPLIST_TAKES_INTS)
|
||||
|
@ -1495,6 +1499,17 @@ void setWindowSize(int pty, int width, int height) {
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_SECURITY_PAM_APPL_H)
|
||||
static void pamSessionSighupHandler(int sig ATTR_UNUSED,
|
||||
siginfo_t *info ATTR_UNUSED,
|
||||
void *unused ATTR_UNUSED) {
|
||||
UNUSED(sig);
|
||||
UNUSED(info);
|
||||
UNUSED(unused);
|
||||
pamSessionSighupFlag = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void childProcess(struct Service *service, int width, int height,
|
||||
struct Utmp *utmp, const char *peerName, const char *realIP,
|
||||
const char *url) {
|
||||
|
@ -1585,7 +1600,7 @@ static void childProcess(struct Service *service, int width, int height,
|
|||
#if defined(HAVE_SECURITY_PAM_APPL_H)
|
||||
if (pam && !geteuid()) {
|
||||
if (pam_open_session(pam, PAM_SILENT) != PAM_SUCCESS) {
|
||||
fprintf(stderr, "Access denied.\n");
|
||||
fprintf(stderr, "[server] Unable to open PAM session!\n");
|
||||
_exit(1);
|
||||
}
|
||||
pid_t pid = fork();
|
||||
|
@ -1595,9 +1610,26 @@ static void childProcess(struct Service *service, int width, int height,
|
|||
case 0:
|
||||
break;
|
||||
default:;
|
||||
// Finish all pending PAM operations.
|
||||
// This process is used for finishing all pending PAM operations.
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
|
||||
sa.sa_sigaction = pamSessionSighupHandler;
|
||||
check(!sigaction(SIGHUP, &sa, NULL));
|
||||
int status, rc;
|
||||
check(NOINTR(waitpid(pid, &status, 0)) == pid);
|
||||
while (1) {
|
||||
pamSessionSighupFlag = 0;
|
||||
int val = waitpid(pid, &status, 0);
|
||||
if (val < 0 && errno == EINTR) {
|
||||
if (pamSessionSighupFlag) {
|
||||
// If SIGHUP signal is received it needs to be forwarded to child
|
||||
// process, which is acctual service process.
|
||||
kill(pid, SIGHUP);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc = pam_close_session(pam, PAM_SILENT);
|
||||
pam_end(pam, rc | PAM_DATA_SILENT);
|
||||
_exit(WIFEXITED(status) ? WEXITSTATUS(status) : -WTERMSIG(status));
|
||||
|
|
Loading…
Reference in a new issue