File indexing completed on 2022-11-29 20:01:37

0001 /*
0002     SPDX-FileCopyrightText: 2019 Christoph Roick <chrisito@gmx.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "ptracer.h"
0007 
0008 #ifdef Q_OS_LINUX
0009 
0010 #include "drkonqi_debug.h"
0011 
0012 #include <QFile>
0013 #include <QStandardPaths>
0014 
0015 #include <sys/poll.h>
0016 #include <sys/socket.h>
0017 #include <sys/un.h>
0018 
0019 #include <errno.h>
0020 #include <unistd.h>
0021 
0022 void setPtracer(qint64 debuggerpid, qint64 debuggeepid)
0023 {
0024     int sfd = socket(PF_UNIX, SOCK_STREAM, 0);
0025     if (sfd < 0) {
0026         qCWarning(DRKONQI_LOG) << "socket to set ptracer not accessible";
0027         return;
0028     }
0029 
0030     static struct sockaddr_un server;
0031     static socklen_t sl = sizeof(server);
0032     server.sun_family = AF_UNIX;
0033     const QString socketPath = QStringLiteral("%1/kcrash_%2").arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)).arg(debuggeepid);
0034 
0035     if (socketPath.size() >= static_cast<int>(sizeof(server.sun_path))) {
0036         qCWarning(DRKONQI_LOG) << "socket path is too long";
0037         close(sfd);
0038         return;
0039     }
0040     strcpy(server.sun_path, QFile::encodeName(socketPath).constData());
0041 
0042     if (::connect(sfd, (struct sockaddr *)&server, sl) == 0) {
0043         static const int msize = 21; // most digits in a 64bit int (+sign +'\0')
0044         char msg[msize];
0045         sprintf(msg, "%lld", debuggerpid);
0046 
0047         int r, bytes = 0;
0048         while (bytes < msize) {
0049             r = write(sfd, msg + bytes, msize - bytes);
0050             if (r > 0)
0051                 bytes += r;
0052             else if (r == -1 && errno != EINTR)
0053                 break;
0054         }
0055         if (bytes == msize) {
0056             struct pollfd fd;
0057             fd.fd = sfd;
0058             fd.events = POLLIN;
0059             while ((r = poll(&fd, 1, 1000)) == -1 && errno == EINTR) { }
0060             if (r > 0 && (fd.revents & POLLIN)) {
0061                 char rmsg[msize];
0062                 bytes = 0;
0063                 while (bytes < msize) {
0064                     r = read(sfd, rmsg + bytes, msize - bytes);
0065                     if (r > 0)
0066                         bytes += r;
0067                     else if (r == -1 && errno != EINTR)
0068                         break;
0069                 }
0070                 if (bytes == msize && memcmp(msg, rmsg, msize) == 0)
0071                     qCInfo(DRKONQI_LOG) << "ptracer set to" << debuggerpid << "by debugged process";
0072                 else
0073                     qCWarning(DRKONQI_LOG) << "debugged process did not acknowledge setting ptracer to" << debuggerpid;
0074                 close(sfd);
0075                 return;
0076             }
0077         }
0078     }
0079 
0080     qCWarning(DRKONQI_LOG) << "unable to set ptracer to" << debuggerpid;
0081     close(sfd);
0082 }
0083 
0084 #else
0085 
0086 void setPtracer(qint64, qint64)
0087 {
0088 }
0089 
0090 #endif