diff options
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r-- | security/selinux/ss/services.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 9ea2feca3cd4..223c1ff6ef23 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/mutex.h> | 51 | #include <linux/mutex.h> |
52 | #include <linux/selinux.h> | 52 | #include <linux/selinux.h> |
53 | #include <linux/flex_array.h> | 53 | #include <linux/flex_array.h> |
54 | #include <linux/vmalloc.h> | ||
54 | #include <net/netlabel.h> | 55 | #include <net/netlabel.h> |
55 | 56 | ||
56 | #include "flask.h" | 57 | #include "flask.h" |
@@ -991,7 +992,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
991 | { | 992 | { |
992 | char *scontextp; | 993 | char *scontextp; |
993 | 994 | ||
994 | *scontext = NULL; | 995 | if (scontext) |
996 | *scontext = NULL; | ||
995 | *scontext_len = 0; | 997 | *scontext_len = 0; |
996 | 998 | ||
997 | if (context->len) { | 999 | if (context->len) { |
@@ -1008,6 +1010,9 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
1008 | *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1; | 1010 | *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1; |
1009 | *scontext_len += mls_compute_context_len(context); | 1011 | *scontext_len += mls_compute_context_len(context); |
1010 | 1012 | ||
1013 | if (!scontext) | ||
1014 | return 0; | ||
1015 | |||
1011 | /* Allocate space for the context; caller must free this space. */ | 1016 | /* Allocate space for the context; caller must free this space. */ |
1012 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); | 1017 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); |
1013 | if (!scontextp) | 1018 | if (!scontextp) |
@@ -1047,7 +1052,8 @@ static int security_sid_to_context_core(u32 sid, char **scontext, | |||
1047 | struct context *context; | 1052 | struct context *context; |
1048 | int rc = 0; | 1053 | int rc = 0; |
1049 | 1054 | ||
1050 | *scontext = NULL; | 1055 | if (scontext) |
1056 | *scontext = NULL; | ||
1051 | *scontext_len = 0; | 1057 | *scontext_len = 0; |
1052 | 1058 | ||
1053 | if (!ss_initialized) { | 1059 | if (!ss_initialized) { |
@@ -1055,6 +1061,8 @@ static int security_sid_to_context_core(u32 sid, char **scontext, | |||
1055 | char *scontextp; | 1061 | char *scontextp; |
1056 | 1062 | ||
1057 | *scontext_len = strlen(initial_sid_to_string[sid]) + 1; | 1063 | *scontext_len = strlen(initial_sid_to_string[sid]) + 1; |
1064 | if (!scontext) | ||
1065 | goto out; | ||
1058 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); | 1066 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); |
1059 | if (!scontextp) { | 1067 | if (!scontextp) { |
1060 | rc = -ENOMEM; | 1068 | rc = -ENOMEM; |
@@ -1769,6 +1777,7 @@ int security_load_policy(void *data, size_t len) | |||
1769 | return rc; | 1777 | return rc; |
1770 | } | 1778 | } |
1771 | 1779 | ||
1780 | policydb.len = len; | ||
1772 | rc = selinux_set_mapping(&policydb, secclass_map, | 1781 | rc = selinux_set_mapping(&policydb, secclass_map, |
1773 | ¤t_mapping, | 1782 | ¤t_mapping, |
1774 | ¤t_mapping_size); | 1783 | ¤t_mapping_size); |
@@ -1791,6 +1800,7 @@ int security_load_policy(void *data, size_t len) | |||
1791 | selinux_complete_init(); | 1800 | selinux_complete_init(); |
1792 | avc_ss_reset(seqno); | 1801 | avc_ss_reset(seqno); |
1793 | selnl_notify_policyload(seqno); | 1802 | selnl_notify_policyload(seqno); |
1803 | selinux_status_update_policyload(seqno); | ||
1794 | selinux_netlbl_cache_invalidate(); | 1804 | selinux_netlbl_cache_invalidate(); |
1795 | selinux_xfrm_notify_policyload(); | 1805 | selinux_xfrm_notify_policyload(); |
1796 | return 0; | 1806 | return 0; |
@@ -1804,6 +1814,7 @@ int security_load_policy(void *data, size_t len) | |||
1804 | if (rc) | 1814 | if (rc) |
1805 | return rc; | 1815 | return rc; |
1806 | 1816 | ||
1817 | newpolicydb.len = len; | ||
1807 | /* If switching between different policy types, log MLS status */ | 1818 | /* If switching between different policy types, log MLS status */ |
1808 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) | 1819 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) |
1809 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); | 1820 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); |
@@ -1870,6 +1881,7 @@ int security_load_policy(void *data, size_t len) | |||
1870 | 1881 | ||
1871 | avc_ss_reset(seqno); | 1882 | avc_ss_reset(seqno); |
1872 | selnl_notify_policyload(seqno); | 1883 | selnl_notify_policyload(seqno); |
1884 | selinux_status_update_policyload(seqno); | ||
1873 | selinux_netlbl_cache_invalidate(); | 1885 | selinux_netlbl_cache_invalidate(); |
1874 | selinux_xfrm_notify_policyload(); | 1886 | selinux_xfrm_notify_policyload(); |
1875 | 1887 | ||
@@ -1883,6 +1895,17 @@ err: | |||
1883 | 1895 | ||
1884 | } | 1896 | } |
1885 | 1897 | ||
1898 | size_t security_policydb_len(void) | ||
1899 | { | ||
1900 | size_t len; | ||
1901 | |||
1902 | read_lock(&policy_rwlock); | ||
1903 | len = policydb.len; | ||
1904 | read_unlock(&policy_rwlock); | ||
1905 | |||
1906 | return len; | ||
1907 | } | ||
1908 | |||
1886 | /** | 1909 | /** |
1887 | * security_port_sid - Obtain the SID for a port. | 1910 | * security_port_sid - Obtain the SID for a port. |
1888 | * @protocol: protocol number | 1911 | * @protocol: protocol number |
@@ -2374,6 +2397,7 @@ out: | |||
2374 | if (!rc) { | 2397 | if (!rc) { |
2375 | avc_ss_reset(seqno); | 2398 | avc_ss_reset(seqno); |
2376 | selnl_notify_policyload(seqno); | 2399 | selnl_notify_policyload(seqno); |
2400 | selinux_status_update_policyload(seqno); | ||
2377 | selinux_xfrm_notify_policyload(); | 2401 | selinux_xfrm_notify_policyload(); |
2378 | } | 2402 | } |
2379 | return rc; | 2403 | return rc; |
@@ -3129,3 +3153,38 @@ netlbl_sid_to_secattr_failure: | |||
3129 | return rc; | 3153 | return rc; |
3130 | } | 3154 | } |
3131 | #endif /* CONFIG_NETLABEL */ | 3155 | #endif /* CONFIG_NETLABEL */ |
3156 | |||
3157 | /** | ||
3158 | * security_read_policy - read the policy. | ||
3159 | * @data: binary policy data | ||
3160 | * @len: length of data in bytes | ||
3161 | * | ||
3162 | */ | ||
3163 | int security_read_policy(void **data, ssize_t *len) | ||
3164 | { | ||
3165 | int rc; | ||
3166 | struct policy_file fp; | ||
3167 | |||
3168 | if (!ss_initialized) | ||
3169 | return -EINVAL; | ||
3170 | |||
3171 | *len = security_policydb_len(); | ||
3172 | |||
3173 | *data = vmalloc_user(*len); | ||
3174 | if (!*data) | ||
3175 | return -ENOMEM; | ||
3176 | |||
3177 | fp.data = *data; | ||
3178 | fp.len = *len; | ||
3179 | |||
3180 | read_lock(&policy_rwlock); | ||
3181 | rc = policydb_write(&policydb, &fp); | ||
3182 | read_unlock(&policy_rwlock); | ||
3183 | |||
3184 | if (rc) | ||
3185 | return rc; | ||
3186 | |||
3187 | *len = (unsigned long)fp.data - (unsigned long)*data; | ||
3188 | return 0; | ||
3189 | |||
3190 | } | ||