Plugin context check: check termios settings

This commit is contained in:
Olof hagsand 2021-10-21 15:44:04 +02:00
parent 7d7024d114
commit 5d29d8aff0
6 changed files with 119 additions and 17 deletions

View file

@ -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(),

View file

@ -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;

View file

@ -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);

View file

@ -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>

View file

@ -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)

View file

@ -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