diff --git a/0001-Solves-problem-with-dnf-upgrade-if-base.conf.obsolet.patch b/0001-Solves-problem-with-dnf-upgrade-if-base.conf.obsolet.patch
new file mode 100644
index 0000000..a36e551
--- /dev/null
+++ b/0001-Solves-problem-with-dnf-upgrade-if-base.conf.obsolet.patch
@@ -0,0 +1,99 @@
+From 55ea10083506f58b0eb2d9e302df235414a140c1 Mon Sep 17 00:00:00 2001
+From: Jaroslav Mracek <jmracek@redhat.com>
+Date: Thu, 2 Aug 2018 15:06:00 +0200
+Subject: [PATCH 1/2] Solves problem with "dnf upgrade" if
+ base.conf.obsoletes=True
+
+In this case obsoletes were always applied.
+---
+ dnf/base.py | 63 ++++++++++++++++++++++++-----------------------------
+ 1 file changed, 28 insertions(+), 35 deletions(-)
+
+diff --git a/dnf/base.py b/dnf/base.py
+index 57b1663d..3ec3fba6 100644
+--- a/dnf/base.py
++++ b/dnf/base.py
+@@ -1919,6 +1919,26 @@ class Base(object):
+             logger.warning(msg, pkg.name)
+             return 0
+ 
++    def _upgrade_internal(self, query, obsoletes, reponame, pkg_spec=None):
++        installed = self.sack.query().installed()
++        q = query.intersection(self.sack.query().filterm(name=[pkg.name for pkg in installed]))
++        if obsoletes:
++            obsoletes = self.sack.query().available().filterm(obsoletes=q.installed.union(q.upgrades()))
++            # add obsoletes into transaction
++            q = q.union(obsoletes)
++        # provide only available packages to solver otherwise selection of available
++        # possibilities will be ignored
++        q = q.available()
++        if reponame is not None:
++            q.filterm(reponame=reponame)
++        q = self._merge_update_filters(q, pkg_spec=pkg_spec)
++        if q:
++            sltr = dnf.selector.Selector(self.sack)
++            sltr.set(pkg=q)
++            self._goal.upgrade(select=sltr)
++        return 1
++
++
+     def upgrade(self, pkg_spec, reponame=None):
+         # :api
+         subj = dnf.subject.Subject(pkg_spec)
+@@ -1941,45 +1961,18 @@ class Base(object):
+                     if not installed.filter(arch=solution['nevra'].arch):
+                         msg = _('Package %s available, but installed for different architecture.')
+                         logger.warning(msg, "{}.{}".format(pkg_name, solution['nevra'].arch))
+-
+-            if self.conf.obsoletes and solution['nevra'] and solution['nevra'].has_just_name():
+-                obsoletes = self.sack.query().filterm(obsoletes=q.installed())
+-                # provide only available packages to solver otherwise selection of available
+-                # possibilities will be ignored
+-                q = q.available()
+-                # add obsoletes into transaction
+-                q = q.union(obsoletes)
+-            else:
+-                q = q.available()
+-            if reponame is not None:
+-                q.filterm(reponame=reponame)
+-            q = self._merge_update_filters(q, pkg_spec=pkg_spec)
+-            if q:
+-                sltr = dnf.selector.Selector(self.sack)
+-                sltr.set(pkg=q)
+-                self._goal.upgrade(select=sltr)
+-            return 1
+-
++            obsoletes = self.conf.obsoletes and solution['nevra'] \
++                        and solution['nevra'].has_just_name()
++            return self._upgrade_internal(q, obsoletes, reponame, pkg_spec)
+         raise dnf.exceptions.MarkingError(_('No match for argument: %s') % pkg_spec, pkg_spec)
+ 
+     def upgrade_all(self, reponame=None):
+         # :api
+-        if reponame is None and not self._update_security_filters:
+-            self._goal.upgrade_all()
+-        else:
+-            # provide only available packages to solver otherwise selection of available
+-            # possibilities will be ignored
+-            q = self.sack.query().available()
+-            # add obsoletes into transaction
+-            if self.conf.obsoletes:
+-                q = q.union(self.sack.query().filterm(obsoletes=self.sack.query().installed()))
+-            if reponame is not None:
+-                q.filterm(reponame=reponame)
+-            q = self._merge_update_filters(q)
+-            sltr = dnf.selector.Selector(self.sack)
+-            sltr.set(pkg=q)
+-            self._goal.upgrade(select=sltr)
+-        return 1
++        # provide only available packages to solver to trigger targeted upgrade
++        # possibilities will be ignored
++        # usage of selected packages will unify dnf behavior with other upgrade functions
++        return self._upgrade_internal(
++            self.sack.query(), self.conf.obsoletes, reponame, pkg_spec=None)
+ 
+     def distro_sync(self, pkg_spec=None):
+         if pkg_spec is None:
+-- 
+2.19.0
+
diff --git a/0002-Fix-problem-with-upgrade-in-dnf.patch b/0002-Fix-problem-with-upgrade-in-dnf.patch
new file mode 100644
index 0000000..5f5bf77
--- /dev/null
+++ b/0002-Fix-problem-with-upgrade-in-dnf.patch
@@ -0,0 +1,26 @@
+From 2de14efc0c535f10691ff1738caa8c76661e12f3 Mon Sep 17 00:00:00 2001
+From: Jaroslav Mracek <jmracek@redhat.com>
+Date: Fri, 5 Oct 2018 09:38:30 +0200
+Subject: [PATCH 2/2] Fix problem with upgrade in dnf
+
+---
+ dnf/base.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/dnf/base.py b/dnf/base.py
+index 3ec3fba6..b2628150 100644
+--- a/dnf/base.py
++++ b/dnf/base.py
+@@ -1923,7 +1923,8 @@ class Base(object):
+         installed = self.sack.query().installed()
+         q = query.intersection(self.sack.query().filterm(name=[pkg.name for pkg in installed]))
+         if obsoletes:
+-            obsoletes = self.sack.query().available().filterm(obsoletes=q.installed.union(q.upgrades()))
++            obsoletes = self.sack.query().available().filterm(
++                obsoletes=q.installed().union(q.upgrades()))
+             # add obsoletes into transaction
+             q = q.union(obsoletes)
+         # provide only available packages to solver otherwise selection of available
+-- 
+2.19.0
+
diff --git a/dnf.spec b/dnf.spec
index 7d44a07..a941599 100644
--- a/dnf.spec
+++ b/dnf.spec
@@ -73,12 +73,16 @@ It supports RPMs, modules and comps groups & environments.
 
 Name:           dnf
 Version:        3.6.1
-Release:        2%{?dist}
+Release:        3%{?dist}
 Summary:        %{pkg_summary}
 # For a breakdown of the licensing, see PACKAGE-LICENSING
 License:        GPLv2+ and GPLv2 and GPL
 URL:            https://github.com/rpm-software-management/dnf
 Source0:        %{url}/archive/%{version}/%{name}-%{version}.tar.gz
+# Backported fixes for https://bugzilla.redhat.com/show_bug.cgi?id=1616118
+# from upstream master
+Patch0:         0001-Solves-problem-with-dnf-upgrade-if-base.conf.obsolet.patch
+Patch1:         0002-Fix-problem-with-upgrade-in-dnf.patch
 BuildArch:      noarch
 BuildRequires:  cmake
 BuildRequires:  gettext
@@ -495,6 +499,9 @@ ln -sr  %{buildroot}%{confdir}/vars %{buildroot}%{_sysconfdir}/yum/vars
 %endif
 
 %changelog
+* Tue Oct 09 2018 Adam Williamson <awilliam@redhat.com> - 3.6.1-3
+- Backport fixes for RHBZ#1616118 from upstream master
+
 * Sat Sep 29 2018 Kevin Fenzi <kevin@scrye.com> - 3.6.1-2
 - Temp re-add python2 package to get rawhide composes working again.