diff --git a/grsecurity/gracl.c b/grsecurity/gracl.c
index 6ae3aa0..9c2d930 100644
--- a/grsecurity/gracl.c
+++ b/grsecurity/gracl.c
@@ -1171,9 +1171,10 @@ gr_set_proc_res(struct task_struct *task)
 	rcu_read_lock();
 	read_lock(&tasklist_lock);
 	read_lock(&grsec_exec_file_lock);
+   except in the case of gr_set_role_label() (for __gr_get_subject_for_task)
 */
 
-struct acl_subject_label *__gr_get_subject_for_task(const struct gr_policy_state *state, struct task_struct *task, const char *filename)
+struct acl_subject_label *__gr_get_subject_for_task(const struct gr_policy_state *state, struct task_struct *task, const char *filename, int fallback)
 {
 	char *tmpname;
 	struct acl_subject_label *tmpsubj;
@@ -1215,15 +1216,15 @@ struct acl_subject_label *__gr_get_subject_for_task(const struct gr_policy_state
 	/* this also works for the reload case -- if we don't match a potentially inherited subject
 	   then we fall back to a normal lookup based on the binary's ino/dev
 	*/
-	if (tmpsubj == NULL)
+	if (tmpsubj == NULL && fallback)
 		tmpsubj = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt, task->role);
 
 	return tmpsubj;
 }
 
-static struct acl_subject_label *gr_get_subject_for_task(struct task_struct *task, const char *filename)
+static struct acl_subject_label *gr_get_subject_for_task(struct task_struct *task, const char *filename, int fallback)
 {
-	return __gr_get_subject_for_task(&running_polstate, task, filename);
+	return __gr_get_subject_for_task(&running_polstate, task, filename, fallback);
 }
 
 void __gr_apply_subject_to_task(const struct gr_policy_state *state, struct task_struct *task, struct acl_subject_label *subj)
@@ -1287,7 +1288,7 @@ gr_search_file(const struct dentry * dentry, const __u32 mode,
 			task->role = current->role;
 			rcu_read_lock();
 			read_lock(&grsec_exec_file_lock);
-			subj = gr_get_subject_for_task(task, NULL);
+			subj = gr_get_subject_for_task(task, NULL, 1);
 			gr_apply_subject_to_task(task, subj);
 			read_unlock(&grsec_exec_file_lock);
 			rcu_read_unlock();
@@ -1697,6 +1698,7 @@ void
 gr_set_role_label(struct task_struct *task, const kuid_t kuid, const kgid_t kgid)
 {
 	struct acl_role_label *role = task->role;
+	struct acl_role_label *origrole = role;
 	struct acl_subject_label *subj = NULL;
 	struct acl_object_label *obj;
 	struct file *filp;
@@ -1729,10 +1731,28 @@ gr_set_role_label(struct task_struct *task, const kuid_t kuid, const kgid_t kgid
 	     ((role->roletype & GR_ROLE_GROUP) && !gr_acl_is_capable(CAP_SETGID))))
 		return;
 
-	/* perform subject lookup in possibly new role
-	   we can use this result below in the case where role == task->role
-	*/
-	subj = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt, role);
+	task->role = role;
+
+	if (task->inherited) {
+		/* if we reached our subject through inheritance, then first see
+		   if there's a subject of the same name in the new role that has
+		   an object that would result in the same inherited subject
+		*/
+		subj = gr_get_subject_for_task(task, task->acl->filename, 0);
+		if (subj) {
+			obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, subj);
+			if (!(obj->mode & GR_INHERIT))
+				subj = NULL;
+		}
+		
+	}
+	if (subj == NULL) {
+		/* otherwise:
+		   perform subject lookup in possibly new role
+		   we can use this result below in the case where role == task->role
+		*/
+		subj = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt, role);
+	}
 
 	/* if we changed uid/gid, but result in the same role
 	   and are using inheritance, don't lose the inherited subject
@@ -1740,14 +1760,12 @@ gr_set_role_label(struct task_struct *task, const kuid_t kuid, const kgid_t kgid
 	   would result in, we arrived via inheritance, don't
 	   lose subject
 	*/
-	if (role != task->role || (!(task->acl->mode & GR_INHERITLEARN) &&
+	if (role != origrole || (!(task->acl->mode & GR_INHERITLEARN) &&
 				   (subj == task->acl)))
 		task->acl = subj;
 
 	/* leave task->inherited unaffected */
 
-	task->role = role;
-
 	task->is_writable = 0;
 
 	/* ignore additional mmap checks for processes that are writable 
diff --git a/grsecurity/gracl_policy.c b/grsecurity/gracl_policy.c
index 3f8ade0..7949dcd 100644
--- a/grsecurity/gracl_policy.c
+++ b/grsecurity/gracl_policy.c
@@ -68,7 +68,7 @@ extern void gr_free_uidset(void);
 extern void gr_remove_uid(uid_t uid);
 extern int gr_find_uid(uid_t uid);
 
-extern struct acl_subject_label *__gr_get_subject_for_task(const struct gr_policy_state *state, struct task_struct *task, const char *filename);
+extern struct acl_subject_label *__gr_get_subject_for_task(const struct gr_policy_state *state, struct task_struct *task, const char *filename, int fallback);
 extern void __gr_apply_subject_to_task(struct gr_policy_state *state, struct task_struct *task, struct acl_subject_label *subj);
 extern int gr_streq(const char *a, const char *b, const unsigned int lena, const unsigned int lenb);
 extern void __insert_inodev_entry(const struct gr_policy_state *state, struct inodev_entry *entry);
@@ -1173,8 +1173,8 @@ static int gracl_reload_apply_policies(void *reload)
 		}
 		/* this handles non-nested inherited subjects, nested subjects will still
 		   be dropped currently */
-		subj = __gr_get_subject_for_task(polstate, task, task->acl->filename);
-		task->tmpacl = __gr_get_subject_for_task(polstate, task, NULL);
+		subj = __gr_get_subject_for_task(polstate, task, task->acl->filename, 1);
+		task->tmpacl = __gr_get_subject_for_task(polstate, task, NULL, 1);
 		/* change the role back so that we've made no modifications to the policy */
 		task->role = rtmp;
 
@@ -1206,7 +1206,7 @@ static int gracl_reload_apply_policies(void *reload)
 			/* this handles non-nested inherited subjects, nested subjects will still
 			   be dropped currently */
 			if (!reload_state->oldmode && task->inherited)
-				subj = __gr_get_subject_for_task(polstate, task, task->acl->filename);
+				subj = __gr_get_subject_for_task(polstate, task, task->acl->filename, 1);
 			else {
 				/* looked up and tagged to the task previously */
 				subj = task->tmpacl;
@@ -1755,7 +1755,7 @@ gr_set_acls(const int type)
 		if (task->exec_file) {
 			cred = __task_cred(task);
 			task->role = __lookup_acl_role_label(polstate, task, GR_GLOBAL_UID(cred->uid), GR_GLOBAL_GID(cred->gid));
-			subj = __gr_get_subject_for_task(polstate, task, NULL);
+			subj = __gr_get_subject_for_task(polstate, task, NULL, 1);
 			if (subj == NULL) {
 				ret = -EINVAL;
 				read_unlock(&grsec_exec_file_lock);
