diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
index 528c1cad..5efd0a47 100644
--- a/libsepol/include/sepol/policydb/policydb.h
+++ b/libsepol/include/sepol/policydb/policydb.h
@@ -749,9 +749,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
 #define MOD_POLICYDB_VERSION_INFINIBAND		19
 #define MOD_POLICYDB_VERSION_GLBLUB		20
 #define MOD_POLICYDB_VERSION_SELF_TYPETRANS	21
+#define MOD_POLICYDB_VERSION_AVRULE_FTRANS	22
 
 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_SELF_TYPETRANS
+#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_AVRULE_FTRANS
 
 #define POLICYDB_CONFIG_MLS    1
 
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index b15d4163..37bb97a1 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -341,6 +341,13 @@ static const struct policydb_compat_info policydb_compat[] = {
 	 .ocon_num = OCON_IBENDPORT + 1,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
+	{
+	 .type = POLICY_BASE,
+	 .version = MOD_POLICYDB_VERSION_AVRULE_FTRANS,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = OCON_IBENDPORT + 1,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
 	{
 	 .type = POLICY_MOD,
 	 .version = MOD_POLICYDB_VERSION_BASE,
@@ -467,6 +474,13 @@ static const struct policydb_compat_info policydb_compat[] = {
 	 .ocon_num = 0,
 	 .target_platform = SEPOL_TARGET_SELINUX,
 	},
+	{
+	 .type = POLICY_MOD,
+	 .version = MOD_POLICYDB_VERSION_AVRULE_FTRANS,
+	 .sym_num = SYM_NUM,
+	 .ocon_num = 0,
+	 .target_platform = SEPOL_TARGET_SELINUX,
+	},
 };
 
 #if 0
@@ -3202,6 +3216,19 @@ static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp)
 		tail = cur;
 	}
 
+	if (p->policyvers >= MOD_POLICYDB_VERSION_AVRULE_FTRANS &&
+	    avrule->specified & AVRULE_TRANSITION) {
+		rc = next_entry(buf, fp, sizeof(uint32_t));
+		if (rc < 0)
+			goto bad;
+		len = le32_to_cpu(*buf);
+		if (len) {
+			rc = str_read(&avrule->object_name, fp, len);
+			if (rc < 0)
+				goto bad;
+		}
+	}
+
 	if (avrule->specified & AVRULE_XPERMS) {
 		uint8_t buf8;
 		size_t nel = ARRAY_SIZE(avrule->xperms->perms);
@@ -3633,6 +3660,7 @@ static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl,
 	}
 
 	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
+	    p->policyvers < MOD_POLICYDB_VERSION_AVRULE_FTRANS &&
 	    filename_trans_rule_read(p, &decl->avrules, fp))
 		return -1;
 
diff --git a/libsepol/src/write.c b/libsepol/src/write.c
index 68495198..d7f47c8d 100644
--- a/libsepol/src/write.c
+++ b/libsepol/src/write.c
@@ -2025,8 +2025,9 @@ static int avrule_write(policydb_t *p, avrule_t * avrule,
 	uint32_t buf[32], len;
 	class_perm_node_t *cur;
 
-	/* skip filename transitions for now */
-	if (avrule->specified & AVRULE_TRANSITION && avrule->object_name)
+	/* skip filename transitions if writing older version without name */
+	if (p->policyvers < MOD_POLICYDB_VERSION_AVRULE_FTRANS &&
+	    avrule->specified & AVRULE_TRANSITION && avrule->object_name)
 		return POLICYDB_SUCCESS;
 
 	if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS &&
@@ -2073,6 +2074,21 @@ static int avrule_write(policydb_t *p, avrule_t * avrule,
 		cur = cur->next;
 	}
 
+	if (p->policyvers >= MOD_POLICYDB_VERSION_AVRULE_FTRANS &&
+	    avrule->specified & AVRULE_TRANSITION) {
+		len = avrule->object_name ? strlen(avrule->object_name) : 0;
+		*buf = cpu_to_le32(len);
+		items = put_entry(buf, sizeof(uint32_t), 1, fp);
+		if (items != 1)
+			return POLICYDB_ERROR;
+		if (avrule->object_name) {
+			items = put_entry(avrule->object_name, sizeof(char),
+					  len, fp);
+			if (items != len)
+				return POLICYDB_ERROR;
+		}
+	}
+
 	if (avrule->specified & AVRULE_XPERMS) {
 		size_t nel = ARRAY_SIZE(avrule->xperms->perms);
 		uint32_t buf32[nel];
@@ -2122,7 +2138,8 @@ static int avrule_write_list(policydb_t *p, avrule_t * avrules,
 	avrule = avrules;
 	len = 0;
 	while (avrule) {
-		if (!(avrule->specified & AVRULE_TRANSITION &&
+		if (p->policyvers >= MOD_POLICYDB_VERSION_AVRULE_FTRANS ||
+		    !(avrule->specified & AVRULE_TRANSITION &&
 		      avrule->object_name))
 			len++;
 		avrule = avrule->next;
@@ -2357,6 +2374,7 @@ static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
 	}
 
 	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
+	    p->policyvers < MOD_POLICYDB_VERSION_AVRULE_FTRANS &&
 	    filename_trans_rule_write(p, decl->avrules, fp))
 		return POLICYDB_ERROR;
 
