diff -Nru aptdaemon-1.1.1/debian/changelog aptdaemon-1.1.1/debian/changelog --- aptdaemon-1.1.1/debian/changelog 2014-06-06 13:19:42.000000000 +0200 +++ aptdaemon-1.1.1/debian/changelog 2015-05-29 22:04:16.000000000 +0200 @@ -1,3 +1,9 @@ +aptdaemon (1.1.1-1ubuntu5.2) trusty-security; urgency=low + + * Fix LP: #1449587 (CVE-2015-1323) + + -- Michael Vogt Fri, 29 May 2015 22:03:59 +0200 + aptdaemon (1.1.1-1ubuntu5.1) trusty-proposed; urgency=low [ Brian Murray ] diff -Nru aptdaemon-1.1.1/debian/patches/lp1449587.diff aptdaemon-1.1.1/debian/patches/lp1449587.diff --- aptdaemon-1.1.1/debian/patches/lp1449587.diff 1970-01-01 01:00:00.000000000 +0100 +++ aptdaemon-1.1.1/debian/patches/lp1449587.diff 2015-05-29 22:04:16.000000000 +0200 @@ -0,0 +1,349 @@ +=== modified file 'aptdaemon/core.py' +Index: aptdaemon-1.1.1/aptdaemon/core.py +=================================================================== +--- aptdaemon-1.1.1.orig/aptdaemon/core.py ++++ aptdaemon-1.1.1/aptdaemon/core.py +@@ -342,7 +342,7 @@ class Transaction(DBusObject): + "DebconfSocket", "MetaData", "Locale", + "RemoveObsoleteDepends") + +- def __init__(self, tid, role, queue, pid, uid, cmdline, sender, ++ def __init__(self, tid, role, queue, pid, uid, gid, cmdline, sender, + connect=True, bus=None, packages=None, kwargs=None): + """Initialize a new Transaction instance. + +@@ -378,6 +378,7 @@ class Transaction(DBusObject): + kwargs = {} + self.queue = queue + self.uid = uid ++ self.gid = gid + self.locale = dbus.String("") + self.allow_unauthenticated = dbus.Boolean(False) + self.remove_obsoleted_depends = dbus.Boolean(False) +@@ -1538,11 +1539,12 @@ class AptDaemon(DBusObject): + @inline_callbacks + def _create_trans(self, role, sender, packages=None, kwargs=None): + """Helper method which returns the tid of a new transaction.""" +- pid, uid, cmdline = ( ++ pid, uid, gid, cmdline = ( + yield policykit1.get_proc_info_from_dbus_name(sender, self.bus)) + tid = uuid.uuid4().hex +- trans = Transaction(tid, role, self.queue, pid, uid, cmdline, sender, +- packages=packages, kwargs=kwargs, bus=self.bus) ++ trans = Transaction( ++ tid, role, self.queue, pid, uid, gid, cmdline, sender, ++ packages=packages, kwargs=kwargs, bus=self.bus) + self.queue.limbo[trans.tid] = trans + return_value(trans.tid) + +Index: aptdaemon-1.1.1/aptdaemon/pkcompat.py +=================================================================== +--- aptdaemon-1.1.1.orig/aptdaemon/pkcompat.py ++++ aptdaemon-1.1.1/aptdaemon/pkcompat.py +@@ -469,9 +469,10 @@ class PackageKit(core.DBusObject): + + @inline_callbacks + def _create_transaction(self, sender): +- pid, uid, cmdline = yield policykit1.get_proc_info_from_dbus_name( ++ pid, uid, gid, cmdline = yield policykit1.get_proc_info_from_dbus_name( + sender, self.bus) +- pktrans = PackageKitTransaction(pid, uid, cmdline, self.queue, sender) ++ pktrans = PackageKitTransaction( ++ pid, uid, gid, cmdline, self.queue, sender) + return_value(pktrans.tid) + + # pylint: disable-msg=C0103,C0322 +@@ -602,7 +603,7 @@ class MergedTransaction(core.Transaction + def __init__(self, pktrans, role, queue, connect=True, + bus=None, packages=None, kwargs=None): + core.Transaction.__init__(self, pktrans.tid[1:], role, queue, +- pktrans.pid, pktrans.uid, ++ pktrans.pid, pktrans.uid, pktrans.gid, + pktrans.cmdline, pktrans.sender, + connect, bus, packages, kwargs) + self.pktrans = pktrans +@@ -758,7 +759,7 @@ class PackageKitTransaction(core.DBusObj + + """Provides a PackageKit transaction object.""" + +- def __init__(self, pid, uid, cmdline, queue, sender, ++ def __init__(self, pid, uid, gid, cmdline, queue, sender, + connect=True, bus=None): + pklog.info("Initializing PackageKit transaction") + bus_name = None +@@ -784,6 +785,7 @@ class PackageKitTransaction(core.DBusObj + self._status = pk.StatusEnum.SETUP + self._last_package = "" + self.uid = dbus.UInt32(uid) ++ self.gid = dbus.UInt32(gid) + self.pid = pid + self.cmdline = cmdline + self.role = pk.RoleEnum.UNKNOWN +Index: aptdaemon-1.1.1/aptdaemon/policykit1.py +=================================================================== +--- aptdaemon-1.1.1.orig/aptdaemon/policykit1.py ++++ aptdaemon-1.1.1/aptdaemon/policykit1.py +@@ -161,12 +161,15 @@ def get_proc_info_from_dbus_name(dbus_na + bus = dbus.SystemBus() + pid = yield get_pid_from_dbus_name(dbus_name, bus) + with open("/proc/%s/status" % pid) as proc: +- values = [v for v in proc.readlines() if v.startswith("Uid:")] ++ lines = proc.readlines() ++ uid_values = [v for v in lines if v.startswith("Uid:")] ++ gid_values = [v for v in lines if v.startswith("Gid:")] + # instead of ", encoding='utf8'" we use the "rb"/decode() here for + # py2 compatibility + with open("/proc/%s/cmdline" % pid, "rb") as cmdline_file: + cmdline = cmdline_file.read().decode("utf-8") +- uid = int(values[0].split()[1]) +- return_value((pid, uid, cmdline)) ++ uid = int(uid_values[0].split()[1]) ++ gid = int(gid_values[0].split()[1]) ++ return_value((pid, uid, gid, cmdline)) + + # vim:ts=4:sw=4:et +Index: aptdaemon-1.1.1/aptdaemon/progress.py +=================================================================== +--- aptdaemon-1.1.1.orig/aptdaemon/progress.py ++++ aptdaemon-1.1.1/aptdaemon/progress.py +@@ -628,6 +628,11 @@ class DaemonLintianProgress(DaemonForkPr + + def _child(self, path): + # Avoid running lintian as root ++ try: ++ os.setgroups([self.transaction.gid]) ++ except OSError: ++ pass ++ os.setgid(self.transaction.gid) + os.setuid(self.transaction.uid) + + if platform.dist()[1] == "debian": +Index: aptdaemon-1.1.1/aptdaemon/worker.py +=================================================================== +--- aptdaemon-1.1.1.orig/aptdaemon/worker.py ++++ aptdaemon-1.1.1/aptdaemon/worker.py +@@ -76,6 +76,25 @@ log = logging.getLogger("AptDaemon.Worke + _ = lambda s: s + + ++@contextlib.contextmanager ++def set_euid_egid(uid, gid): ++ # no need to drop privs ++ if os.getuid() != 0 and os.getgid() != 0: ++ yield ++ return ++ # temporary drop privs ++ os.setegid(gid) ++ old_groups = os.getgroups() ++ os.setgroups([gid]) ++ os.seteuid(uid) ++ try: ++ yield ++ finally: ++ os.seteuid(os.getuid()) ++ os.setegid(os.getgid()) ++ os.setgroups(old_groups) ++ ++ + def trans_only_installs_pkgs_from_high_trust_repos(trans, + whitelist=set()): + """Return True if this transaction only touches packages in the +@@ -1329,8 +1348,16 @@ class AptWorker(GObject.GObject): + + :returns: An apt.debfile.Debfile instance. + """ +- if not os.path.isfile(path): +- raise TransactionFailed(ERROR_UNREADABLE_PACKAGE_FILE, path) ++ # This code runs as root for simulate and simulate requires no ++ # authentication - so we need to ensure we do not leak information ++ # about files here (LP: #1449587, CVE-2015-1323) ++ # ++ # Note that the actual lintian run is also droping privs (real, ++ # not just seteuid) ++ with set_euid_egid(trans.uid, trans.gid): ++ if not os.path.isfile(path): ++ raise TransactionFailed(ERROR_UNREADABLE_PACKAGE_FILE, path) ++ + if not force and os.path.isfile("/usr/bin/lintian"): + with DaemonLintianProgress(trans) as progress: + progress.run(path) +Index: aptdaemon-1.1.1/tests/test_high_trust_repository_whitelist.py +=================================================================== +--- aptdaemon-1.1.1.orig/tests/test_high_trust_repository_whitelist.py ++++ aptdaemon-1.1.1/tests/test_high_trust_repository_whitelist.py +@@ -116,7 +116,7 @@ class HighTrustRepositoryTestCase(BaseHi + ("Ubuntu", "", "silly.*")) + # a high-trust whitelisted pkg and a non-whitelisted one + trans = Transaction(None, enums.ROLE_INSTALL_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[["silly-base", "other-pkg"], [], [], [], + [], []]) +@@ -128,7 +128,7 @@ class HighTrustRepositoryTestCase(BaseHi + trans, self.worker._high_trust_repositories)) + # whitelisted only + trans = Transaction(None, enums.ROLE_INSTALL_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[["silly-base"], [], [], [], [], []]) + self.worker.simulate(trans) +Index: aptdaemon-1.1.1/tests/test_worker.py +=================================================================== +--- aptdaemon-1.1.1.orig/tests/test_worker.py ++++ aptdaemon-1.1.1/tests/test_worker.py +@@ -77,7 +77,8 @@ class WorkerTestCase(aptdaemon.test.AptD + self.chroot.add_repository("/does/not/exist", copy_list=False) + # Only update the repository from the working snippet + trans = Transaction(None, enums.ROLE_UPDATE_CACHE, +- self.queue, os.getpid(), os.getuid(), sys.argv[0], ++ self.queue, os.getpid(), os.getuid(), ++ os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + kwargs={"sources_list": "test.list"}) + self.worker.simulate(trans) +@@ -99,7 +100,7 @@ class WorkerTestCase(aptdaemon.test.AptD + "silly-base_0.1-0_all.deb")) + # Install the package + trans = Transaction(None, enums.ROLE_UPGRADE_SYSTEM, +- self.queue, os.getpid(), ++ self.queue, os.getpid(), os.getgid(), + os.getuid(), sys.argv[0], + "org.debian.apt.test", connect=False, + kwargs={"safe_mode": False}) +@@ -130,7 +131,7 @@ class WorkerTestCase(aptdaemon.test.AptD + self.chroot.add_test_repository(copy_sig=False) + # Install the package + trans = Transaction(None, enums.ROLE_INSTALL_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[["silly-base"], [], [], [], [], []]) + self.worker.simulate(trans) +@@ -144,7 +145,7 @@ class WorkerTestCase(aptdaemon.test.AptD + + # Allow installation of unauthenticated packages + trans = Transaction(None, enums.ROLE_INSTALL_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[["silly-base"], [], [], [], [], []]) + trans.allow_unauthenticated = True +@@ -164,7 +165,7 @@ class WorkerTestCase(aptdaemon.test.AptD + self.chroot.add_test_repository() + # Install the package + trans = Transaction(None, enums.ROLE_INSTALL_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[["silly-depend-base"], [], [], [], + [], []]) +@@ -193,7 +194,7 @@ class WorkerTestCase(aptdaemon.test.AptD + Architecture: all + Auto-Installed: 1""") + trans = Transaction(None, enums.ROLE_REMOVE_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[[], [], ["silly-depend-base"], [], + [], []]) +@@ -219,7 +220,7 @@ Auto-Installed: 1""") + "silly-depend-base_0.1-0_all.deb"]: + self.chroot.install_debfile(os.path.join(REPO_PATH, pkg)) + trans = Transaction(None, enums.ROLE_REMOVE_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[[], [], ["silly-base"], [], [], []]) + self.worker.simulate(trans) +@@ -240,7 +241,7 @@ Auto-Installed: 1""") + pass + # Don't allow to remove essential packages + trans = Transaction(None, enums.ROLE_REMOVE_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[[], [], ["silly-essential"], [], [], []]) + self.worker.run(trans) +@@ -263,7 +264,7 @@ Auto-Installed: 1""") + Architecture: all + Auto-Installed: 1""") + trans = Transaction(None, enums.ROLE_COMMIT_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[[], [], [], [], + ["silly-base=0.1-0update1"], []]) +@@ -283,7 +284,7 @@ Auto-Installed: 1""") + pkg = os.path.join(REPO_PATH, "silly-base_0.1-0update1_all.deb") + self.chroot.install_debfile(pkg) + trans = Transaction(None, enums.ROLE_COMMIT_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[[], [], [], [], [], + ["silly-base=0.1-0"]]) +@@ -301,7 +302,7 @@ Auto-Installed: 1""") + for pkg in ["silly-base_0.1-0_all.deb", "silly-config_0.1-0_all.deb"]: + self.chroot.install_debfile(os.path.join(REPO_PATH, pkg)) + trans = Transaction(None, enums.ROLE_REMOVE_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + packages=[[], [], [], ["silly-config"], [], []]) + self.worker.run(trans) +@@ -324,7 +325,7 @@ Auto-Installed: 1""") + pkg = os.path.join(REPO_PATH, + "silly-depend-base-lintian-broken_0.1-0_all.deb") + trans = Transaction(None, enums.ROLE_INSTALL_FILE, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + kwargs={"path": os.path.join(REPO_PATH, pkg), + "force": False}) +@@ -359,7 +360,7 @@ Auto-Installed: 1""") + self.chroot.install_debfile(os.path.join(REPO_PATH, pkg_base)) + pkg = os.path.join(REPO_PATH, "silly-bully_0.1-0_all.deb") + trans = Transaction(None, enums.ROLE_INSTALL_FILE, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + kwargs={"path": os.path.join(REPO_PATH, pkg), + "force": True}) +@@ -379,7 +380,7 @@ Auto-Installed: 1""") + """ + pkg = os.path.join(REPO_PATH, "silly-base_0.1-0_all.deb") + trans = Transaction(None, enums.ROLE_INSTALL_FILE, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False, + kwargs={"path": os.path.join(REPO_PATH, pkg), + "force": True}) +@@ -400,7 +401,7 @@ Auto-Installed: 1""") + for pkg in ["silly-base_0.1-0_all.deb", "silly-broken_0.1-0_all.deb"]: + self.chroot.install_debfile(os.path.join(REPO_PATH, pkg), True) + trans = Transaction(None, enums.ROLE_FIX_BROKEN_DEPENDS, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", connect=False) + self.worker.simulate(trans) + self.loop.run() +@@ -420,7 +421,7 @@ Auto-Installed: 1""") + """ + self.chroot.add_test_repository() + trans = Transaction(None, enums.ROLE_COMMIT_PACKAGES, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", + packages=[["silly-broken"], [], [], [], [], []], + connect=False) +@@ -459,7 +460,7 @@ Auto-Installed: 1""") + + self.chroot.add_test_repository() + trans = Transaction(None, enums.ROLE_ADD_LICENSE_KEY, self.queue, +- os.getpid(), os.getuid(), sys.argv[0], ++ os.getpid(), os.getuid(), os.getgid(), sys.argv[0], + "org.debian.apt.test", + kwargs={"pkg_name": "silly-license", + "json_token": "lalelu", diff -Nru aptdaemon-1.1.1/debian/patches/series aptdaemon-1.1.1/debian/patches/series --- aptdaemon-1.1.1/debian/patches/series 2014-06-06 13:19:42.000000000 +0200 +++ aptdaemon-1.1.1/debian/patches/series 2015-05-29 22:04:16.000000000 +0200 @@ -7,4 +7,6 @@ lp1266844.patch fix-configparser.patch py3_inheritable.patch -upstream-include-pkg-version.patch \ No newline at end of file +upstream-include-pkg-version.patch +lp1449587.diff +