1 /*
2     SPDX-FileCopyrightText: 2019 Christoph Roick <chrisito@gmx.de>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 #include "ptracer.h"
7 
8 #ifdef Q_OS_LINUX
9 
10 #include "drkonqi_debug.h"
11 
12 #include <QFile>
13 #include <QStandardPaths>
14 
15 #include <sys/poll.h>
16 #include <sys/socket.h>
17 #include <sys/un.h>
18 
19 #include <errno.h>
20 #include <unistd.h>
21 
setPtracer(qint64 debuggerpid,qint64 debuggeepid)22 void setPtracer(qint64 debuggerpid, qint64 debuggeepid)
23 {
24     int sfd = socket(PF_UNIX, SOCK_STREAM, 0);
25     if (sfd < 0) {
26         qCWarning(DRKONQI_LOG) << "socket to set ptracer not accessible";
27         return;
28     }
29 
30     static struct sockaddr_un server;
31     static socklen_t sl = sizeof(server);
32     server.sun_family = AF_UNIX;
33     const QString socketPath = QStringLiteral("%1/kcrash_%2").arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)).arg(debuggeepid);
34 
35     if (socketPath.size() >= static_cast<int>(sizeof(server.sun_path))) {
36         qCWarning(DRKONQI_LOG) << "socket path is too long";
37         close(sfd);
38         return;
39     }
40     strcpy(server.sun_path, QFile::encodeName(socketPath).constData());
41 
42     if (::connect(sfd, (struct sockaddr *)&server, sl) == 0) {
43         static const int msize = 21; // most digits in a 64bit int (+sign +'\0')
44         char msg[msize];
45         sprintf(msg, "%lld", debuggerpid);
46 
47         int r, bytes = 0;
48         while (bytes < msize) {
49             r = write(sfd, msg + bytes, msize - bytes);
50             if (r > 0)
51                 bytes += r;
52             else if (r == -1 && errno != EINTR)
53                 break;
54         }
55         if (bytes == msize) {
56             struct pollfd fd;
57             fd.fd = sfd;
58             fd.events = POLLIN;
59             while ((r = poll(&fd, 1, 1000)) == -1 && errno == EINTR) { }
60             if (r > 0 && (fd.revents & POLLIN)) {
61                 char rmsg[msize];
62                 bytes = 0;
63                 while (bytes < msize) {
64                     r = read(sfd, rmsg + bytes, msize - bytes);
65                     if (r > 0)
66                         bytes += r;
67                     else if (r == -1 && errno != EINTR)
68                         break;
69                 }
70                 if (bytes == msize && memcmp(msg, rmsg, msize) == 0)
71                     qCInfo(DRKONQI_LOG) << "ptracer set to" << debuggerpid << "by debugged process";
72                 else
73                     qCWarning(DRKONQI_LOG) << "debugged process did not acknowledge setting ptracer to" << debuggerpid;
74                 close(sfd);
75                 return;
76             }
77         }
78     }
79 
80     qCWarning(DRKONQI_LOG) << "unable to set ptracer to" << debuggerpid;
81     close(sfd);
82 }
83 
84 #else
85 
setPtracer(qint64,qint64)86 void setPtracer(qint64, qint64)
87 {
88 }
89 
90 #endif
91