summaryrefslogtreecommitdiffstats
path: root/src/input
diff options
context:
space:
mode:
authorSebastien Braun2010-10-06 15:08:03 +0200
committerSebastien Braun2010-10-06 15:08:03 +0200
commit6afd810d1954018791456a7cebca0d275c50ed95 (patch)
tree64d7b3e560dde3049c6c3056387c14f10066c666 /src/input
parentImplement administratively configured user privileges (diff)
downloadpvs-6afd810d1954018791456a7cebca0d275c50ed95.tar.gz
pvs-6afd810d1954018791456a7cebca0d275c50ed95.tar.xz
pvs-6afd810d1954018791456a7cebca0d275c50ed95.zip
Refactor signal handling in pvsprivinputd
Only use one socketpair and delegate the actual decision of what to do when a specific signal is received to a special object.
Diffstat (limited to 'src/input')
-rw-r--r--src/input/CMakeLists.txt2
-rw-r--r--src/input/pvsPrivInputSignalHandler.cpp69
-rw-r--r--src/input/pvsPrivInputSignalHandler.h47
-rw-r--r--src/input/pvsPrivInputSocket.cpp14
-rw-r--r--src/input/pvsPrivInputSocket.h1
-rw-r--r--src/input/pvsprivinputd.cpp40
6 files changed, 155 insertions, 18 deletions
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
index 29c463a..fcb5ff5 100644
--- a/src/input/CMakeLists.txt
+++ b/src/input/CMakeLists.txt
@@ -18,6 +18,7 @@ if(UNIX)
pvsprivinputd.cpp
pvsPrivInputHandler.cpp
pvsCheckPrivileges.cpp
+ pvsPrivInputSignalHandler.cpp
rebootSystemHandler.cpp
killX11Handler.cpp
sayHelloHandler.cpp
@@ -26,6 +27,7 @@ if(UNIX)
set(pvsprivinputd_MOC_HDRS
pvsPrivInputHandler.h
pvsCheckPrivileges.h
+ pvsPrivInputSignalHandler.h
)
qt4_wrap_cpp(pvsprivinputd_MOC_SRCS
diff --git a/src/input/pvsPrivInputSignalHandler.cpp b/src/input/pvsPrivInputSignalHandler.cpp
new file mode 100644
index 0000000..b09c335
--- /dev/null
+++ b/src/input/pvsPrivInputSignalHandler.cpp
@@ -0,0 +1,69 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsPrivInputSignalHandler.cpp:
+ # - Handle signals forwarded over a file descriptor - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <cerrno>
+#include "pvsPrivInputSocket.h"
+#include "pvsPrivInputSignalHandler.h"
+
+void PVSPrivInputSignalHandler::signalReceived(int sigfd)
+{
+ int signum;
+
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+ int err;
+ size_t siz = sizeof(signum);
+
+ if(!pvsPrivInputRecvMessage(sigfd, &signum, siz, pid, uid, gid, &err))
+ {
+ qWarning("Should have received a signal but could not read message: %s", strerror(err));
+ return;
+ }
+
+ if(siz != sizeof(signum))
+ {
+ qWarning("Sould have received a message of size %d bytes but got %d bytes instead. Discarding message.", (int)sizeof(signum), (int)siz);
+ return;
+ }
+
+ if(!_allowUnauthenticatedKilling && pid != getpid())
+ {
+ qCritical("SOMETHING STRANGE IS GOING ON!\nReceived signal %d from PID %d\nPlease kill me instead of sending me signal notifications.", signum, (int)pid);
+ return;
+ }
+
+ switch(signum)
+ {
+ case SIGINT:
+ qDebug("Caught SIGINT. Quitting.");
+ emit terminate();
+ break;
+ case SIGTERM:
+ qDebug("Caught SIGTERM. Quitting.");
+ emit terminate();
+ break;
+ case SIGHUP:
+ qDebug("Caught SIGHUP. Reloading configuration.");
+ emit reloadConfiguration();
+ break;
+ default:
+ qWarning("Received signal %d, but don't know how to handle it.", signum);
+ }
+}
diff --git a/src/input/pvsPrivInputSignalHandler.h b/src/input/pvsPrivInputSignalHandler.h
new file mode 100644
index 0000000..cb75c86
--- /dev/null
+++ b/src/input/pvsPrivInputSignalHandler.h
@@ -0,0 +1,47 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsPrivInputSignalHandler.h:
+ # - Handle signals forwarded over a file descriptor - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef PVSPRIVINPUTSIGNALHANDLER_H_
+#define PVSPRIVINPUTSIGNALHANDLER_H_
+
+#include <QObject>
+
+class PVSPrivInputSignalHandler : public QObject
+{
+ Q_OBJECT
+public:
+ PVSPrivInputSignalHandler(QObject* parent = 0)
+ : QObject(parent)
+ {
+ }
+
+ void allowUnauthenticatedKilling(bool value)
+ {
+ _allowUnauthenticatedKilling = value;
+ }
+
+public slots:
+ void signalReceived(int sigfd);
+
+signals:
+ void terminate();
+ void reloadConfiguration();
+
+private:
+ bool _allowUnauthenticatedKilling;
+};
+
+#endif /* PVSPRIVINPUTSIGNALHANDLER_H_ */
diff --git a/src/input/pvsPrivInputSocket.cpp b/src/input/pvsPrivInputSocket.cpp
index c491dd9..df5dff5 100644
--- a/src/input/pvsPrivInputSocket.cpp
+++ b/src/input/pvsPrivInputSocket.cpp
@@ -60,6 +60,17 @@ QString pvsPrivInputGetSocketAddress()
return pvsPrivInputGetSettings()->value("socketpath", "/tmp/pvsprivinputd.sock").toString();
}
+bool pvsPrivInputEnableReceiveCredentials(int sock)
+{
+ int passcred = 1;
+ if(setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &passcred, sizeof(passcred)) < 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
int pvsPrivInputMakeClientSocket()
@@ -110,8 +121,7 @@ int pvsPrivInputMakeServerSocket()
}
// Announce that credentials are requested:
- int passcred = 1;
- if(setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &passcred, sizeof(passcred)) < 0)
+ if(!pvsPrivInputEnableReceiveCredentials(sock))
{
// We will not operate without credentials.
qCritical("Could not request peer credentials: %s", strerror(errno));
diff --git a/src/input/pvsPrivInputSocket.h b/src/input/pvsPrivInputSocket.h
index 879ca99..447360b 100644
--- a/src/input/pvsPrivInputSocket.h
+++ b/src/input/pvsPrivInputSocket.h
@@ -28,6 +28,7 @@ QSettings* pvsPrivInputGetSettings();
QSettings* pvsPrivInputReopenSettings();
QString pvsPrivInputGetSettingsPath();
QString pvsPrivInputGetSocketAddress();
+bool pvsPrivInputEnableReceiveCredentials(int sock);
int pvsPrivInputMakeClientSocket();
int pvsPrivInputMakeServerSocket();
bool pvsPrivInputSendMessage(int sock, void* buf, size_t len, int* err = 0);
diff --git a/src/input/pvsprivinputd.cpp b/src/input/pvsprivinputd.cpp
index 3a5e1a8..361bf9f 100644
--- a/src/input/pvsprivinputd.cpp
+++ b/src/input/pvsprivinputd.cpp
@@ -30,6 +30,7 @@
#include <QSocketNotifier>
#include "pvsPrivInputSocket.h"
#include "pvsPrivInputHandler.h"
+#include "pvsPrivInputSignalHandler.h"
using namespace std;
@@ -38,7 +39,7 @@ using namespace std;
#endif
QByteArray socketPath;
-int sigintFds[2];
+int signalFds[2];
static void unlinkSocket()
{
@@ -48,12 +49,9 @@ static void unlinkSocket()
}
}
-static void onInterrupt(int)
+static void onCaughtSignal(int signum)
{
- char buf[] = { '!' };
- char msg[] = "SIGINT caught. Quitting.\n";
- write(sigintFds[0], buf, 1);
- write(1, msg, sizeof(msg)-1);
+ pvsPrivInputSendMessage(signalFds[0], &signum, sizeof(signum), 0);
}
int main(int argc, char** argv)
@@ -103,28 +101,38 @@ int main(int argc, char** argv)
// the socket (access control is handled differently):
umask(0);
+ // Store the socket path before the signal handler is installed so it does not risk segfaulting
+ // due to bad timing.
+ socketPath = pvsPrivInputGetSocketAddress().toLocal8Bit();
+
// Ignore SIGPIPE. Connection errors are handled internally.
// According to signal(2), the only error is that the signal number
// is invalid. This cannot happen.
signal(SIGPIPE, SIG_IGN);
- // set up signal handling:
- if(socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFds) < 0)
+ // Create our socket:
+ int sock = pvsPrivInputMakeServerSocket();
+ if(sock < 0)
{
- qCritical("Could not set up signal handling. Giving up.");
exit(EXIT_FAILURE);
}
- socketPath = pvsPrivInputGetSocketAddress().toLocal8Bit();
- QSocketNotifier sigintWatcher(sigintFds[1], QSocketNotifier::Read);
- QObject::connect(&sigintWatcher, SIGNAL(activated(int)), &app, SLOT(quit()));
- signal(SIGINT, onInterrupt);
- // Create our socket:
- int sock = pvsPrivInputMakeServerSocket();
- if(sock < 0)
+ // set up signal handling:
+ if(socketpair(AF_UNIX, SOCK_DGRAM, 0, signalFds) < 0)
{
+ qCritical("Could not set up signal handling. Giving up.");
exit(EXIT_FAILURE);
}
+ PVSPrivInputSignalHandler sigHandler;
+ QSocketNotifier sigintWatcher(signalFds[1], QSocketNotifier::Read);
+ sigHandler.allowUnauthenticatedKilling(!pvsPrivInputEnableReceiveCredentials(signalFds[1]));
+ QObject::connect(&sigintWatcher, SIGNAL(activated(int)), &sigHandler, SLOT(signalReceived(int)));
+ QObject::connect(&sigHandler, SIGNAL(terminate()), &app, SLOT(quit()));
+ QObject::connect(&sigHandler, SIGNAL(reloadConfiguration()), PVSCheckPrivileges::instance(), SLOT(updateCachedUserDatabase()));
+ QObject::connect(&sigHandler, SIGNAL(reloadConfiguration()), PVSCheckPrivileges::instance(), SLOT(rereadConfiguration()));
+ signal(SIGINT, onCaughtSignal);
+ signal(SIGTERM, onCaughtSignal);
+ signal(SIGHUP, onCaughtSignal);
// Our setup is complete.
if(!no_fork)