diff --git a/src/ioslaves/file/fdreceiver.h b/src/ioslaves/file/fdreceiver.h --- a/src/ioslaves/file/fdreceiver.h +++ b/src/ioslaves/file/fdreceiver.h @@ -42,6 +42,7 @@ QSocketNotifier *m_readNotifier; int m_socketDes; int m_fileDes; + QString m_path; }; #endif diff --git a/src/ioslaves/file/fdreceiver.cpp b/src/ioslaves/file/fdreceiver.cpp --- a/src/ioslaves/file/fdreceiver.cpp +++ b/src/ioslaves/file/fdreceiver.cpp @@ -19,6 +19,7 @@ ***/ #include +#include #include "sharefd_p.h" #include "fdreceiver.h" @@ -28,14 +29,20 @@ , m_readNotifier(nullptr) , m_socketDes(-1) , m_fileDes(-1) + , m_path(path) { + SocketAddress addr(m_path.toStdString()); + if (!addr.address()) { + std::cerr << "Invalid socket address" << std::endl; + return; + } + m_socketDes = ::socket(AF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0); if (m_socketDes == -1) { std::cerr << "socket error:" << strerror(errno) << std::endl; return; } - const SocketAddress addr(path.toStdString()); if (bind(m_socketDes, addr.address(), addr.length()) != 0 || listen(m_socketDes, 5) != 0) { std::cerr << "bind/listen error:" << strerror(errno) << std::endl; ::close(m_socketDes); @@ -52,6 +59,7 @@ if (m_socketDes >= 0) { ::close(m_socketDes); } + ::unlink(QFile::encodeName(m_path).constData()); } bool FdReceiver::isListening() const @@ -63,11 +71,30 @@ { int client = ::accept(m_socketDes, NULL, NULL); if (client > 0) { - FDMessageHeader msg; - if (::recvmsg(client, msg.message(), 0) == 2) { - ::memcpy(&m_fileDes, CMSG_DATA(msg.cmsgHeader()), sizeof m_fileDes); + // Receive fd only if socket owner is root + bool acceptConnection = false; +#if defined(__linux__) + ucred cred; + socklen_t len = sizeof(cred); + if (getsockopt(client, SOL_SOCKET, SO_PEERCRED, &cred, &len) == 0 && cred.uid == 0) { + acceptConnection = true; + } +#elif defined(__FreeBSD__) || defined(__APPLE__) + uid_t uid; + gid_t gid; + if (getpeereid(m_socketDes, &uid, &gid) == 0 && uid == 0) { + acceptConnection = true; + } +#else +#error Cannot get socket credentials! +#endif + if (acceptConnection) { + FDMessageHeader msg; + if (::recvmsg(client, msg.message(), 0) == 2) { + ::memcpy(&m_fileDes, CMSG_DATA(msg.cmsgHeader()), sizeof m_fileDes); + } + ::close(client); } - ::close(client); } } diff --git a/src/ioslaves/file/file.h b/src/ioslaves/file/file.h --- a/src/ioslaves/file/file.h +++ b/src/ioslaves/file/file.h @@ -103,16 +103,13 @@ void fileSystemFreeSpace(const QUrl &url); // KF6 TODO: Turn into virtual method in SlaveBase bool privilegeOperationUnitTestMode(); - PrivilegeOperationReturnValue execWithElevatedPrivilege(ActionType action, const QVariant &arg1, - const QVariant &arg2 = QVariant(), - const QVariant &arg3 = QVariant()); - PrivilegeOperationReturnValue tryOpen(QFile &f, const QByteArray &path, int flags, int mode); + PrivilegeOperationReturnValue execWithElevatedPrivilege(ActionType action, const QVariantList &args, int errcode); + PrivilegeOperationReturnValue tryOpen(QFile &f, const QByteArray &path, int flags, int mode, int errcode); // We want to execute chmod/chown/utime with elevated privileges (in copy & put) // only during the brief period privileges are elevated. If it's not the case show // a warning and continue. - PrivilegeOperationReturnValue tryChangeFileAttr(ActionType action, const QVariant &arg1, - const QVariant &arg2, const QVariant &arg3 = QVariant()); + PrivilegeOperationReturnValue tryChangeFileAttr(ActionType action, const QVariantList &args, int errcode); private: mutable QHash mUsercache; mutable QHash mGroupcache; diff --git a/src/ioslaves/file/file.cpp b/src/ioslaves/file/file.cpp --- a/src/ioslaves/file/file.cpp +++ b/src/ioslaves/file/file.cpp @@ -234,9 +234,9 @@ (setACL(_path.data(), permissions, false) == -1) || /* if not a directory, cannot set default ACLs */ (setACL(_path.data(), permissions, true) == -1 && errno != ENOTDIR)) { - if (auto err = execWithElevatedPrivilege(CHMOD, _path, permissions)) { + if (auto err = execWithElevatedPrivilege(CHMOD, {_path, permissions}, errno)) { if (!err.wasCanceled()) { - switch (errno) { + switch (err) { case EPERM: case EACCES: error(KIO::ERR_ACCESS_DENIED, path); @@ -269,7 +269,7 @@ utbuf.actime = statbuf.st_atime; // access time, unchanged utbuf.modtime = mtime.toTime_t(); // modification time if (::utime(QFile::encodeName(path).constData(), &utbuf) != 0) { - if (auto err = execWithElevatedPrivilege(UTIME, path, qint64(utbuf.actime), qint64(utbuf.modtime))) { + if (auto err = execWithElevatedPrivilege(UTIME, {path, qint64(utbuf.actime), qint64(utbuf.modtime)}, errno)) { if (!err.wasCanceled()) { // TODO: errno could be EACCES, EPERM, EROFS error(KIO::ERR_CANNOT_SETTIME, path); @@ -292,15 +292,15 @@ // Remove existing file or symlink, if requested (#151851) if (metaData(QStringLiteral("overwrite")) == QLatin1String("true")) { if (!QFile::remove(path)) { - execWithElevatedPrivilege(DEL, path); + execWithElevatedPrivilege(DEL, {path}, errno); } } QT_STATBUF buff; if (QT_LSTAT(QFile::encodeName(path).constData(), &buff) == -1) { bool dirCreated = QDir().mkdir(path); if (!dirCreated) { - if (auto err = execWithElevatedPrivilege(MKDIR, path)) { + if (auto err = execWithElevatedPrivilege(MKDIR, {path}, errno)) { if (!err.wasCanceled()) { //TODO: add access denied & disk full (or another reasons) handling (into Qt, possibly) error(KIO::ERR_CANNOT_MKDIR, path); @@ -361,7 +361,7 @@ QFile f(path); if (!f.open(QIODevice::ReadOnly)) { - if (auto err = tryOpen(f, QFile::encodeName(path), O_RDONLY, S_IRUSR)) { + if (auto err = tryOpen(f, QFile::encodeName(path), O_RDONLY, S_IRUSR, errno)) { if (!err.wasCanceled()) { error(KIO::ERR_CANNOT_OPEN_FOR_READING, path); } @@ -658,7 +658,7 @@ } } - if (auto err = tryOpen(f, QFile::encodeName(dest), oflags, filemode)) { + if (auto err = tryOpen(f, QFile::encodeName(dest), oflags, filemode, errno)) { if (!err.wasCanceled()) { // qDebug() << "####################### COULD NOT WRITE" << dest << "_mode=" << _mode; // qDebug() << "QFile error==" << f.error() << "(" << f.errorString() << ")"; @@ -673,7 +673,7 @@ } else { #ifndef Q_OS_WIN if ((_flags & KIO::Resume)) { - execWithElevatedPrivilege(CHOWN, dest, getuid(), getgid()); + execWithElevatedPrivilege(CHOWN, {dest, getuid(), getgid()}, errno); QFile::setPermissions(dest, modeToQFilePermissions(filemode)); } #endif @@ -732,12 +732,12 @@ //so we must remove it manually first if (_flags & KIO::Overwrite) { if (!QFile::remove(dest_orig)) { - execWithElevatedPrivilege(DEL, dest_orig); + execWithElevatedPrivilege(DEL, {dest_orig}, errno); } } if (!QFile::rename(dest, dest_orig)) { - if (auto err = execWithElevatedPrivilege(RENAME, dest, dest_orig)) { + if (auto err = execWithElevatedPrivilege(RENAME, {dest, dest_orig}, errno)) { if (!err.wasCanceled()) { qCWarning(KIO_FILE) << " Couldn't rename " << dest << " to " << dest_orig; error(KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig); @@ -752,7 +752,7 @@ if (_mode != -1 && !(_flags & KIO::Resume)) { if (!QFile::setPermissions(dest_orig, modeToQFilePermissions(_mode))) { // couldn't chmod. Eat the error if the filesystem apparently doesn't support it. - if (tryChangeFileAttr(CHMOD, dest_orig, _mode)) { + if (tryChangeFileAttr(CHMOD, {dest_orig, _mode}, errno)) { warning(i18n("Could not change permissions for\n%1", dest_orig)); } } @@ -779,7 +779,7 @@ utbuf.actime = dest_statbuf.st_atime; utbuf.modtime = dt.toTime_t(); if (utime(QFile::encodeName(dest_orig).constData(), &utbuf) != 0) { - tryChangeFileAttr(UTIME, dest_orig, qint64(utbuf.actime), qint64(utbuf.modtime)); + tryChangeFileAttr(UTIME, {dest_orig, qint64(utbuf.actime), qint64(utbuf.modtime)}, errno); } #endif } @@ -1392,7 +1392,7 @@ } else { //qDebug() << "QFile::remove" << itemPath; if (!QFile::remove(itemPath)) { - if (auto err = execWithElevatedPrivilege(DEL, itemPath)) { + if (auto err = execWithElevatedPrivilege(DEL, {itemPath}, errno)) { if (!err.wasCanceled()) { error(KIO::ERR_CANNOT_DELETE, itemPath); } @@ -1405,7 +1405,7 @@ Q_FOREACH (const QString &itemPath, dirsToDelete) { //qDebug() << "QDir::rmdir" << itemPath; if (!dir.rmdir(itemPath)) { - if (auto err = execWithElevatedPrivilege(RMDIR, itemPath)) { + if (auto err = execWithElevatedPrivilege(RMDIR, {itemPath}, errno)) { if (!err.wasCanceled()) { error(KIO::ERR_CANNOT_DELETE, itemPath); } diff --git a/src/ioslaves/file/file_p.h b/src/ioslaves/file/file_p.h --- a/src/ioslaves/file/file_p.h +++ b/src/ioslaves/file/file_p.h @@ -36,7 +36,7 @@ /** * PrivilegeOperationReturnValue encapsulates the return value from execWithElevatedPrivilege() in a convenient way. - * Warning, this class will cast to a bool that is false on success and true on failure. This unusual solution allows + * Warning, this class will cast to an int that is zero on success and non-zero on failure. This unusual solution allows * to write kioslave code like this: if (!dir.rmdir(itemPath)) { @@ -52,15 +52,16 @@ class PrivilegeOperationReturnValue { public: - static PrivilegeOperationReturnValue success() { return PrivilegeOperationReturnValue{false, false}; } - static PrivilegeOperationReturnValue failure() { return PrivilegeOperationReturnValue{true, false}; } - static PrivilegeOperationReturnValue canceled() { return PrivilegeOperationReturnValue{true, true}; } - operator bool() const { return m_failed; } + static PrivilegeOperationReturnValue success() { return PrivilegeOperationReturnValue{false, 0}; } + static PrivilegeOperationReturnValue canceled() { return PrivilegeOperationReturnValue{true, 0}; } + static PrivilegeOperationReturnValue failure(int error) { return PrivilegeOperationReturnValue{false, error}; } + operator int() const { return m_error; } + bool operator==(int error) const { return m_error == error; } bool wasCanceled() const { return m_canceled; } private: - PrivilegeOperationReturnValue(bool failed, bool canceled) : m_failed(failed), m_canceled(canceled) {} - const bool m_failed; + PrivilegeOperationReturnValue(bool canceled, int error) : m_canceled(canceled), m_error(error) {} const bool m_canceled; + const int m_error; }; #endif diff --git a/src/ioslaves/file/file_unix.cpp b/src/ioslaves/file/file_unix.cpp --- a/src/ioslaves/file/file_unix.cpp +++ b/src/ioslaves/file/file_unix.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ #include #include +#include #include "fdreceiver.h" @@ -69,20 +71,23 @@ static const QString socketPath() { - return QStringLiteral("org_kde_kio_file_helper_%1").arg(getpid()); + const QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); + return QStringLiteral("%1/filehelper%2%3").arg(runtimeDir).arg(KRandom::randomString(10)).arg(getpid()); } bool FileProtocol::privilegeOperationUnitTestMode() { return (metaData(QStringLiteral("UnitTesting")) == QLatin1String("true")) && (requestPrivilegeOperation() == KIO::OperationAllowed); } -PrivilegeOperationReturnValue FileProtocol::tryOpen(QFile &f, const QByteArray &path, int flags, int mode) +PrivilegeOperationReturnValue FileProtocol::tryOpen(QFile &f, const QByteArray &path, int flags, int mode, int errcode) { - FdReceiver fdRecv(socketPath()); + const QString sockPath = socketPath(); + QFile::remove(sockPath); + FdReceiver fdRecv(sockPath); if (!fdRecv.isListening()) { - return PrivilegeOperationReturnValue::failure(); + return PrivilegeOperationReturnValue::failure(errcode); } QIODevice::OpenMode openMode; @@ -102,26 +107,25 @@ openMode |= QIODevice::Append; } - if (auto err = execWithElevatedPrivilege(OPEN, path, flags, mode)) { + if (auto err = execWithElevatedPrivilege(OPEN, {path, flags, mode, sockPath}, errcode)) { return err; } else { int fd = fdRecv.fileDescriptor(); if (fd < 3 || !f.open(fd, openMode, QFileDevice::AutoCloseHandle)) { - return PrivilegeOperationReturnValue::failure(); + return PrivilegeOperationReturnValue::failure(errcode); } } return PrivilegeOperationReturnValue::success(); } -PrivilegeOperationReturnValue FileProtocol::tryChangeFileAttr(ActionType action, const QVariant &arg1, - const QVariant &arg2, const QVariant &arg3) +PrivilegeOperationReturnValue FileProtocol::tryChangeFileAttr(ActionType action, const QVariantList &args, int errcode) { KAuth::Action execAction(QStringLiteral("org.kde.kio.file.exec")); execAction.setHelperId(QStringLiteral("org.kde.kio.file")); if (execAction.status() == KAuth::Action::AuthorizedStatus) { - return execWithElevatedPrivilege(action, arg1, arg2, arg3); + return execWithElevatedPrivilege(action, args, errcode); } - return PrivilegeOperationReturnValue::failure(); + return PrivilegeOperationReturnValue::failure(errcode); } void FileProtocol::copy(const QUrl &srcUrl, const QUrl &destUrl, @@ -185,7 +189,7 @@ if ((_flags & KIO::Overwrite) && ((buff_dest.st_mode & QT_STAT_MASK) == QT_STAT_LNK)) { //qDebug() << "copy(): LINK DESTINATION"; if (!QFile::remove(dest)) { - if (auto err = execWithElevatedPrivilege(DEL, _dest)) { + if (auto err = execWithElevatedPrivilege(DEL, {_dest}, errno)) { if (!err.wasCanceled()) { error(KIO::ERR_CANNOT_DELETE_ORIGINAL, dest); } @@ -197,7 +201,7 @@ QFile src_file(src); if (!src_file.open(QIODevice::ReadOnly)) { - if (auto err = tryOpen(src_file, _src, O_RDONLY, S_IRUSR)) { + if (auto err = tryOpen(src_file, _src, O_RDONLY, S_IRUSR, errno)) { if (!err.wasCanceled()) { error(KIO::ERR_CANNOT_OPEN_FOR_READING, src); } @@ -211,10 +215,10 @@ QFile dest_file(dest); if (!dest_file.open(QIODevice::Truncate | QIODevice::WriteOnly)) { - if (auto err = tryOpen(dest_file, _dest, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) { + if (auto err = tryOpen(dest_file, _dest, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR, errno)) { if (!err.wasCanceled()) { // qDebug() << "###### COULD NOT WRITE " << dest; - if (errno == EACCES) { + if (err == EACCES) { error(KIO::ERR_WRITE_ACCESS_DENIED, dest); } else { error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest); @@ -227,9 +231,9 @@ // nobody shall be allowed to peek into the file during creation if (!QFile::setPermissions(dest, QFileDevice::ReadOwner | QFileDevice::WriteOwner)) { - if (auto err = execWithElevatedPrivilege(CHOWN, _dest, getuid(), getgid())) { + if (auto err = execWithElevatedPrivilege(CHOWN, {_dest, getuid(), getgid()}, errno)) { dest_file.close(); - execWithElevatedPrivilege(DEL, _dest); + execWithElevatedPrivilege(DEL, {_dest}, errno); if (!err.wasCanceled()) { error(KIO::ERR_CANNOT_CHOWN, dest); } @@ -299,7 +303,7 @@ } #endif if (!QFile::remove(dest)) { // don't keep partly copied file - execWithElevatedPrivilege(DEL, _dest); + execWithElevatedPrivilege(DEL, {_dest}, errno); } return; } @@ -322,7 +326,7 @@ } #endif if (!QFile::remove(dest)) { // don't keep partly copied file - execWithElevatedPrivilege(DEL, _dest); + execWithElevatedPrivilege(DEL, {_dest}, errno); } return; } @@ -345,7 +349,7 @@ } #endif if (!QFile::remove(dest)) { // don't keep partly copied file - execWithElevatedPrivilege(DEL, _dest); + execWithElevatedPrivilege(DEL, {_dest}, errno); } return; } @@ -361,7 +365,7 @@ || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0) #endif ) { - if (tryChangeFileAttr(CHMOD, _dest, _mode)) { + if (tryChangeFileAttr(CHMOD, {_dest, _mode}, errno)) { warning(i18n("Could not change permissions for '%1'", dest)); } } @@ -377,7 +381,7 @@ // we might not be allowed to change the owner (void)::chown(_dest.data(), buff_src.st_uid, -1 /*keep group*/); } else { - if (tryChangeFileAttr(CHOWN, _dest, buff_src.st_uid, buff_src.st_gid)) { + if (tryChangeFileAttr(CHOWN, {_dest, buff_src.st_uid, buff_src.st_gid}, errno)) { qCWarning(KIO_FILE) << QStringLiteral("Couldn't preserve group for '%1'").arg(dest); } } @@ -387,7 +391,7 @@ ut.actime = buff_src.st_atime; ut.modtime = buff_src.st_mtime; if (::utime(_dest.data(), &ut) != 0) { - if (tryChangeFileAttr(UTIME, _dest, qint64(ut.actime), qint64(ut.modtime))) { + if (tryChangeFileAttr(UTIME, {_dest, qint64(ut.actime), qint64(ut.modtime)}, errno)) { qCWarning(KIO_FILE) << QStringLiteral("Couldn't preserve access and modification time for '%1'").arg(dest); } } @@ -564,13 +568,13 @@ } if (::rename(_src.data(), _dest.data())) { - if (auto err = execWithElevatedPrivilege(RENAME, _src, _dest)) { + if (auto err = execWithElevatedPrivilege(RENAME, {_src, _dest}, errno)) { if (!err.wasCanceled()) { - if ((errno == EACCES) || (errno == EPERM)) { + if ((err == EACCES) || (err == EPERM)) { error(KIO::ERR_ACCESS_DENIED, dest); - } else if (errno == EXDEV) { + } else if (err == EXDEV) { error(KIO::ERR_UNSUPPORTED_ACTION, QStringLiteral("rename")); - } else if (errno == EROFS) { // The file is on a read-only filesystem + } else if (err == EROFS) { // The file is on a read-only filesystem error(KIO::ERR_CANNOT_DELETE, src); } else { error(KIO::ERR_CANNOT_RENAME, src); @@ -593,7 +597,7 @@ if ((flags & KIO::Overwrite)) { // Try to delete the destination if (unlink(QFile::encodeName(dest).constData()) != 0) { - if (auto err = execWithElevatedPrivilege(DEL, dest)) { + if (auto err = execWithElevatedPrivilege(DEL, {dest}, errno)) { if (!err.wasCanceled()) { error(KIO::ERR_CANNOT_DELETE, dest); } @@ -613,7 +617,7 @@ return; } } else { - if (auto err = execWithElevatedPrivilege(SYMLINK, dest, target)) { + if (auto err = execWithElevatedPrivilege(SYMLINK, {dest, target}, errno)) { if (!err.wasCanceled()) { // Some error occurred while we tried to symlink error(KIO::ERR_CANNOT_SYMLINK, dest); @@ -637,11 +641,11 @@ // qDebug() << "Deleting file "<< url; if (unlink(_path.data()) == -1) { - if (auto err = execWithElevatedPrivilege(DEL, _path)) { + if (auto err = execWithElevatedPrivilege(DEL, {_path}, errno)) { if (!err.wasCanceled()) { - if ((errno == EACCES) || (errno == EPERM)) { + if ((err == EACCES) || (err == EPERM)) { error(KIO::ERR_ACCESS_DENIED, path); - } else if (errno == EISDIR) { + } else if (err == EISDIR) { error(KIO::ERR_IS_DIRECTORY, path); } else { error(KIO::ERR_CANNOT_DELETE, path); @@ -663,9 +667,9 @@ } } if (QT_RMDIR(_path.data()) == -1) { - if (auto err = execWithElevatedPrivilege(RMDIR, _path)) { + if (auto err = execWithElevatedPrivilege(RMDIR, {_path}, errno)) { if (!err.wasCanceled()) { - if ((errno == EACCES) || (errno == EPERM)) { + if ((err == EACCES) || (err == EPERM)) { error(KIO::ERR_ACCESS_DENIED, path); } else { // qDebug() << "could not rmdir " << perror; @@ -714,9 +718,9 @@ } if (::chown(_path.constData(), uid, gid) == -1) { - if (auto err = execWithElevatedPrivilege(CHOWN, _path, uid, gid)) { + if (auto err = execWithElevatedPrivilege(CHOWN, {_path, uid, gid}, errno)) { if (!err.wasCanceled()) { - switch (errno) { + switch (err) { case EPERM: case EACCES: error(KIO::ERR_ACCESS_DENIED, path); @@ -775,45 +779,42 @@ finished(); } -PrivilegeOperationReturnValue FileProtocol::execWithElevatedPrivilege(ActionType action, const QVariant &arg1, - const QVariant &arg2, const QVariant &arg3) +PrivilegeOperationReturnValue FileProtocol::execWithElevatedPrivilege(ActionType action, const QVariantList &args, int errcode) { if (privilegeOperationUnitTestMode()) { return PrivilegeOperationReturnValue::success(); } - // temporarily disable privilege execution if (true) { - return PrivilegeOperationReturnValue::failure(); + return PrivilegeOperationReturnValue::failure(errcode); } - if (!(errno == EACCES || errno == EPERM)) { - return PrivilegeOperationReturnValue::failure(); + if (!(errcode == EACCES || errcode == EPERM)) { + return PrivilegeOperationReturnValue::failure(errcode); } KIO::PrivilegeOperationStatus opStatus = requestPrivilegeOperation(); if (opStatus != KIO::OperationAllowed) { if (opStatus == KIO::OperationCanceled) { error(KIO::ERR_USER_CANCELED, QString()); return PrivilegeOperationReturnValue::canceled(); } - return PrivilegeOperationReturnValue::failure(); + return PrivilegeOperationReturnValue::failure(errcode); } if (action == CHMOD || action == CHOWN || action == UTIME) { - KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(arg1.toString()); + KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(args.first().toString()); // Test for chmod and utime will return the same result as test for chown. if (mp && !mp->testFileSystemFlag(KMountPoint::SupportsChown)) { - return PrivilegeOperationReturnValue::failure(); + return PrivilegeOperationReturnValue::failure(errcode); } } QByteArray helperArgs; QDataStream out(&helperArgs, QIODevice::WriteOnly); - out << action << arg1 << arg2 << arg3; - - if (action == OPEN || action == OPENDIR) { - out << QVariant::fromValue(socketPath()); + out << action; + foreach (const QVariant &arg, args) { + out << arg; } KAuth::Action execAction(QStringLiteral("org.kde.kio.file.exec")); @@ -828,5 +829,5 @@ return PrivilegeOperationReturnValue::success(); } - return PrivilegeOperationReturnValue::failure(); + return PrivilegeOperationReturnValue::failure(errcode); } diff --git a/src/ioslaves/file/file_win.cpp b/src/ioslaves/file/file_win.cpp --- a/src/ioslaves/file/file_win.cpp +++ b/src/ioslaves/file/file_win.cpp @@ -387,17 +387,16 @@ return false; } -PrivilegeOperationReturnValue FileProtocol::execWithElevatedPrivilege(ActionType, const QVariant &, - const QVariant &, const QVariant &) +PrivilegeOperationReturnValue FileProtocol::execWithElevatedPrivilege(ActionType, const QVariantList &, int) { return PrivilegeOperationReturnValue::failure(); } -PrivilegeOperationReturnValue FileProtocol::tryOpen(QFile &f, const QByteArray &, int , int) +PrivilegeOperationReturnValue FileProtocol::tryOpen(QFile &, const QByteArray &, int , int, int) { return PrivilegeOperationReturnValue::failure(); } -PrivilegeOperationReturnValue FileProtocol::tryChangeFileAttr(ActionType , const QVariant &, const QVariant &, const QVariant &) +PrivilegeOperationReturnValue FileProtocol::tryChangeFileAttr(ActionType , const QVariantList &, int) { return PrivilegeOperationReturnValue::failure(); } diff --git a/src/ioslaves/file/kauth/fdsender.cpp b/src/ioslaves/file/kauth/fdsender.cpp --- a/src/ioslaves/file/kauth/fdsender.cpp +++ b/src/ioslaves/file/kauth/fdsender.cpp @@ -24,13 +24,18 @@ FdSender::FdSender(const std::string &path) : m_socketDes(-1) { + SocketAddress addr(path); + if (!addr.address()) { + std::cerr << "Invalid socket address" << std::endl; + return; + } + m_socketDes = ::socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); if (m_socketDes == -1) { std::cerr << "socket error:" << strerror(errno) << std::endl; return; } - SocketAddress addr(path); if (::connect(m_socketDes, addr.address(), addr.length()) != 0) { std::cerr << "connection error:" << strerror(errno) << std::endl; ::close(m_socketDes); diff --git a/src/ioslaves/file/sharefd_p.h b/src/ioslaves/file/sharefd_p.h --- a/src/ioslaves/file/sharefd_p.h +++ b/src/ioslaves/file/sharefd_p.h @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include // fix SOCK_NONBLOCK for e.g. macOS #ifndef SOCK_NONBLOCK @@ -41,24 +44,22 @@ int length() const { - return sizeof addr; + return offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1; } const sockaddr *address() const { - return reinterpret_cast(&addr); + return addr.sun_path[0] ? reinterpret_cast(&addr) : nullptr; } private: static sockaddr_un make_address(const std::string& path) { - sockaddr_un a{ AF_UNIX, {0}}; - std::string finalPath = "/tmp/" + path; -#ifdef __linux__ - ::strcpy(&a.sun_path[1], finalPath.c_str()); -#else - ::strcpy(a.sun_path, finalPath.c_str()); - ::unlink(finalPath.c_str()); -#endif + sockaddr_un a; + memset(&a, 0, sizeof(a)); + a.sun_family = AF_UNIX; + if (path.length() > 0 && path.length() < sizeof(a.sun_path)-1) { + ::strncpy(a.sun_path, path.c_str(), sizeof(a.sun_path)-1); + } return a; } };