Plugin context check: check termios settings
This commit is contained in:
parent
7d7024d114
commit
5d29d8aff0
6 changed files with 119 additions and 17 deletions
|
|
@ -70,6 +70,7 @@ Developers may need to change their code
|
||||||
|
|
||||||
* Plugin context check before and after all callbacks.
|
* Plugin context check before and after all callbacks.
|
||||||
* Check blocked signals and signal handlers
|
* Check blocked signals and signal handlers
|
||||||
|
* Check termios settings
|
||||||
* Any changes to context are logged at loglevel WARNING
|
* Any changes to context are logged at loglevel WARNING
|
||||||
* Added set/get pointer API to clixon_data:
|
* Added set/get pointer API to clixon_data:
|
||||||
* clicon_ptr_get(), clicon_ptr_set(),
|
* clicon_ptr_get(), clicon_ptr_set(),
|
||||||
|
|
|
||||||
|
|
@ -165,17 +165,17 @@ cli_signal_flush(clicon_handle h)
|
||||||
|
|
||||||
sigfn_t h1, h2, h3, h4;
|
sigfn_t h1, h2, h3, h4;
|
||||||
|
|
||||||
set_signal (SIGTSTP, SIG_IGN, &h1);
|
set_signal(SIGTSTP, SIG_IGN, &h1);
|
||||||
set_signal (SIGQUIT, SIG_IGN, &h2);
|
set_signal(SIGQUIT, SIG_IGN, &h2);
|
||||||
set_signal (SIGCHLD, SIG_IGN, &h3);
|
set_signal(SIGCHLD, SIG_IGN, &h3);
|
||||||
set_signal (SIGINT, SIG_IGN, &h4);
|
set_signal(SIGINT, SIG_IGN, &h4);
|
||||||
|
|
||||||
cli_signal_unblock (h);
|
cli_signal_unblock (h);
|
||||||
|
|
||||||
set_signal (SIGTSTP, h1, NULL);
|
set_signal(SIGTSTP, h1, NULL);
|
||||||
set_signal (SIGQUIT, h2, NULL);
|
set_signal(SIGQUIT, h2, NULL);
|
||||||
set_signal (SIGCHLD, h3, NULL);
|
set_signal(SIGCHLD, h3, NULL);
|
||||||
set_signal (SIGINT, h4, NULL);
|
set_signal(SIGINT, h4, NULL);
|
||||||
|
|
||||||
cli_signal_block (h);
|
cli_signal_block (h);
|
||||||
}
|
}
|
||||||
|
|
@ -562,9 +562,10 @@ cli_start_shell(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char bcmd[128];
|
char bcmd[128];
|
||||||
cg_var *cv1 = cvec_i(vars, 1);
|
cg_var *cv1 = cvec_i(vars, 1);
|
||||||
|
sigset_t oldsigset;
|
||||||
|
struct sigaction oldsigaction[32] = {0,};
|
||||||
|
|
||||||
cmd = (cvec_len(vars)>1 ? cv_string_get(cv1) : NULL);
|
cmd = (cvec_len(vars)>1 ? cv_string_get(cv1) : NULL);
|
||||||
|
|
||||||
if ((pw = getpwuid(getuid())) == NULL){
|
if ((pw = getpwuid(getuid())) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "getpwuid");
|
clicon_err(OE_UNIX, errno, "getpwuid");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -575,6 +576,9 @@ cli_start_shell(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
endpwent();
|
endpwent();
|
||||||
|
|
||||||
|
if (clixon_signal_save(&oldsigset, oldsigaction) < 0)
|
||||||
|
goto done;
|
||||||
cli_signal_flush(h);
|
cli_signal_flush(h);
|
||||||
cli_signal_unblock(h);
|
cli_signal_unblock(h);
|
||||||
if (cmd){
|
if (cmd){
|
||||||
|
|
@ -598,6 +602,8 @@ cli_start_shell(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (clixon_signal_restore(&oldsigset, oldsigaction) < 0)
|
||||||
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ typedef void (*sigfn_t)(int);
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
int set_signal(int signo, void (*handler)(int), void (**oldhandler)(int));
|
int set_signal(int signo, void (*handler)(int), void (**oldhandler)(int));
|
||||||
|
int clixon_signal_save(sigset_t *sigset, struct sigaction sigaction_vec[32]);
|
||||||
|
int clixon_signal_restore(sigset_t *sigset, struct sigaction sigaction_vec[32]);
|
||||||
void clicon_signal_block(int);
|
void clicon_signal_block(int);
|
||||||
void clicon_signal_unblock(int);
|
void clicon_signal_unblock(int);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <termios.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
|
@ -71,12 +72,13 @@
|
||||||
* Private types
|
* Private types
|
||||||
*/
|
*/
|
||||||
/*! Structure for checking status before and after a plugin call
|
/*! Structure for checking status before and after a plugin call
|
||||||
* Currently signal settings: blocked and handlers, could be extended to more
|
* Currently signal settings: blocked and handlers, and termios
|
||||||
* @see plugin_context_check
|
* @see plugin_context_check
|
||||||
*/
|
*/
|
||||||
struct plugin_context {
|
struct plugin_context {
|
||||||
sigset_t pc_sigset; /* See sigprocmask(2) */
|
sigset_t pc_sigset; /* See sigprocmask(2) */
|
||||||
struct sigaction pc_sigaction_vec[32]; /* See sigaction(2) */
|
struct sigaction pc_sigaction_vec[32]; /* See sigaction(2) */
|
||||||
|
struct termios pc_termios; /* See termios(3) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Internal plugin structure with dlopen() handle and plugin_api
|
/* Internal plugin structure with dlopen() handle and plugin_api
|
||||||
|
|
@ -518,6 +520,7 @@ plugin_context_get(void)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
memset(pc, 0, sizeof(*pc));
|
memset(pc, 0, sizeof(*pc));
|
||||||
|
|
||||||
if (sigprocmask(0, NULL, &pc->pc_sigset) < 0){
|
if (sigprocmask(0, NULL, &pc->pc_sigset) < 0){
|
||||||
clicon_err(OE_UNIX, errno, "sigprocmask");
|
clicon_err(OE_UNIX, errno, "sigprocmask");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -536,6 +539,10 @@ plugin_context_get(void)
|
||||||
pc->pc_sigaction_vec[i].sa_flags &= ~0x04000000;
|
pc->pc_sigaction_vec[i].sa_flags &= ~0x04000000;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (isatty(0) && tcgetattr(0, &pc->pc_termios) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "tcgetattr %d", errno);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
return pc;
|
return pc;
|
||||||
done:
|
done:
|
||||||
if (pc)
|
if (pc)
|
||||||
|
|
@ -564,15 +571,48 @@ plugin_context_check(plugin_context_t *oldpc0,
|
||||||
const char *fn)
|
const char *fn)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int failed;
|
int failed = 0;
|
||||||
int i;
|
int i;
|
||||||
struct plugin_context *oldpc = oldpc0;
|
struct plugin_context *oldpc = oldpc0;
|
||||||
struct plugin_context *newpc = NULL;
|
struct plugin_context *newpc = NULL;
|
||||||
|
|
||||||
if ((newpc = plugin_context_get()) == NULL)
|
if ((newpc = plugin_context_get()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (oldpc->pc_termios.c_iflag != newpc->pc_termios.c_iflag){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed termios input modes from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn,
|
||||||
|
oldpc->pc_termios.c_iflag,
|
||||||
|
newpc->pc_termios.c_iflag);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if (oldpc->pc_termios.c_oflag != newpc->pc_termios.c_oflag){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed termios output modes from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn,
|
||||||
|
oldpc->pc_termios.c_oflag,
|
||||||
|
newpc->pc_termios.c_oflag);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if (oldpc->pc_termios.c_cflag != newpc->pc_termios.c_cflag){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed termios control modes from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn,
|
||||||
|
oldpc->pc_termios.c_cflag,
|
||||||
|
newpc->pc_termios.c_cflag);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if (oldpc->pc_termios.c_lflag != newpc->pc_termios.c_lflag){
|
||||||
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed termios local modes from 0x%x to 0x%x", __FUNCTION__,
|
||||||
|
name, fn,
|
||||||
|
oldpc->pc_termios.c_lflag,
|
||||||
|
newpc->pc_termios.c_lflag);
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
/* XXX pc_termios.cc_t c_cc[NCCS] not checked */
|
||||||
|
#if 0
|
||||||
|
/* In case you want early detection and crash. But otherwise it is recommended that
|
||||||
|
* the caller looks for retval == 0 */
|
||||||
|
assert(failed == 0);
|
||||||
|
#endif
|
||||||
for (i=1; i<32; i++){
|
for (i=1; i<32; i++){
|
||||||
failed = 0;
|
|
||||||
if (sigismember(&oldpc->pc_sigset, i) != sigismember(&newpc->pc_sigset, i)){
|
if (sigismember(&oldpc->pc_sigset, i) != sigismember(&newpc->pc_sigset, i)){
|
||||||
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed blocking of signal %s(%d) from %d to %d", __FUNCTION__,
|
clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed blocking of signal %s(%d) from %d to %d", __FUNCTION__,
|
||||||
name, fn, strsignal(i), i,
|
name, fn, strsignal(i), i,
|
||||||
|
|
@ -600,10 +640,10 @@ plugin_context_check(plugin_context_t *oldpc0,
|
||||||
* the caller looks for retval == 0 */
|
* the caller looks for retval == 0 */
|
||||||
assert(failed == 0);
|
assert(failed == 0);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
if (failed)
|
if (failed)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
}
|
|
||||||
retval = 1; /* OK */
|
retval = 1; /* OK */
|
||||||
done:
|
done:
|
||||||
if (newpc)
|
if (newpc)
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,58 @@ clicon_signal_unblock(int sig)
|
||||||
sigprocmask(SIG_UNBLOCK, &set, NULL);
|
sigprocmask(SIG_UNBLOCK, &set, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Save complete signal context
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_signal_save(sigset_t *sigset,
|
||||||
|
struct sigaction sigaction_vec[32])
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sigprocmask(0, NULL, sigset) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigprocmask");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
for (i=1; i<32; i++){
|
||||||
|
if (sigaction(i, NULL, &sigaction_vec[i]) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigaction");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Restore complete signal context
|
||||||
|
*
|
||||||
|
* Note: sigaction may not restore SIGKILL or SIGSTOP, which cannot be caught or ignored.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_signal_restore(sigset_t *sigset,
|
||||||
|
struct sigaction sigaction_vec[32])
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (sigprocmask(0, sigset, NULL) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigprocmask");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
for (i=1; i<32; i++){
|
||||||
|
if (i == SIGKILL || i == SIGSTOP)
|
||||||
|
continue;
|
||||||
|
if (sigaction(i, &sigaction_vec[i], NULL) < 0){
|
||||||
|
clicon_err(OE_UNIX, errno, "sigaction");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Read pidfile and return pid using file descriptor
|
/*! Read pidfile and return pid using file descriptor
|
||||||
*
|
*
|
||||||
* @param[in] pidfile Name of pidfile
|
* @param[in] pidfile Name of pidfile
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue