aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/services.c
diff options
context:
space:
mode:
authorChad Sellers <csellers@tresys.com>2006-11-06 12:38:18 -0500
committerJames Morris <jmorris@namei.org>2006-11-28 12:04:38 -0500
commitb94c7e677b9d28bd3f9ba4a70df6bfa7942867ca (patch)
treeea116d586f821526513d32fd5e7c2f8fa6d59485 /security/selinux/ss/services.c
parentbb242497474da317a7169cc939c741ccf2e79e8c (diff)
SELinux: validate kernel object classes and permissions
This is a new object class and permission validation scheme that validates against the defined kernel headers. This scheme allows extra classes and permissions that do not conflict with the kernel definitions to be added to the policy. This validation is now done for all policy loads, not just subsequent loads after the first policy load. The implementation walks the three structrures containing the defined object class and permission values and ensures their values are the same in the policy being loaded. This includes verifying the object classes themselves, the permissions they contain, and the permissions they inherit from commons. Classes or permissions that are present in the kernel but missing from the policy cause a warning (printed to KERN_INFO) to be printed, but do not stop the policy from loading, emulating current behavior. Any other inconsistencies cause the load to fail. Signed-off-by: Chad Sellers <csellers@tresys.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r--security/selinux/ss/services.c138
1 files changed, 137 insertions, 1 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 33ae1020091e..408820486af0 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -17,9 +17,13 @@
17 * 17 *
18 * Added support for NetLabel 18 * Added support for NetLabel
19 * 19 *
20 * Updated: Chad Sellers <csellers@tresys.com>
21 *
22 * Added validation of kernel classes and permissions
23 *
20 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. 24 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
21 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 25 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
22 * Copyright (C) 2003 - 2004 Tresys Technology, LLC 26 * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
23 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 27 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
24 * This program is free software; you can redistribute it and/or modify 28 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by 29 * it under the terms of the GNU General Public License as published by
@@ -53,6 +57,11 @@
53extern void selnl_notify_policyload(u32 seqno); 57extern void selnl_notify_policyload(u32 seqno);
54unsigned int policydb_loaded_version; 58unsigned int policydb_loaded_version;
55 59
60/*
61 * This is declared in avc.c
62 */
63extern const struct selinux_class_perm selinux_class_perm;
64
56static DEFINE_RWLOCK(policy_rwlock); 65static DEFINE_RWLOCK(policy_rwlock);
57#define POLICY_RDLOCK read_lock(&policy_rwlock) 66#define POLICY_RDLOCK read_lock(&policy_rwlock)
58#define POLICY_WRLOCK write_lock_irq(&policy_rwlock) 67#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
@@ -1018,6 +1027,115 @@ int security_change_sid(u32 ssid,
1018 return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); 1027 return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);
1019} 1028}
1020 1029
1030/*
1031 * Verify that each kernel class that is defined in the
1032 * policy is correct
1033 */
1034static int validate_classes(struct policydb *p)
1035{
1036 int i, j;
1037 struct class_datum *cladatum;
1038 struct perm_datum *perdatum;
1039 u32 nprim, tmp, common_pts_len, perm_val, pol_val;
1040 u16 class_val;
1041 const struct selinux_class_perm *kdefs = &selinux_class_perm;
1042 const char *def_class, *def_perm, *pol_class;
1043 struct symtab *perms;
1044
1045 for (i = 1; i < kdefs->cts_len; i++) {
1046 def_class = kdefs->class_to_string[i];
1047 if (i > p->p_classes.nprim) {
1048 printk(KERN_INFO
1049 "security: class %s not defined in policy\n",
1050 def_class);
1051 continue;
1052 }
1053 pol_class = p->p_class_val_to_name[i-1];
1054 if (strcmp(pol_class, def_class)) {
1055 printk(KERN_ERR
1056 "security: class %d is incorrect, found %s but should be %s\n",
1057 i, pol_class, def_class);
1058 return -EINVAL;
1059 }
1060 }
1061 for (i = 0; i < kdefs->av_pts_len; i++) {
1062 class_val = kdefs->av_perm_to_string[i].tclass;
1063 perm_val = kdefs->av_perm_to_string[i].value;
1064 def_perm = kdefs->av_perm_to_string[i].name;
1065 if (class_val > p->p_classes.nprim)
1066 continue;
1067 pol_class = p->p_class_val_to_name[class_val-1];
1068 cladatum = hashtab_search(p->p_classes.table, pol_class);
1069 BUG_ON(!cladatum);
1070 perms = &cladatum->permissions;
1071 nprim = 1 << (perms->nprim - 1);
1072 if (perm_val > nprim) {
1073 printk(KERN_INFO
1074 "security: permission %s in class %s not defined in policy\n",
1075 def_perm, pol_class);
1076 continue;
1077 }
1078 perdatum = hashtab_search(perms->table, def_perm);
1079 if (perdatum == NULL) {
1080 printk(KERN_ERR
1081 "security: permission %s in class %s not found in policy\n",
1082 def_perm, pol_class);
1083 return -EINVAL;
1084 }
1085 pol_val = 1 << (perdatum->value - 1);
1086 if (pol_val != perm_val) {
1087 printk(KERN_ERR
1088 "security: permission %s in class %s has incorrect value\n",
1089 def_perm, pol_class);
1090 return -EINVAL;
1091 }
1092 }
1093 for (i = 0; i < kdefs->av_inherit_len; i++) {
1094 class_val = kdefs->av_inherit[i].tclass;
1095 if (class_val > p->p_classes.nprim)
1096 continue;
1097 pol_class = p->p_class_val_to_name[class_val-1];
1098 cladatum = hashtab_search(p->p_classes.table, pol_class);
1099 BUG_ON(!cladatum);
1100 if (!cladatum->comdatum) {
1101 printk(KERN_ERR
1102 "security: class %s should have an inherits clause but does not\n",
1103 pol_class);
1104 return -EINVAL;
1105 }
1106 tmp = kdefs->av_inherit[i].common_base;
1107 common_pts_len = 0;
1108 while (!(tmp & 0x01)) {
1109 common_pts_len++;
1110 tmp >>= 1;
1111 }
1112 perms = &cladatum->comdatum->permissions;
1113 for (j = 0; j < common_pts_len; j++) {
1114 def_perm = kdefs->av_inherit[i].common_pts[j];
1115 if (j >= perms->nprim) {
1116 printk(KERN_INFO
1117 "security: permission %s in class %s not defined in policy\n",
1118 def_perm, pol_class);
1119 continue;
1120 }
1121 perdatum = hashtab_search(perms->table, def_perm);
1122 if (perdatum == NULL) {
1123 printk(KERN_ERR
1124 "security: permission %s in class %s not found in policy\n",
1125 def_perm, pol_class);
1126 return -EINVAL;
1127 }
1128 if (perdatum->value != j + 1) {
1129 printk(KERN_ERR
1130 "security: permission %s in class %s has incorrect value\n",
1131 def_perm, pol_class);
1132 return -EINVAL;
1133 }
1134 }
1135 }
1136 return 0;
1137}
1138
1021/* Clone the SID into the new SID table. */ 1139/* Clone the SID into the new SID table. */
1022static int clone_sid(u32 sid, 1140static int clone_sid(u32 sid,
1023 struct context *context, 1141 struct context *context,
@@ -1160,6 +1278,16 @@ int security_load_policy(void *data, size_t len)
1160 avtab_cache_destroy(); 1278 avtab_cache_destroy();
1161 return -EINVAL; 1279 return -EINVAL;
1162 } 1280 }
1281 /* Verify that the kernel defined classes are correct. */
1282 if (validate_classes(&policydb)) {
1283 printk(KERN_ERR
1284 "security: the definition of a class is incorrect\n");
1285 LOAD_UNLOCK;
1286 sidtab_destroy(&sidtab);
1287 policydb_destroy(&policydb);
1288 avtab_cache_destroy();
1289 return -EINVAL;
1290 }
1163 policydb_loaded_version = policydb.policyvers; 1291 policydb_loaded_version = policydb.policyvers;
1164 ss_initialized = 1; 1292 ss_initialized = 1;
1165 seqno = ++latest_granting; 1293 seqno = ++latest_granting;
@@ -1182,6 +1310,14 @@ int security_load_policy(void *data, size_t len)
1182 1310
1183 sidtab_init(&newsidtab); 1311 sidtab_init(&newsidtab);
1184 1312
1313 /* Verify that the kernel defined classes are correct. */
1314 if (validate_classes(&newpolicydb)) {
1315 printk(KERN_ERR
1316 "security: the definition of a class is incorrect\n");
1317 rc = -EINVAL;
1318 goto err;
1319 }
1320
1185 /* Clone the SID table. */ 1321 /* Clone the SID table. */
1186 sidtab_shutdown(&sidtab); 1322 sidtab_shutdown(&sidtab);
1187 if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { 1323 if (sidtab_map(&sidtab, clone_sid, &newsidtab)) {