Skip to content

Commit

Permalink
Merge pull request #1449 from aleixpol/fix_priv_drop
Browse files Browse the repository at this point in the history
Address privilege dropping
  • Loading branch information
aleixpol committed Oct 20, 2021
2 parents 513546d + 725e312 commit c7e8a9f
Show file tree
Hide file tree
Showing 18 changed files with 467 additions and 264 deletions.
11 changes: 2 additions & 9 deletions src/auth/Auth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ namespace SDDM {
bool autologin { false };
bool greeter { false };
QProcessEnvironment environment { };
qint64 sessionPid { -1 };
qint64 id { 0 };
static qint64 lastId;
};
Expand Down Expand Up @@ -194,10 +193,8 @@ namespace SDDM {
}
case SESSION_STATUS: {
bool status;
qint64 pid; //not pid_t as we need to define the wire type
str >> status >> pid;
sessionPid = pid;
Q_EMIT auth->sessionStarted(status, pid);
str >> status;
Q_EMIT auth->sessionStarted(status);
str.reset();
str << SESSION_STATUS;
str.send();
Expand Down Expand Up @@ -301,10 +298,6 @@ namespace SDDM {
return d->request;
}

qint64 Auth::sessionPid() const {
return d->sessionPid;
}

bool Auth::isActive() const {
return d->child->state() != QProcess::NotRunning;
}
Expand Down
4 changes: 1 addition & 3 deletions src/auth/Auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ namespace SDDM {
const QString &cookie() const;
const QString &user() const;
const QString &session() const;
qint64 sessionPid() const;

AuthRequest *request();
/**
* True if an authentication or session is in progress
Expand Down Expand Up @@ -199,7 +197,7 @@ namespace SDDM {
*
* @param success true if succeeded
*/
void sessionStarted(bool success, qint64 pid);
void sessionStarted(bool success);

/**
* Emitted when the display server is ready.
Expand Down
36 changes: 31 additions & 5 deletions src/common/VirtualTerminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <linux/vt.h>
#include <linux/kd.h>
#include <sys/ioctl.h>
#include <qscopeguard.h>

#define RELEASE_DISPLAY_SIGNAL (SIGRTMAX)
#define ACQUIRE_DISPLAY_SIGNAL (SIGRTMAX - 1)
Expand Down Expand Up @@ -115,32 +116,57 @@ namespace SDDM {
qDebug() << "VT mode didn't need to be fixed";
}

int setUpNewVt() {
int fetchAvailableVt() {
// open VT master
int fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
if (fd < 0) {
qCritical() << "Failed to open VT master:" << strerror(errno);
return -1;
}
auto closeFd = qScopeGuard([fd] {
close(fd);
});

vt_stat vtState = { 0 };
if (ioctl(fd, VT_GETSTATE, &vtState) < 0) {
qCritical() << "Failed to get current VT:" << strerror(errno);
close(fd);

int vt = 0;
// If there's no current tty, request the next to open
if (ioctl(fd, VT_OPENQRY, &vt) < 0) {
qCritical() << "Failed to open new VT:" << strerror(errno);
return -1;
}
return vt;
}
return vtState.v_active;
}

int setUpNewVt() {
// open VT master
int fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
if (fd < 0) {
qCritical() << "Failed to open VT master:" << strerror(errno);
return -1;
}
auto closeFd = qScopeGuard([fd] {
close(fd);
});

int vt = 0;
if (ioctl(fd, VT_OPENQRY, &vt) < 0) {
qCritical() << "Failed to open new VT:" << strerror(errno);
close(fd);
return -1;
}

close(fd);

// fallback to active VT
if (vt <= 0) {
vt_stat vtState = { 0 };
if (ioctl(fd, VT_GETSTATE, &vtState) < 0) {
qCritical() << "Failed to get current VT:" << strerror(errno);
return -1;
}

qWarning() << "New VT" << vt << "is not valid, fall back to" << vtState.v_active;
return vtState.v_active;
}
Expand Down
1 change: 1 addition & 0 deletions src/common/VirtualTerminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

namespace SDDM {
namespace VirtualTerminal {
int fetchAvailableVt();
int setUpNewVt();
void jumpToVt(int vt, bool vt_auto);
}
Expand Down
122 changes: 7 additions & 115 deletions src/daemon/Display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include <QFile>
#include <QTimer>
#include <QLocalSocket>
#include <QByteArray>

#include <pwd.h>
#include <unistd.h>
Expand All @@ -49,10 +48,6 @@
#include "VirtualTerminal.h"
#include "WaylandDisplayServer.h"

#if defined(Q_OS_LINUX)
#include <utmp.h>
#endif
#include <utmpx.h>

namespace SDDM {
Display::Display(Seat *parent) : QObject(parent),
Expand Down Expand Up @@ -139,10 +134,6 @@ namespace SDDM {
return m_displayServer;
}

QString Display::displayId() const {
return m_displayServer->display();
}

const int Display::terminalId() const {
return m_terminalId;
}
Expand Down Expand Up @@ -373,11 +364,14 @@ namespace SDDM {

// New VT
if (session.xdgSessionType() != QLatin1String("x11") || m_displayServerType != X11DisplayServerType) {
m_lastSession.setVt(VirtualTerminal::setUpNewVt());
if (m_displayServerType == X11DisplayServerType)
m_lastSession.setVt(VirtualTerminal::setUpNewVt());
else
m_lastSession.setVt(VirtualTerminal::fetchAvailableVt());
}

// some information
qDebug() << "Session" << m_sessionName << "selected, command:" << session.exec();
qDebug() << "Session" << m_sessionName << "selected, command:" << session.exec() << "for VT" << m_lastSession.vt();

QProcessEnvironment env;
env.insert(session.additionalEnv());
Expand Down Expand Up @@ -437,7 +431,6 @@ namespace SDDM {
if (m_socket)
emit loginSucceeded(m_socket);
} else if (m_socket) {
utmpLogin(QString::number(terminalId()), name(), user, 0, false);
qDebug() << "Authentication failure";
emit loginFailed(m_socket);
}
Expand All @@ -462,10 +455,6 @@ namespace SDDM {
}

void Display::slotHelperFinished(Auth::HelperExitStatus status) {
if (m_auth->sessionPid() > 0) {
utmpLogout(QString::number(terminalId()), name(), m_auth->sessionPid());
}

// Don't restart greeter and display server unless sddm-helper exited
// with an internal error or the user session finished successfully,
// we want to avoid greeter from restarting when an authentication
Expand All @@ -490,104 +479,7 @@ namespace SDDM {
}
}

void Display::slotSessionStarted(bool success, qint64 pid) {
if (success) {
utmpLogin(QString::number(terminalId()), name(), m_auth->user(), pid, true);
}
void Display::slotSessionStarted(bool success) {
qDebug() << "Session started";
}

void Display::utmpLogin(const QString &vt, const QString &displayName, const QString &user, qint64 pid, bool authSuccessful) {
struct utmpx entry;
struct timeval tv;

entry = { 0 };
entry.ut_type = USER_PROCESS;
entry.ut_pid = pid;

// ut_line: vt
if (!vt.isEmpty()) {
QString tty = QStringLiteral("tty");
tty.append(vt);
QByteArray ttyBa = tty.toLocal8Bit();
const char* ttyChar = ttyBa.constData();
strncpy(entry.ut_line, ttyChar, sizeof(entry.ut_line) - 1);
}

// ut_host: displayName
QByteArray displayBa = displayName.toLocal8Bit();
const char* displayChar = displayBa.constData();
strncpy(entry.ut_host, displayChar, sizeof(entry.ut_host) - 1);

// ut_user: user
QByteArray userBa = user.toLocal8Bit();
const char* userChar = userBa.constData();
strncpy(entry.ut_user, userChar, sizeof(entry.ut_user) -1);

gettimeofday(&tv, NULL);
entry.ut_tv.tv_sec = tv.tv_sec;
entry.ut_tv.tv_usec = tv.tv_usec;

// write to utmp
setutxent();
if (!pututxline (&entry))
qWarning() << "Failed to write utmpx: " << strerror(errno);
endutxent();

#if !defined(Q_OS_FREEBSD)
// append to failed login database btmp
if (!authSuccessful) {
#if defined(Q_OS_LINUX)
updwtmpx("/var/log/btmp", &entry);
#endif
}

// append to wtmp
else {
#if defined(Q_OS_LINUX)
updwtmpx("/var/log/wtmp", &entry);
#endif
}
#endif
}

void Display::utmpLogout(const QString &vt, const QString &displayName, qint64 pid) {
struct utmpx entry;
struct timeval tv;

entry = { 0 };
entry.ut_type = DEAD_PROCESS;
entry.ut_pid = pid;

// ut_line: vt
if (!vt.isEmpty()) {
QString tty = QStringLiteral("tty");
tty.append(vt);
QByteArray ttyBa = tty.toLocal8Bit();
const char* ttyChar = ttyBa.constData();
strncpy(entry.ut_line, ttyChar, sizeof(entry.ut_line) - 1);
}

// ut_host: displayName
QByteArray displayBa = displayName.toLocal8Bit();
const char* displayChar = displayBa.constData();
strncpy(entry.ut_host, displayChar, sizeof(entry.ut_host) - 1);

gettimeofday(&tv, NULL);
entry.ut_tv.tv_sec = tv.tv_sec;
entry.ut_tv.tv_usec = tv.tv_usec;

// write to utmp
setutxent();
if (!pututxline (&entry))
qWarning() << "Failed to write utmpx: " << strerror(errno);
endutxent();

#if defined(Q_OS_LINUX)
// append to wtmp
updwtmpx("/var/log/wtmp", &entry);
#elif defined(Q_OS_FREEBSD)
pututxline(&entry);
#endif
}

}
21 changes: 1 addition & 20 deletions src/daemon/Display.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ namespace SDDM {
DisplayServerType displayServerType() const;
DisplayServer *displayServer() const;

QString displayId() const;
const int terminalId() const;

const QString &name() const;
Expand Down Expand Up @@ -106,28 +105,10 @@ namespace SDDM {
QLocalSocket *m_socket { nullptr };
Greeter *m_greeter { nullptr };

/*!
\brief Write utmp/wtmp/btmp records when a user logs in
\param vt Virtual terminal (tty7, tty8,...)
\param displayName Display (:0, :1,...)
\param user User logging in
\param pid User process ID (e.g. PID of startkde)
\param authSuccessful Was authentication successful
*/
void utmpLogin(const QString &vt, const QString &displayName, const QString &user, qint64 pid, bool authSuccessful);

/*!
\brief Write utmp/wtmp records when a user logs out
\param vt Virtual terminal (tty7, tty8,...)
\param displayName Display (:0, :1,...)
\param pid User process ID (e.g. PID of startkde)
*/
void utmpLogout(const QString &vt, const QString &displayName, qint64 pid);

private slots:
void slotRequestChanged();
void slotAuthenticationFinished(const QString &user, bool success);
void slotSessionStarted(bool success, qint64 pid);
void slotSessionStarted(bool success);
void slotHelperFinished(Auth::HelperExitStatus status);
void slotAuthInfo(const QString &message, Auth::Info info);
void slotAuthError(const QString &message, Auth::Error error);
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/Seat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ namespace SDDM {
}

void Seat::removeDisplay(Display* display) {
qDebug() << "Removing display" << display->displayId() << "...";
qDebug() << "Removing display" << display << "...";


// remove display from list
Expand Down
22 changes: 16 additions & 6 deletions src/helper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ set(HELPER_SOURCES
Backend.cpp
HelperApp.cpp
UserSession.cpp
xorguserhelper.cpp
xorguserhelper.h
waylandhelper.cpp
waylandsocketwatcher.cpp
)

# Different implementations of the VT switching code
Expand Down Expand Up @@ -66,8 +62,22 @@ else()
target_link_libraries(sddm-helper crypt)
endif()

install(TARGETS sddm-helper RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}")

add_executable(sddm-helper-start-wayland HelperStartWayland.cpp waylandsocketwatcher.cpp waylandhelper.cpp)
target_link_libraries(sddm-helper-start-wayland Qt5::Core)
install(TARGETS sddm-helper-start-wayland RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}")

add_executable(sddm-helper-start-x11user HelperStartX11User.cpp xorguserhelper.cpp
${CMAKE_SOURCE_DIR}/src/common/ConfigReader.cpp
${CMAKE_SOURCE_DIR}/src/common/Configuration.cpp
${CMAKE_SOURCE_DIR}/src/common/XAuth.cpp
)
target_link_libraries(sddm-helper-start-x11user Qt5::Core)
install(TARGETS sddm-helper-start-x11user RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}")

if(JOURNALD_FOUND)
target_link_libraries(sddm-helper ${JOURNALD_LIBRARIES})
target_link_libraries(sddm-helper-start-x11user ${JOURNALD_LIBRARIES})
target_link_libraries(sddm-helper-start-wayland ${JOURNALD_LIBRARIES})
endif()

install(TARGETS sddm-helper RUNTIME DESTINATION "${CMAKE_INSTALL_LIBEXECDIR}")

0 comments on commit c7e8a9f

Please sign in to comment.