diff --git a/SOURCES/0009-libselinux-Eliminate-use-of-security_compute_user.patch b/SOURCES/0009-libselinux-Eliminate-use-of-security_compute_user.patch
new file mode 100644
index 0000000..68085cf
--- /dev/null
+++ b/SOURCES/0009-libselinux-Eliminate-use-of-security_compute_user.patch
@@ -0,0 +1,354 @@
+From bfee1a3131580a7b9d8a7366764b8e78d99a9f1b Mon Sep 17 00:00:00 2001
+From: Petr Lautrbach <plautrba@redhat.com>
+Date: Mon, 17 Feb 2020 21:47:35 +0100
+Subject: [PATCH] libselinux: Eliminate use of security_compute_user()
+
+get_ordered_context_list() code used to ask the kernel to compute the complete
+set of reachable contexts using /sys/fs/selinux/user aka
+security_compute_user(). This set can be so huge so that it doesn't fit into a
+kernel page and security_compute_user() fails. Even if it doesn't fail,
+get_ordered_context_list() throws away the vast majority of the returned
+contexts because they don't match anything in
+/etc/selinux/targeted/contexts/default_contexts or
+/etc/selinux/targeted/contexts/users/
+
+get_ordered_context_list() is rewritten to compute set of contexts based on
+/etc/selinux/targeted/contexts/users/ and
+/etc/selinux/targeted/contexts/default_contexts files and to return only valid
+contexts, using security_check_context(), from this set.
+
+Fixes: https://github.com/SELinuxProject/selinux/issues/28
+
+Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
+---
+ libselinux/src/get_context_list.c | 212 +++++++++++++-----------------
+ 1 file changed, 93 insertions(+), 119 deletions(-)
+
+diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c
+index 689e4658..26d7b3b9 100644
+--- a/libselinux/src/get_context_list.c
++++ b/libselinux/src/get_context_list.c
+@@ -2,6 +2,7 @@
+ #include <errno.h>
+ #include <stdio.h>
+ #include <stdio_ext.h>
++#include <stdint.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+@@ -114,64 +115,41 @@ int get_default_context(const char *user,
+ 	return 0;
+ }
+ 
+-static int find_partialcon(char ** list,
+-			   unsigned int nreach, char *part)
++static int is_in_reachable(char **reachable, const char *usercon_str)
+ {
+-	const char *conrole, *contype;
+-	char *partrole, *parttype, *ptr;
+-	context_t con;
+-	unsigned int i;
++	if (!reachable)
++		return 0;
+ 
+-	partrole = part;
+-	ptr = part;
+-	while (*ptr && !isspace(*ptr) && *ptr != ':')
+-		ptr++;
+-	if (*ptr != ':')
+-		return -1;
+-	*ptr++ = 0;
+-	parttype = ptr;
+-	while (*ptr && !isspace(*ptr) && *ptr != ':')
+-		ptr++;
+-	*ptr = 0;
+-
+-	for (i = 0; i < nreach; i++) {
+-		con = context_new(list[i]);
+-		if (!con)
+-			return -1;
+-		conrole = context_role_get(con);
+-		contype = context_type_get(con);
+-		if (!conrole || !contype) {
+-			context_free(con);
+-			return -1;
+-		}
+-		if (!strcmp(conrole, partrole) && !strcmp(contype, parttype)) {
+-			context_free(con);
+-			return i;
++	for (; *reachable != NULL; reachable++) {
++		if (strcmp(*reachable, usercon_str) == 0) {
++			return 1;
+ 		}
+-		context_free(con);
+ 	}
+-
+-	return -1;
++	return 0;
+ }
+ 
+-static int get_context_order(FILE * fp,
++static int get_context_user(FILE * fp,
+ 			     char * fromcon,
+-			     char ** reachable,
+-			     unsigned int nreach,
+-			     unsigned int *ordering, unsigned int *nordered)
++			     const char * user,
++			     char ***reachable,
++			     unsigned int *nreachable)
+ {
+ 	char *start, *end = NULL;
+ 	char *line = NULL;
+-	size_t line_len = 0;
++	size_t line_len = 0, usercon_len;
++	size_t user_len = strlen(user);
+ 	ssize_t len;
+ 	int found = 0;
+-	const char *fromrole, *fromtype;
++	const char *fromrole, *fromtype, *fromlevel;
+ 	char *linerole, *linetype;
+-	unsigned int i;
++	char **new_reachable = NULL;
++	char *usercon_str;
+ 	context_t con;
++	context_t usercon;
++
+ 	int rc;
+ 
+-	errno = -EINVAL;
++	errno = EINVAL;
+ 
+ 	/* Extract the role and type of the fromcon for matching.
+ 	   User identity and MLS range can be variable. */
+@@ -180,6 +158,7 @@ static int get_context_order(FILE * fp,
+ 		return -1;
+ 	fromrole = context_role_get(con);
+ 	fromtype = context_type_get(con);
++	fromlevel = context_range_get(con);
+ 	if (!fromrole || !fromtype) {
+ 		context_free(con);
+ 		return -1;
+@@ -243,23 +222,75 @@ static int get_context_order(FILE * fp,
+ 		if (*end)
+ 			*end++ = 0;
+ 
+-		/* Check for a match in the reachable list. */
+-		rc = find_partialcon(reachable, nreach, start);
+-		if (rc < 0) {
+-			/* No match, skip it. */
++		/* Check whether a new context is valid */
++		if (SIZE_MAX - user_len < strlen(start) + 2) {
++			fprintf(stderr, "%s: one of partial contexts is too big\n", __FUNCTION__);
++			errno = EINVAL;
++			rc = -1;
++			goto out;
++		}
++		usercon_len = user_len + strlen(start) + 2;
++		usercon_str = malloc(usercon_len);
++		if (!usercon_str) {
++			rc = -1;
++			goto out;
++		}
++
++		/* set range from fromcon in the new usercon */
++		snprintf(usercon_str, usercon_len, "%s:%s", user, start);
++		usercon = context_new(usercon_str);
++		if (!usercon) {
++			if (errno != EINVAL) {
++				free(usercon_str);
++				rc = -1;
++				goto out;
++			}
++			fprintf(stderr,
++				"%s: can't create a context from %s, skipping\n",
++				__FUNCTION__, usercon_str);
++			free(usercon_str);
+ 			start = end;
+ 			continue;
+ 		}
++		free(usercon_str);
++		if (context_range_set(usercon, fromlevel) != 0) {
++			context_free(usercon);
++			rc = -1;
++			goto out;
++		}
++		usercon_str = context_str(usercon);
++		if (!usercon_str) {
++			context_free(usercon);
++			rc = -1;
++			goto out;
++		}
+ 
+-		/* If a match is found and the entry is not already ordered
+-		   (e.g. due to prior match in prior config file), then set
+-		   the ordering for it. */
+-		i = rc;
+-		if (ordering[i] == nreach)
+-			ordering[i] = (*nordered)++;
++		/* check whether usercon is already in reachable */
++		if (is_in_reachable(*reachable, usercon_str)) {
++			context_free(usercon);
++			start = end;
++			continue;
++		}
++		if (security_check_context(usercon_str) == 0) {
++			new_reachable = realloc(*reachable, (*nreachable + 2) * sizeof(char *));
++			if (!new_reachable) {
++				context_free(usercon);
++				rc = -1;
++				goto out;
++			}
++			*reachable = new_reachable;
++			new_reachable[*nreachable] = strdup(usercon_str);
++			if (new_reachable[*nreachable] == NULL) {
++				context_free(usercon);
++				rc = -1;
++				goto out;
++			}
++			new_reachable[*nreachable + 1] = 0;
++			*nreachable += 1;
++		}
++		context_free(usercon);
+ 		start = end;
+ 	}
+-
+ 	rc = 0;
+ 
+       out:
+@@ -313,21 +344,6 @@ static int get_failsafe_context(const char *user, char ** newcon)
+ 	return 0;
+ }
+ 
+-struct context_order {
+-	char * con;
+-	unsigned int order;
+-};
+-
+-static int order_compare(const void *A, const void *B)
+-{
+-	const struct context_order *c1 = A, *c2 = B;
+-	if (c1->order < c2->order)
+-		return -1;
+-	else if (c1->order > c2->order)
+-		return 1;
+-	return strcmp(c1->con, c2->con);
+-}
+-
+ int get_ordered_context_list_with_level(const char *user,
+ 					const char *level,
+ 					char * fromcon,
+@@ -395,11 +411,8 @@ int get_ordered_context_list(const char *user,
+ 			     char *** list)
+ {
+ 	char **reachable = NULL;
+-	unsigned int *ordering = NULL;
+-	struct context_order *co = NULL;
+-	char **ptr;
+ 	int rc = 0;
+-	unsigned int nreach = 0, nordered = 0, freefrom = 0, i;
++	unsigned nreachable = 0, freefrom = 0;
+ 	FILE *fp;
+ 	char *fname = NULL;
+ 	size_t fname_len;
+@@ -413,23 +426,6 @@ int get_ordered_context_list(const char *user,
+ 		freefrom = 1;
+ 	}
+ 
+-	/* Determine the set of reachable contexts for the user. */
+-	rc = security_compute_user(fromcon, user, &reachable);
+-	if (rc < 0)
+-		goto failsafe;
+-	nreach = 0;
+-	for (ptr = reachable; *ptr; ptr++)
+-		nreach++;
+-	if (!nreach)
+-		goto failsafe;
+-
+-	/* Initialize ordering array. */
+-	ordering = malloc(nreach * sizeof(unsigned int));
+-	if (!ordering)
+-		goto failsafe;
+-	for (i = 0; i < nreach; i++)
+-		ordering[i] = nreach;
+-
+ 	/* Determine the ordering to apply from the optional per-user config
+ 	   and from the global config. */
+ 	fname_len = strlen(user_contexts_path) + strlen(user) + 2;
+@@ -440,8 +436,8 @@ int get_ordered_context_list(const char *user,
+ 	fp = fopen(fname, "re");
+ 	if (fp) {
+ 		__fsetlocking(fp, FSETLOCKING_BYCALLER);
+-		rc = get_context_order(fp, fromcon, reachable, nreach, ordering,
+-				       &nordered);
++		rc = get_context_user(fp, fromcon, user, &reachable, &nreachable);
++
+ 		fclose(fp);
+ 		if (rc < 0 && errno != ENOENT) {
+ 			fprintf(stderr,
+@@ -454,8 +450,7 @@ int get_ordered_context_list(const char *user,
+ 	fp = fopen(selinux_default_context_path(), "re");
+ 	if (fp) {
+ 		__fsetlocking(fp, FSETLOCKING_BYCALLER);
+-		rc = get_context_order(fp, fromcon, reachable, nreach, ordering,
+-				       &nordered);
++		rc = get_context_user(fp, fromcon, user, &reachable, &nreachable);
+ 		fclose(fp);
+ 		if (rc < 0 && errno != ENOENT) {
+ 			fprintf(stderr,
+@@ -463,40 +458,19 @@ int get_ordered_context_list(const char *user,
+ 				__FUNCTION__, selinux_default_context_path());
+ 			/* Fall through */
+ 		}
+-		rc = 0;
+ 	}
+ 
+-	if (!nordered)
++	if (!nreachable)
+ 		goto failsafe;
+ 
+-	/* Apply the ordering. */
+-	co = malloc(nreach * sizeof(struct context_order));
+-	if (!co)
+-		goto failsafe;
+-	for (i = 0; i < nreach; i++) {
+-		co[i].con = reachable[i];
+-		co[i].order = ordering[i];
+-	}
+-	qsort(co, nreach, sizeof(struct context_order), order_compare);
+-	for (i = 0; i < nreach; i++)
+-		reachable[i] = co[i].con;
+-	free(co);
+-
+-	/* Only report the ordered entries to the caller. */
+-	if (nordered <= nreach) {
+-		for (i = nordered; i < nreach; i++)
+-			free(reachable[i]);
+-		reachable[nordered] = NULL;
+-		rc = nordered;
+-	}
+-
+       out:
+-	if (rc > 0)
++	if (nreachable > 0) {
+ 		*list = reachable;
++		rc = nreachable;
++	}
+ 	else
+ 		freeconary(reachable);
+ 
+-	free(ordering);
+ 	if (freefrom)
+ 		freecon(fromcon);
+ 
+@@ -519,7 +493,7 @@ int get_ordered_context_list(const char *user,
+ 		reachable = NULL;
+ 		goto out;
+ 	}
+-	rc = 1;			/* one context in the list */
++	nreachable = 1;			/* one context in the list */
+ 	goto out;
+ }
+ 
+-- 
+2.25.4
+
diff --git a/SOURCES/0010-libselinux-deprecate-security_compute_user-update-ma.patch b/SOURCES/0010-libselinux-deprecate-security_compute_user-update-ma.patch
new file mode 100644
index 0000000..7e782b4
--- /dev/null
+++ b/SOURCES/0010-libselinux-deprecate-security_compute_user-update-ma.patch
@@ -0,0 +1,168 @@
+From d4c22fcd5943fe35db648dee971f631d40b3eb94 Mon Sep 17 00:00:00 2001
+From: Stephen Smalley <sds@tycho.nsa.gov>
+Date: Thu, 20 Feb 2020 10:40:19 -0500
+Subject: [PATCH] libselinux: deprecate security_compute_user(), update man
+ pages
+
+commit 1f89c4e7879fcf6da5d8d1b025dcc03371f30fc9 ("libselinux: Eliminate
+use of security_compute_user()") eliminated the use of
+security_compute_user() by get_ordered_context_list().  Deprecate
+all use of security_compute_user() by updating the headers and man
+pages and logging a warning message on any calls to it.  Remove
+the example utility that called the interface. While here, also
+fix the documentation of correct usage of the user argument to these
+interfaces.
+
+Fixes: https://github.com/SELinuxProject/selinux/issues/70
+Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
+Acked-by: Petr Lautrbach <plautrba@redhat.com>
+---
+ libselinux/include/selinux/selinux.h          |  8 +++-
+ .../man/man3/get_ordered_context_list.3       | 24 +++++++++---
+ libselinux/man/man3/security_compute_av.3     |  5 ++-
+ libselinux/src/compute_user.c                 |  3 ++
+ libselinux/utils/compute_user.c               | 38 -------------------
+ 5 files changed, 31 insertions(+), 47 deletions(-)
+ delete mode 100644 libselinux/utils/compute_user.c
+
+diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
+index a34d54fc..a5ada324 100644
+--- a/libselinux/include/selinux/selinux.h
++++ b/libselinux/include/selinux/selinux.h
+@@ -246,8 +246,12 @@ extern int security_compute_member_raw(const char * scon,
+ 				       security_class_t tclass,
+ 				       char ** newcon);
+ 
+-/* Compute the set of reachable user contexts and set *con to refer to 
+-   the NULL-terminated array of contexts.  Caller must free via freeconary. */
++/*
++ * Compute the set of reachable user contexts and set *con to refer to
++ * the NULL-terminated array of contexts.  Caller must free via freeconary.
++ * These interfaces are deprecated.  Use get_ordered_context_list() or
++ * one of its variant interfaces instead.
++ */
+ extern int security_compute_user(const char * scon,
+ 				 const char *username,
+ 				 char *** con);
+diff --git a/libselinux/man/man3/get_ordered_context_list.3 b/libselinux/man/man3/get_ordered_context_list.3
+index e084da40..3ed14a96 100644
+--- a/libselinux/man/man3/get_ordered_context_list.3
++++ b/libselinux/man/man3/get_ordered_context_list.3
+@@ -26,14 +26,28 @@ get_ordered_context_list, get_ordered_context_list_with_level, get_default_conte
+ .BI "int get_default_type(const char *" role ", char **" type );
+ .
+ .SH "DESCRIPTION"
++
++This family of functions can be used to obtain either a prioritized list of
++all reachable security contexts for a given SELinux user or a single default
++(highest priority) context for a given SELinux user for use by login-like
++programs.  These functions takes a SELinux user identity that must
++be defined in the SELinux policy as their input, not a Linux username.
++Most callers should typically first call
++.BR getseuserbyname(3)
++to look up the SELinux user identity and level for a given
++Linux username and then invoke one of
++.BR get_ordered_context_list_with_level ()
++or
++.BR get_default_context_with_level ()
++with the returned SELinux user and level as inputs.
++
+ .BR get_ordered_context_list ()
+-invokes the 
+-.BR security_compute_user (3)
+-function to obtain the list of contexts for the specified
++obtains the list of contexts for the specified
++SELinux
+ .I user
+-that are reachable from the specified
++identity that are reachable from the specified
+ .I fromcon
+-context.  The function then orders the resulting list based on the global
++context based on the global
+ .I \%/etc/selinux/{SELINUXTYPE}/contexts/default_contexts
+ file and the per-user
+ .I \%/etc/selinux/{SELINUXTYPE}/contexts/users/<username>
+diff --git a/libselinux/man/man3/security_compute_av.3 b/libselinux/man/man3/security_compute_av.3
+index 2aade5fe..8e1f746a 100644
+--- a/libselinux/man/man3/security_compute_av.3
++++ b/libselinux/man/man3/security_compute_av.3
+@@ -97,8 +97,9 @@ instance.
+ 
+ .BR security_compute_user ()
+ is used to determine the set of user contexts that can be reached from a
+-source context. It is mainly used by
+-.BR get_ordered_context_list ().
++source context. This function is deprecated; use
++.BR get_ordered_context_list (3)
++instead.
+ 
+ .BR security_get_initial_context ()
+ is used to get the context of a kernel initial security identifier specified by 
+diff --git a/libselinux/src/compute_user.c b/libselinux/src/compute_user.c
+index 401fd107..0f55de84 100644
+--- a/libselinux/src/compute_user.c
++++ b/libselinux/src/compute_user.c
+@@ -8,6 +8,7 @@
+ #include "selinux_internal.h"
+ #include "policy.h"
+ #include <limits.h>
++#include "callbacks.h"
+ 
+ int security_compute_user_raw(const char * scon,
+ 			      const char *user, char *** con)
+@@ -24,6 +25,8 @@ int security_compute_user_raw(const char * scon,
+ 		return -1;
+ 	}
+ 
++	selinux_log(SELINUX_WARNING, "Direct use of security_compute_user() is deprecated, switch to get_ordered_context_list()\n");
++
+ 	if (! scon) {
+ 		errno=EINVAL;
+ 		return -1;
+diff --git a/libselinux/utils/compute_user.c b/libselinux/utils/compute_user.c
+deleted file mode 100644
+index cae62b26..00000000
+--- a/libselinux/utils/compute_user.c
++++ /dev/null
+@@ -1,38 +0,0 @@
+-#include <unistd.h>
+-#include <sys/types.h>
+-#include <fcntl.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <errno.h>
+-#include <string.h>
+-#include <ctype.h>
+-#include <selinux/selinux.h>
+-
+-int main(int argc, char **argv)
+-{
+-	char **buf, **ptr;
+-	int ret;
+-
+-	if (argc != 3) {
+-		fprintf(stderr, "usage:  %s context user\n", argv[0]);
+-		exit(1);
+-	}
+-
+-	ret = security_compute_user(argv[1], argv[2], &buf);
+-	if (ret < 0) {
+-		fprintf(stderr, "%s:  security_compute_user(%s,%s) failed\n",
+-			argv[0], argv[1], argv[2]);
+-		exit(2);
+-	}
+-
+-	if (!buf[0]) {
+-		printf("none\n");
+-		exit(0);
+-	}
+-
+-	for (ptr = buf; *ptr; ptr++) {
+-		printf("%s\n", *ptr);
+-	}
+-	freeconary(buf);
+-	exit(0);
+-}
+-- 
+2.25.4
+
diff --git a/SPECS/libselinux.spec b/SPECS/libselinux.spec
index 83af24c..5c649a9 100644
--- a/SPECS/libselinux.spec
+++ b/SPECS/libselinux.spec
@@ -6,7 +6,7 @@
 %endif
 
 %define libsepolver 2.9-1
-%define libselinuxrelease 3
+%define libselinuxrelease 5
 
 Summary: SELinux library and simple utilities
 Name: libselinux
@@ -27,6 +27,8 @@ Patch0005: 0005-libselinux-add-missing-av_permission-values.patch
 Patch0006: 0006-libselinux-Use-Python-distutils-to-install-SELinux-p.patch
 Patch0007: 0007-libselinux-Do-not-use-SWIG_CFLAGS-when-Python-bindin.patch
 Patch0008: 0008-Fix-mcstrans-secolor-examples.patch
+Patch0009: 0009-libselinux-Eliminate-use-of-security_compute_user.patch
+Patch0010: 0010-libselinux-deprecate-security_compute_user-update-ma.patch
 
 BuildRequires: gcc
 %if 0%{?with_ruby}
@@ -274,6 +276,12 @@ rm -f %{buildroot}%{_mandir}/man8/togglesebool*
 %endif
 
 %changelog
+* Tue Oct 20 2020 Vit Mojzis <vmojzis@redhat.com> - 2.9-5
+- Deprecate security_compute_user(), update man pages (#1879368)
+
+* Thu Sep 24 2020 Vit Mojzis <vmojzis@redhat.com> - 2.9-4
+- Eliminate use of security_compute_user() (#1879368)
+
 * Fri Nov 08 2019 Vit Mojzis <vmojzis@redhat.com> - 2.9-3
 - Fix mcstrans secolor examples in secolor.conf man page (#1770270)