diff --git a/policy/flask/access_vectors b/policy/flask/access_vectors
index 6760c95..1e1a6a3 100644
--- a/policy/flask/access_vectors
+++ b/policy/flask/access_vectors
@@ -816,3 +816,17 @@ inherits x_device
class x_keyboard
inherits x_device
+
+class kv_item
+{
+ create
+ getattr
+ setattr
+ remove
+ relabelfrom
+ relabelto
+ read
+ write
+ append
+ calculate
+}
diff --git a/policy/flask/security_classes b/policy/flask/security_classes
index fa65db2..9ace105 100644
--- a/policy/flask/security_classes
+++ b/policy/flask/security_classes
@@ -125,4 +125,7 @@ class tun_socket
class x_pointer # userspace
class x_keyboard # userspace
+# key-value-store, such as memcached
+class kv_item # userspace
+
# FLASK
diff --git a/policy/mcs b/policy/mcs
index af90ef2..bcc0c54 100644
--- a/policy/mcs
+++ b/policy/mcs
@@ -132,4 +132,13 @@ mlsconstrain db_procedure { drop getattr setattr execute install }
mlsconstrain db_blob { drop getattr setattr relabelfrom read write import export }
( h1 dom h2 );
+#
+# MCS policy for key-value items with SELinux support
+#
+mlsconstrain kv_item { create relabelto }
+ (( h1 dom h2 ) and ( l2 eq h2 ));
+
+mlsconstrain kv_item { getattr setattr remove read write append calculate }
+ ( h1 dom h2 );
+
') dnl end enable_mcs
diff --git a/policy/mls b/policy/mls
index b9f0a3e..75a5b98 100644
--- a/policy/mls
+++ b/policy/mls
@@ -827,4 +827,42 @@ mlsvalidatetrans { db_database db_table db_procedure db_column db_tuple db_blob
(( t3 == mlsdbdowngrade ) and ( h1 dom h2 )) or
(( t3 == mlsdbdowngrade ) and ( h1 incomp h2 ))));
+#
+# MLS policy for key-value store
+#
+
+# make sure kv_item has single level
+mlsconstrain { kv_item } { create relabelto }
+ ( l2 eq h2 );
+
+# new label must be dominated by the subjects clearance
+mlsconstrain { kv_item } { relabelto }
+ ( h1 dom h2 );
+
+# the key-value item "read" operations
+mlsconstrain { kv_item } { getattr read }
+ (( l1 dom l2 ) or
+ (( t1 == mlsdbreadtoclr ) and ( h1 dom l2 )) or
+ ( t1 == mlsdbread ) or
+ ( t2 == mlstrustedobject ));
+
+# the key-value item "write" operations
+mlsconstrain { kv_item } { create remove setattr write append calculate }
+ (( l1 eq l2 ) or
+ (( t1 == mlsdbwritetoclr ) and ( h1 dom l2 ) and ( l1 domby l2 )) or
+ (( t2 == mlsdbwriteinrange ) and ( l1 dom l2 ) and ( h1 domby h2 )) or
+ ( t1 == mlsdbwrite ) or
+ ( t2 == mlstrustedobject ));
+
+# the key-value item upgrade/downgrade rule
+mlsvalidatetrans { kv_item }
+ ((( l1 eq l2 ) or
+ (( t3 == mlsdbupgrade ) and ( l1 domby l2 )) or
+ (( t3 == mlsdbdowngrade ) and ( l1 dom l2 )) or
+ (( t3 == mlsdbdowngrade ) and ( l1 incomp l2 ))) and
+ (( l1 eq h2 ) or
+ (( t3 == mlsdbupgrade ) and ( h1 domby h2 )) or
+ (( t3 == mlsdbdowngrade ) and ( h1 dom h2 )) or
+ (( t3 == mlsdbdowngrade ) and ( h1 incomp h2 ))));
+
') dnl end enable_mls
diff --git a/policy/modules/roles/staff.te b/policy/modules/roles/staff.te
index 30754e4..c447f70 100644
--- a/policy/modules/roles/staff.te
+++ b/policy/modules/roles/staff.te
@@ -79,6 +79,10 @@ optional_policy(`
')
optional_policy(`
+ memcached_role(staff_r, staff_t)
+')
+
+optional_policy(`
mozilla_role(staff_r, staff_t)
')
diff --git a/policy/modules/roles/unprivuser.te b/policy/modules/roles/unprivuser.te
index d5d5042..f737a33 100644
--- a/policy/modules/roles/unprivuser.te
+++ b/policy/modules/roles/unprivuser.te
@@ -73,6 +73,10 @@ optional_policy(`
')
optional_policy(`
+ memcached_role(user_r, user_t)
+')
+
+optional_policy(`
mozilla_role(user_r, user_t)
')
diff --git a/policy/modules/services/apache.if b/policy/modules/services/apache.if
index 57feb5a..9fe608d 100644
--- a/policy/modules/services/apache.if
+++ b/policy/modules/services/apache.if
@@ -175,6 +175,14 @@ template(`apache_content_template',`
')
optional_policy(`
+ memcached_unpriv_client(httpd_$1_script_t)
+
+ tunable_policy(`httpd_enable_cgi && httpd_can_network_connect_db',`
+ memcached_tcp_connect(httpd_$1_script_t)
+ ')
+ ')
+
+ optional_policy(`
tunable_policy(`httpd_enable_cgi && allow_ypbind',`
nis_use_ypbind_uncond(httpd_$1_script_t)
')
diff --git a/policy/modules/services/apache.te b/policy/modules/services/apache.te
index e33b9cd..da1b513 100644
--- a/policy/modules/services/apache.te
+++ b/policy/modules/services/apache.te
@@ -570,6 +570,16 @@ optional_policy(`
')
optional_policy(`
+ # Allow httpd to work with memcached
+ memcached_stream_connect(httpd_t)
+ memcached_unpriv_client(httpd_t)
+
+ tunable_policy(`httpd_can_network_connect_db',`
+ memcached_tcp_connect(httpd_t)
+ ')
+')
+
+optional_policy(`
openca_domtrans(httpd_t)
openca_signal(httpd_t)
openca_sigstop(httpd_t)
diff --git a/policy/modules/services/memcached.if b/policy/modules/services/memcached.if
index db4fd6f..9f2e07b 100644
--- a/policy/modules/services/memcached.if
+++ b/policy/modules/services/memcached.if
@@ -71,3 +71,148 @@ interface(`memcached_admin',`
admin_pattern($1, memcached_var_run_t)
')
+
+########################################
+##
+## Marks as a memcached key/value item type
+##
+##
+##
+## Type marked as a memcached key/value item type.
+##
+##
+#
+interface(`memcached_item_object',`
+ gen_require(`
+ attribute memcached_item_type;
+ ')
+
+ typeattribute $1 memcached_item_type;
+')
+
+########################################
+##
+## Allow the specified domain to connect to memcached with a tcp socket.
+##
+##
+##
+## Domain allowed access.
+##
+##
+#
+interface(`memcached_tcp_connect',`
+ gen_require(`
+ type memcached_t;
+ ')
+
+ corenet_tcp_recvfrom_labeled($1, memcached_t)
+ corenet_tcp_sendrecv_memcache_port($1)
+ corenet_tcp_connect_memcache_port($1)
+ corenet_sendrecv_memcache_client_packets($1)
+')
+
+########################################
+##
+## Allow the specified domain to connect to memcached with a unix socket.
+##
+##
+##
+## Domain allowed access.
+##
+##
+##
+#
+interface(`memcached_stream_connect',`
+ gen_require(`
+ type memcached_t;
+ type memcached_var_run_t;
+ ')
+
+ files_search_pids($1)
+ allow $1 memcached_t:unix_stream_socket connectto;
+ # we recommend to put the sock file in /var/run/memcached
+ rw_sock_files_pattern($1, memcached_var_run_t, memcached_var_run_t)
+')
+
+########################################
+##
+## Allow the specified domain unconfined accesses to any memcached items.
+##
+##
+##
+## Domain allowed access.
+##
+##
+#
+interface(`memcached_unconfined',`
+ gen_require(`
+ attribute memcached_unconfined_type;
+ ')
+ typeattribute $1 memcached_unconfined_type;
+')
+
+#######################################
+##
+## Role access to memcached with SELinux suport
+##
+##
+##
+## The role associated with the user domain.
+##
+##
+##
+##
+## The type of the user domain.
+##
+##
+#
+interface(`memcached_role',`
+ gen_require(`
+ class kv_item all_kv_item_perms;
+
+ attribute memcached_client_type;
+ type memcached_t;
+ type user_memcached_item_t;
+ ')
+
+ ########################################
+ #
+ # Client local policy
+ #
+ typeattribute $2 memcached_client_type;
+
+ type_transition $2 memcached_t:kv_item user_memcached_item_t;
+
+ allow $2 user_memcached_item_t:kv_item { create getattr setattr remove read write append calculate };
+')
+
+########################################
+##
+## Allow the specified domain unprivileged accesses to unifined key-value
+## items managed by memcached with SELinux support.
+##
+##
+##
+## Domain allowed access.
+##
+##
+#
+interface(`memcached_unpriv_client',`
+ gen_require(`
+ class kv_item all_kv_item_perms;
+
+ attribute memcached_client_type;
+ type memcached_t;
+ type unpriv_memcached_item_t;
+ ')
+
+ ########################################
+ #
+ # Client local policy
+ #
+ typeattribute $1 memcached_client_type;
+
+ type_transition $1 memcached_t:kv_item unpriv_memcached_item_t;
+
+ allow $1 unpriv_memcached_item_t:kv_item { create getattr setattr remove read write calculate };
+')
diff --git a/policy/modules/services/memcached.te b/policy/modules/services/memcached.te
index b681608..854d904 100644
--- a/policy/modules/services/memcached.te
+++ b/policy/modules/services/memcached.te
@@ -15,6 +15,33 @@ init_script_file(memcached_initrc_exec_t)
type memcached_var_run_t;
files_pid_file(memcached_var_run_t)
+type memcached_db_t;
+files_type(memcached_db_t)
+
+# memcached clients
+attribute memcached_client_type;
+attribute memcached_unconfined_type;
+
+# memcached key/value items
+attribute memcached_item_type;
+
+type memcached_item_t;
+memcached_item_object(memcached_item_t)
+
+type memcached_ro_item_t;
+memcached_item_object(memcached_ro_item_t)
+
+type memcached_secret_item_t;
+memcached_item_object(memcached_secret_item_t)
+
+type user_memcached_item_t;
+typealias user_memcached_item_t alias { staff_memcached_item_t sysadm_memcached_item_t };
+typealias user_memcached_item_t alias { auditadm_memcached_item_t secadm_memcached_item_t };
+memcached_item_object(user_memcached_item_t)
+
+type unpriv_memcached_item_t;
+memcached_item_object(unpriv_memcached_item_t)
+
########################################
#
# memcached local policy
@@ -27,6 +54,7 @@ allow memcached_t self:tcp_socket create_stream_socket_perms;
allow memcached_t self:udp_socket { create_socket_perms listen };
allow memcached_t self:fifo_file rw_fifo_file_perms;
allow memcached_t self:unix_stream_socket create_stream_socket_perms;
+allow memcached_t self:netlink_selinux_socket create_socket_perms;
corenet_all_recvfrom_unlabeled(memcached_t)
corenet_udp_sendrecv_generic_if(memcached_t)
@@ -42,17 +70,41 @@ corenet_udp_bind_memcache_port(memcached_t)
manage_dirs_pattern(memcached_t, memcached_var_run_t, memcached_var_run_t)
manage_files_pattern(memcached_t, memcached_var_run_t, memcached_var_run_t)
+manage_sock_files_pattern(memcached_t, memcached_var_run_t, memcached_var_run_t)
files_pid_filetrans(memcached_t, memcached_var_run_t, { file dir })
+manage_files_pattern(memcached_t, memcached_db_t, memcached_db_t)
+
kernel_read_kernel_sysctls(memcached_t)
kernel_read_system_state(memcached_t)
files_read_etc_files(memcached_t)
+selinux_get_enforce_mode(memcached_t)
+selinux_validate_context(memcached_t)
+selinux_compute_access_vector(memcached_t)
+selinux_compute_create_context(memcached_t)
+selinux_compute_relabel_context(memcached_t)
+
term_dontaudit_use_all_ptys(memcached_t)
term_dontaudit_use_all_ttys(memcached_t)
term_dontaudit_use_console(memcached_t)
auth_use_nsswitch(memcached_t)
+logging_send_audit_msgs(memcached_t)
+
miscfiles_read_localization(memcached_t)
+
+########################################
+#
+# Rules to managed items by memcached with SELinux support
+#
+gen_require(`
+ class kv_item all_kv_item_perms;
+')
+
+allow memcached_client_type memcached_item_t:kv_item { getattr setattr read write append calculate };
+allow memcached_client_type memcached_ro_item_t:kv_item { getattr read };
+type_transition memcached_unconfined_type memcached_t:kv_item memcached_item_t;
+allow memcached_unconfined_type memcached_item_type:kv_item *;
diff --git a/policy/modules/system/unconfined.if b/policy/modules/system/unconfined.if
index c11cb30..85645fc 100644
--- a/policy/modules/system/unconfined.if
+++ b/policy/modules/system/unconfined.if
@@ -77,6 +77,10 @@ interface(`unconfined_domain_noaudit',`
')
optional_policy(`
+ memcached_unconfined($1)
+ ')
+
+ optional_policy(`
nscd_unconfined($1)
')
diff --git a/policy/modules/system/userdomain.if b/policy/modules/system/userdomain.if
index fafdd3d..525f3b0 100644
--- a/policy/modules/system/userdomain.if
+++ b/policy/modules/system/userdomain.if
@@ -626,6 +626,11 @@ template(`userdom_common_user_template',`
locate_read_lib_files($1_t)
')
+ optional_policy(`
+ memcached_stream_connect($1_t)
+ memcached_tcp_connect($1_t)
+ ')
+
# for running depmod as part of the kernel packaging process
optional_policy(`
modutils_read_module_config($1_t)
@@ -1159,6 +1164,10 @@ template(`userdom_admin_user_template',`
')
optional_policy(`
+ memcached_unconfined($1_t)
+ ')
+
+ optional_policy(`
postgresql_unconfined($1_t)
')