Index: src/ioslaves/file/file_unix.cpp =================================================================== --- src/ioslaves/file/file_unix.cpp +++ src/ioslaves/file/file_unix.cpp @@ -40,6 +40,7 @@ #include #include +#include "sharefd.h" //sendfile has different semantics in different platforms #if defined HAVE_SENDFILE && defined Q_OS_LINUX @@ -120,14 +121,28 @@ // the symlink actually points to current source! if ((_flags & KIO::Overwrite) && ((buff_dest.st_mode & QT_STAT_MASK) == QT_STAT_LNK)) { //qDebug() << "copy(): LINK DESTINATION"; - QFile::remove(dest); + if (!QFile::remove(dest)) { + if (!execWithElevatedPrivilege(DEL, _dest)) { + error(KIO::ERR_CANNOT_DELETE_ORIGINAL, dest); + return; + } + } } } QFile src_file(src); if (!src_file.open(QIODevice::ReadOnly)) { - error(KIO::ERR_CANNOT_OPEN_FOR_READING, src); - return; + int src_fd = -1; + FdReceiver fdRecv; + bool _continue = ( fdRecv.startListening(QStringLiteral("org_kde_kio_file_helper_socket")) + && execWithElevatedPrivilege(OPEN, _src, O_RDONLY, S_IRUSR) + && (src_fd = fdRecv.fileDescriptor()) != -1 + && src_file.open(src_fd, QIODevice::ReadOnly, QFileDevice::AutoCloseHandle)); + + if (!_continue) { + error(KIO::ERR_CANNOT_OPEN_FOR_READING, src); + return; + } } #if HAVE_FADVISE @@ -137,17 +152,35 @@ QFile dest_file(dest); if (!dest_file.open(QIODevice::Truncate | QIODevice::WriteOnly)) { // qDebug() << "###### COULD NOT WRITE " << dest; - if (errno == EACCES) { - error(KIO::ERR_WRITE_ACCESS_DENIED, dest); - } else { - error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest); + int dest_fd = -1; + FdReceiver fdRecv; + bool _continue = ( fdRecv.startListening(QStringLiteral("org_kde_kio_file_helper_socket")) + && execWithElevatedPrivilege(OPEN, _dest, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR) + && (dest_fd = fdRecv.fileDescriptor()) != -1 + && dest_file.open(dest_fd, QIODevice::WriteOnly | QIODevice::Truncate, QFileDevice::AutoCloseHandle)); + + if (!_continue) { + if (errno == EACCES) { + error(KIO::ERR_WRITE_ACCESS_DENIED, dest); + } else { + error(KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest); + } + src_file.close(); + return; } - src_file.close(); - return; } // nobody shall be allowed to peek into the file during creation - dest_file.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner); + if (!QFile::setPermissions(dest, QFileDevice::ReadOwner | QFileDevice::WriteOwner)) { + // File was created by root user with the above permissions. We only need to + // change its owner. + if (!execWithElevatedPrivilege(CHOWN, _dest, getuid(), getgid())) { + dest_file.close(); + execWithElevatedPrivilege(DEL, _dest); + error(KIO::ERR_CANNOT_CHOWN, dest); + return; + } + } #if HAVE_FADVISE posix_fadvise(dest_file.handle(), 0, 0, POSIX_FADV_SEQUENTIAL); @@ -208,7 +241,9 @@ acl_free(acl); } #endif - dest_file.remove(); // don't keep partly copied file + if (!QFile::remove(dest)) { // don't keep partly copied file + execWithElevatedPrivilege(DEL, _dest); + } return; } if (n == 0) { @@ -229,7 +264,9 @@ acl_free(acl); } #endif - dest_file.remove(); // don't keep partly copied file + if (!QFile::remove(dest)) { // don't keep partly copied file + execWithElevatedPrivilege(DEL, _dest); + } return; } processed_size += n; @@ -250,7 +287,9 @@ acl_free(acl); } #endif - dest_file.remove(); // don't keep partly copied file + if (!QFile::remove(dest)) { // don't keep partly copied file + execWithElevatedPrivilege(DEL, _dest); + } return; } @@ -265,10 +304,12 @@ || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0) #endif ) { - KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest); - // Eat the error if the filesystem apparently doesn't support chmod. - if (mp && mp->testFileSystemFlag(KMountPoint::SupportsChmod)) { - warning(i18n("Could not change permissions for '%1'", dest)); + if (!execWithElevatedPrivilege(CHMOD, _dest, _mode)) { + KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByPath(dest); + // Eat the error if the filesystem apparently doesn't support chmod. + if (mp && mp->testFileSystemFlag(KMountPoint::SupportsChmod)) { + warning(i18n("Could not change permissions for '%1'", dest)); + } } } #if HAVE_POSIX_ACL @@ -283,15 +324,19 @@ // we might not be allowed to change the owner (void)::chown(_dest.data(), buff_src.st_uid, -1 /*keep group*/); } else { - qCWarning(KIO_FILE) << QStringLiteral("Couldn't preserve group for '%1'").arg(dest); + if (!execWithElevatedPrivilege(CHOWN, _dest, buff_src.st_uid, buff_src.st_gid)) + qCWarning(KIO_FILE) << QStringLiteral("Couldn't preserve group for '%1'").arg(dest); } // copy access and modification time struct utimbuf ut; ut.actime = buff_src.st_atime; ut.modtime = buff_src.st_mtime; if (::utime(_dest.data(), &ut) != 0) { - qCWarning(KIO_FILE) << QStringLiteral("Couldn't preserve access and modification time for '%1'").arg(dest); + // atime and modtime are of type long so not usable with QVariant. + if (!execWithElevatedPrivilege(UTIME, _dest, qint64(ut.actime), qint64(ut.modtime))) { + qCWarning(KIO_FILE) << QStringLiteral("Couldn't preserve access and modification time for '%1'").arg(dest); + } } processedSize(buff_src.st_size);