Index: internal.h
===================================================================
--- internal.h	(revision 5696)
+++ internal.h	(working copy)
@@ -412,6 +412,7 @@
 	CCS_TYPE_AUTO_TASK_ACL,
 	CCS_TYPE_MANUAL_TASK_ACL,
 #endif
+	CCS_TYPE_USE_GROUP_ACL,
 };
 
 /* Index numbers for "struct ccs_condition". */
@@ -513,6 +514,7 @@
 enum ccs_group_id {
 	CCS_PATH_GROUP,
 	CCS_NUMBER_GROUP,
+	CCS_ACL_GROUP,
 #ifdef CONFIG_CCSECURITY_NETWORK
 	CCS_ADDRESS_GROUP,
 #endif
@@ -1354,6 +1356,12 @@
 	struct ccs_name_union name;
 };
 
+/* Structure for "use_group @" directive. */
+struct ccs_use_group_acl {
+	struct ccs_acl_info head; /* type = CCS_TYPE_USE_GROUP_ACL */
+	struct ccs_group *group;
+};
+
 /* Structure for holding string data. */
 struct ccs_name {
 	struct ccs_shared_acl_head head;
@@ -1381,6 +1389,7 @@
 		struct ccs_signal_acl signal_acl;
 		struct ccs_inet_acl inet_acl;
 		struct ccs_unix_acl unix_acl;
+		struct ccs_use_group_acl use_group_acl;
 		/**/
 		struct ccs_acl_head acl_head;
 		struct ccs_transition_control transition_control;
@@ -1404,6 +1413,7 @@
 		struct list_head *domain;
 		struct list_head *group;
 		struct list_head *acl;
+		const struct ccs_path_info *acl_group_name; 
 		size_t avail;
 		unsigned int step;
 		unsigned int query_index;
Index: policy_io.c
===================================================================
--- policy_io.c	(revision 5698)
+++ policy_io.c	(working copy)
@@ -356,6 +356,7 @@
 static const char * const ccs_group_name[CCS_MAX_GROUP] = {
 	[CCS_PATH_GROUP]    = "path_group ",
 	[CCS_NUMBER_GROUP]  = "number_group ",
+	[CCS_ACL_GROUP]     = "acl_group ",
 #ifdef CONFIG_CCSECURITY_NETWORK
 	[CCS_ADDRESS_GROUP] = "address_group ",
 #endif
@@ -3426,6 +3427,27 @@
 #endif
 
 /**
+ * ccs_write_use_group_acl - Write "struct ccs_use_group_acl" list.
+ *
+ * @param: Pointer to "struct ccs_acl_param".
+ *
+ * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds ccs_read_lock().
+ */
+static int ccs_write_use_group_acl(struct ccs_acl_param *param)
+{
+	struct ccs_use_group_acl *e = &param->e.use_group_acl;
+	if (!ccs_correct_word(param->data))
+		return -EINVAL;
+	e->head.type = CCS_TYPE_USE_GROUP_ACL;
+	e->group = ccs_get_group(param, CCS_ACL_GROUP);
+	if (!e->group)
+		return -ENOMEM;
+	return ccs_update_acl(sizeof(*e), param);
+}
+
+/**
  * ccs_write_acl - Write "struct ccs_acl_info" list.
  *
  * @ns:        Pointer to "struct ccs_policy_namespace".
@@ -3466,6 +3488,7 @@
 		{ "ipc signal ", ccs_write_ipc },
 #endif
 		{ "task ", ccs_write_task },
+		{ "use_group @", ccs_write_use_group_acl },
 	};
 	u8 i;
 	/* Forced zero clear for using memcmp() at ccs_update_acl(). */
@@ -3550,11 +3573,14 @@
 				domain->profile = (u8) profile;
 		return 0;
 	}
-	if (sscanf(data, "use_group %u\n", &profile) == 1
-	    && profile < CCS_MAX_ACL_GROUPS) {
-		if (!is_delete)
-			domain->group = (u8) profile;
-		return 0;
+	if (!strncmp(data, "use_group ", 10)) {
+		char *ep;
+		profile = simple_strtoul(data + 10, &ep, 10);
+		if (profile < CCS_MAX_ACL_GROUPS && !*ep) {
+			if (!is_delete)
+				domain->group = (u8) profile;
+			return 0;
+		}
 	}
 	for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) {
 		const char *cp = ccs_dif[profile];
@@ -3815,7 +3841,12 @@
 {
 	if (head->type == CCS_EXCEPTION_POLICY) {
 		ccs_print_namespace(head);
-		ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
+		ccs_set_string(head, "acl_group ");
+		if (head->r.acl_group_name)
+			ccs_set_string(head, head->r.acl_group_name->name);
+		else
+			ccs_io_printf(head, "%u", head->r.acl_group_index);
+		ccs_set_space(head);
 	}
 	ccs_set_string(head, category);
 }
@@ -3841,6 +3872,8 @@
 		return true;
 	if (!ccs_flush(head))
 		return false;
+	//if (head->type == CCS_EXCEPTION_POLICY && head->r.acl_group_name)
+	//printk(KERN_INFO "%s ptr=%p\n", __func__, acl);
 	else if (acl_type == CCS_TYPE_PATH_ACL) {
 		struct ccs_path_acl *ptr
 			= container_of(acl, typeof(*ptr), head);
@@ -3883,6 +3916,11 @@
 			       "manual_domain_transition ");
 		ccs_set_string(head, ptr->domainname->name);
 #endif
+	} else if (acl_type == CCS_TYPE_USE_GROUP_ACL) {
+		struct ccs_use_group_acl *ptr =
+			container_of(acl, typeof(*ptr), head);
+		ccs_set_group(head, "use_group @");
+		ccs_set_string(head, ptr->group->group_name->name);
 	} else if (head->r.print_transition_related_only &&
 		   !may_trigger_transition) {
 		return true;
@@ -4198,8 +4236,17 @@
  */
 static int ccs_write_group(struct ccs_acl_param *param, const u8 type)
 {
-	struct ccs_group *group = ccs_get_group(param, type);
+	struct ccs_group *group;
 	int error = -EINVAL;
+	if (type == CCS_ACL_GROUP) {
+		char *data;
+		unsigned int group = simple_strtoul(param->data, &data, 10);
+		if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
+			return ccs_write_acl(param->ns,
+					     &param->ns->acl_group[group],
+					     data, param->is_delete);
+	}
+	group = ccs_get_group(param, type);
 	if (!group)
 		return -ENOMEM;
 	param->list = &group->member_list;
@@ -4218,6 +4265,11 @@
 		    !ccs_parse_number_union(param, &e->number))
 			goto out;
 		error = ccs_update_policy(sizeof(*e), param);
+	} else if (type == CCS_ACL_GROUP) {
+		error = ccs_write_acl(param->ns, param->list, param->data,
+				      param->is_delete);
+		//printk(KERN_INFO "%s: ptr=%p ret=%d\n", __func__, group,
+		//error);
 #ifdef CONFIG_CCSECURITY_NETWORK
 	} else {
 		struct ccs_address_group *e = &param->e.address_group;
@@ -4404,15 +4456,6 @@
 	for (i = 0; i < CCS_MAX_GROUP; i++)
 		if (ccs_str_starts(&param.data, ccs_group_name[i]))
 			return ccs_write_group(&param, i);
-	if (ccs_str_starts(&param.data, "acl_group ")) {
-		unsigned int group;
-		char *data;
-		group = simple_strtoul(param.data, &data, 10);
-		if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
-			return ccs_write_acl(head->w.ns,
-					     &head->w.ns->acl_group[group],
-					     data, is_delete);
-	}
 	return -EINVAL;
 }
 
@@ -4431,6 +4474,22 @@
 	struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
 						       namespace_list);
 	struct list_head *list = &ns->group_list[idx];
+	if (idx == CCS_ACL_GROUP) {
+		list_for_each_cookie(head->r.group, list) {
+			struct ccs_group *group =
+				list_entry(head->r.group, typeof(*group),
+					   head.list);
+			printk(KERN_INFO "%s ptr=%p\n", __func__, group);
+			head->r.acl_group_name = group->group_name;
+			head->r.domain = &group->member_list;
+			if (!ccs_read_acl(head, head->r.domain))
+				return false;
+			head->r.acl_group_name = NULL;
+			head->r.domain = NULL;
+		}
+		head->r.group = NULL;
+		return true;
+	}
 	list_for_each_cookie(head->r.group, list) {
 		struct ccs_group *group =
 			list_entry(head->r.group, typeof(*group), head.list);
Index: gc.c
===================================================================
--- gc.c	(revision 5696)
+++ gc.c	(working copy)
@@ -152,6 +152,7 @@
 		[CCS_TYPE_AUTO_TASK_ACL] = sizeof(struct ccs_task_acl),
 		[CCS_TYPE_MANUAL_TASK_ACL] = sizeof(struct ccs_task_acl),
 #endif
+		[CCS_TYPE_USE_GROUP_ACL] = sizeof(struct ccs_use_group_acl),
 	};
 	size_t size;
 	if (type == CCS_ID_ACL)
@@ -487,6 +488,12 @@
 		}
 		break;
 #endif
+	case CCS_TYPE_USE_GROUP_ACL:
+		{
+			struct ccs_use_group_acl *entry =
+				container_of(acl, typeof(*entry), head);
+			ccs_put_group(entry->group);
+		}
 	}
 }
 
@@ -897,28 +904,35 @@
 			struct list_head *list = &ns->group_list[i];
 			struct ccs_group *group;
 			struct ccs_group *tmp;
-			switch (i) {
-			case 0:
+			if (i == CCS_PATH_GROUP)
 				id = CCS_ID_PATH_GROUP;
-				break;
-			case 1:
+			else if (i == CCS_NUMBER_GROUP)
 				id = CCS_ID_NUMBER_GROUP;
-				break;
-			default:
+			else if (i == CCS_ACL_GROUP)
+				id = CCS_ID_ACL;
 #ifdef CONFIG_CCSECURITY_NETWORK
+			else
 				id = CCS_ID_ADDRESS_GROUP;
-#else
-				continue;
 #endif
-				break;
-			}
 			list_for_each_entry_safe(group, tmp, list, head.list) {
-				ccs_collect_member(id, &group->member_list);
+				if (id == CCS_ID_ACL)
+					ccs_collect_acl(&group->member_list);
+				else
+					ccs_collect_member(id, &group->
+							   member_list);
 				if (!list_empty(&group->member_list) ||
-				    atomic_read(&group->head.users) > 0)
+				    atomic_read(&group->head.users) > 0) {
+					if (id == CCS_ID_ACL)
+						printk("%s users=%d\n",
+			       __func__, atomic_read(&group->head.users));
 					continue;
+				}
 				atomic_set(&group->head.users,
 					   CCS_GC_IN_PROGRESS);
+				if (id == CCS_ID_ACL)
+					printk("%s trying to gc %s\n",
+					       __func__,
+					       group->group_name->name);
 				ccs_try_to_gc(CCS_ID_GROUP, &group->head.list);
 			}
 		}
