aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/services.c
diff options
context:
space:
mode:
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)) {