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.c437
1 files changed, 236 insertions, 201 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index bfe122764c98..bdb7070dd3dc 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
@@ -29,6 +33,7 @@
29#include <linux/slab.h> 33#include <linux/slab.h>
30#include <linux/string.h> 34#include <linux/string.h>
31#include <linux/spinlock.h> 35#include <linux/spinlock.h>
36#include <linux/rcupdate.h>
32#include <linux/errno.h> 37#include <linux/errno.h>
33#include <linux/in.h> 38#include <linux/in.h>
34#include <linux/sched.h> 39#include <linux/sched.h>
@@ -49,10 +54,17 @@
49#include "mls.h" 54#include "mls.h"
50#include "objsec.h" 55#include "objsec.h"
51#include "selinux_netlabel.h" 56#include "selinux_netlabel.h"
57#include "xfrm.h"
58#include "ebitmap.h"
52 59
53extern void selnl_notify_policyload(u32 seqno); 60extern void selnl_notify_policyload(u32 seqno);
54unsigned int policydb_loaded_version; 61unsigned int policydb_loaded_version;
55 62
63/*
64 * This is declared in avc.c
65 */
66extern const struct selinux_class_perm selinux_class_perm;
67
56static DEFINE_RWLOCK(policy_rwlock); 68static DEFINE_RWLOCK(policy_rwlock);
57#define POLICY_RDLOCK read_lock(&policy_rwlock) 69#define POLICY_RDLOCK read_lock(&policy_rwlock)
58#define POLICY_WRLOCK write_lock_irq(&policy_rwlock) 70#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
@@ -1019,86 +1031,112 @@ int security_change_sid(u32 ssid,
1019} 1031}
1020 1032
1021/* 1033/*
1022 * Verify that each permission that is defined under the 1034 * Verify that each kernel class that is defined in the
1023 * existing policy is still defined with the same value 1035 * policy is correct
1024 * in the new policy.
1025 */
1026static int validate_perm(void *key, void *datum, void *p)
1027{
1028 struct hashtab *h;
1029 struct perm_datum *perdatum, *perdatum2;
1030 int rc = 0;
1031
1032
1033 h = p;
1034 perdatum = datum;
1035
1036 perdatum2 = hashtab_search(h, key);
1037 if (!perdatum2) {
1038 printk(KERN_ERR "security: permission %s disappeared",
1039 (char *)key);
1040 rc = -ENOENT;
1041 goto out;
1042 }
1043 if (perdatum->value != perdatum2->value) {
1044 printk(KERN_ERR "security: the value of permission %s changed",
1045 (char *)key);
1046 rc = -EINVAL;
1047 }
1048out:
1049 return rc;
1050}
1051
1052/*
1053 * Verify that each class that is defined under the
1054 * existing policy is still defined with the same
1055 * attributes in the new policy.
1056 */ 1036 */
1057static int validate_class(void *key, void *datum, void *p) 1037static int validate_classes(struct policydb *p)
1058{ 1038{
1059 struct policydb *newp; 1039 int i, j;
1060 struct class_datum *cladatum, *cladatum2; 1040 struct class_datum *cladatum;
1061 int rc; 1041 struct perm_datum *perdatum;
1062 1042 u32 nprim, tmp, common_pts_len, perm_val, pol_val;
1063 newp = p; 1043 u16 class_val;
1064 cladatum = datum; 1044 const struct selinux_class_perm *kdefs = &selinux_class_perm;
1065 1045 const char *def_class, *def_perm, *pol_class;
1066 cladatum2 = hashtab_search(newp->p_classes.table, key); 1046 struct symtab *perms;
1067 if (!cladatum2) { 1047
1068 printk(KERN_ERR "security: class %s disappeared\n", 1048 for (i = 1; i < kdefs->cts_len; i++) {
1069 (char *)key); 1049 def_class = kdefs->class_to_string[i];
1070 rc = -ENOENT; 1050 if (i > p->p_classes.nprim) {
1071 goto out; 1051 printk(KERN_INFO
1072 } 1052 "security: class %s not defined in policy\n",
1073 if (cladatum->value != cladatum2->value) { 1053 def_class);
1074 printk(KERN_ERR "security: the value of class %s changed\n", 1054 continue;
1075 (char *)key); 1055 }
1076 rc = -EINVAL; 1056 pol_class = p->p_class_val_to_name[i-1];
1077 goto out; 1057 if (strcmp(pol_class, def_class)) {
1058 printk(KERN_ERR
1059 "security: class %d is incorrect, found %s but should be %s\n",
1060 i, pol_class, def_class);
1061 return -EINVAL;
1062 }
1078 } 1063 }
1079 if ((cladatum->comdatum && !cladatum2->comdatum) || 1064 for (i = 0; i < kdefs->av_pts_len; i++) {
1080 (!cladatum->comdatum && cladatum2->comdatum)) { 1065 class_val = kdefs->av_perm_to_string[i].tclass;
1081 printk(KERN_ERR "security: the inherits clause for the access " 1066 perm_val = kdefs->av_perm_to_string[i].value;
1082 "vector definition for class %s changed\n", (char *)key); 1067 def_perm = kdefs->av_perm_to_string[i].name;
1083 rc = -EINVAL; 1068 if (class_val > p->p_classes.nprim)
1084 goto out; 1069 continue;
1070 pol_class = p->p_class_val_to_name[class_val-1];
1071 cladatum = hashtab_search(p->p_classes.table, pol_class);
1072 BUG_ON(!cladatum);
1073 perms = &cladatum->permissions;
1074 nprim = 1 << (perms->nprim - 1);
1075 if (perm_val > nprim) {
1076 printk(KERN_INFO
1077 "security: permission %s in class %s not defined in policy\n",
1078 def_perm, pol_class);
1079 continue;
1080 }
1081 perdatum = hashtab_search(perms->table, def_perm);
1082 if (perdatum == NULL) {
1083 printk(KERN_ERR
1084 "security: permission %s in class %s not found in policy\n",
1085 def_perm, pol_class);
1086 return -EINVAL;
1087 }
1088 pol_val = 1 << (perdatum->value - 1);
1089 if (pol_val != perm_val) {
1090 printk(KERN_ERR
1091 "security: permission %s in class %s has incorrect value\n",
1092 def_perm, pol_class);
1093 return -EINVAL;
1094 }
1085 } 1095 }
1086 if (cladatum->comdatum) { 1096 for (i = 0; i < kdefs->av_inherit_len; i++) {
1087 rc = hashtab_map(cladatum->comdatum->permissions.table, validate_perm, 1097 class_val = kdefs->av_inherit[i].tclass;
1088 cladatum2->comdatum->permissions.table); 1098 if (class_val > p->p_classes.nprim)
1089 if (rc) { 1099 continue;
1090 printk(" in the access vector definition for class " 1100 pol_class = p->p_class_val_to_name[class_val-1];
1091 "%s\n", (char *)key); 1101 cladatum = hashtab_search(p->p_classes.table, pol_class);
1092 goto out; 1102 BUG_ON(!cladatum);
1103 if (!cladatum->comdatum) {
1104 printk(KERN_ERR
1105 "security: class %s should have an inherits clause but does not\n",
1106 pol_class);
1107 return -EINVAL;
1108 }
1109 tmp = kdefs->av_inherit[i].common_base;
1110 common_pts_len = 0;
1111 while (!(tmp & 0x01)) {
1112 common_pts_len++;
1113 tmp >>= 1;
1114 }
1115 perms = &cladatum->comdatum->permissions;
1116 for (j = 0; j < common_pts_len; j++) {
1117 def_perm = kdefs->av_inherit[i].common_pts[j];
1118 if (j >= perms->nprim) {
1119 printk(KERN_INFO
1120 "security: permission %s in class %s not defined in policy\n",
1121 def_perm, pol_class);
1122 continue;
1123 }
1124 perdatum = hashtab_search(perms->table, def_perm);
1125 if (perdatum == NULL) {
1126 printk(KERN_ERR
1127 "security: permission %s in class %s not found in policy\n",
1128 def_perm, pol_class);
1129 return -EINVAL;
1130 }
1131 if (perdatum->value != j + 1) {
1132 printk(KERN_ERR
1133 "security: permission %s in class %s has incorrect value\n",
1134 def_perm, pol_class);
1135 return -EINVAL;
1136 }
1093 } 1137 }
1094 } 1138 }
1095 rc = hashtab_map(cladatum->permissions.table, validate_perm, 1139 return 0;
1096 cladatum2->permissions.table);
1097 if (rc)
1098 printk(" in access vector definition for class %s\n",
1099 (char *)key);
1100out:
1101 return rc;
1102} 1140}
1103 1141
1104/* Clone the SID into the new SID table. */ 1142/* Clone the SID into the new SID table. */
@@ -1243,6 +1281,16 @@ int security_load_policy(void *data, size_t len)
1243 avtab_cache_destroy(); 1281 avtab_cache_destroy();
1244 return -EINVAL; 1282 return -EINVAL;
1245 } 1283 }
1284 /* Verify that the kernel defined classes are correct. */
1285 if (validate_classes(&policydb)) {
1286 printk(KERN_ERR
1287 "security: the definition of a class is incorrect\n");
1288 LOAD_UNLOCK;
1289 sidtab_destroy(&sidtab);
1290 policydb_destroy(&policydb);
1291 avtab_cache_destroy();
1292 return -EINVAL;
1293 }
1246 policydb_loaded_version = policydb.policyvers; 1294 policydb_loaded_version = policydb.policyvers;
1247 ss_initialized = 1; 1295 ss_initialized = 1;
1248 seqno = ++latest_granting; 1296 seqno = ++latest_granting;
@@ -1265,10 +1313,10 @@ int security_load_policy(void *data, size_t len)
1265 1313
1266 sidtab_init(&newsidtab); 1314 sidtab_init(&newsidtab);
1267 1315
1268 /* Verify that the existing classes did not change. */ 1316 /* Verify that the kernel defined classes are correct. */
1269 if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) { 1317 if (validate_classes(&newpolicydb)) {
1270 printk(KERN_ERR "security: the definition of an existing " 1318 printk(KERN_ERR
1271 "class changed\n"); 1319 "security: the definition of a class is incorrect\n");
1272 rc = -EINVAL; 1320 rc = -EINVAL;
1273 goto err; 1321 goto err;
1274 } 1322 }
@@ -2145,6 +2193,32 @@ void selinux_audit_set_callback(int (*callback)(void))
2145 aurule_callback = callback; 2193 aurule_callback = callback;
2146} 2194}
2147 2195
2196/**
2197 * security_skb_extlbl_sid - Determine the external label of a packet
2198 * @skb: the packet
2199 * @base_sid: the SELinux SID to use as a context for MLS only external labels
2200 * @sid: the packet's SID
2201 *
2202 * Description:
2203 * Check the various different forms of external packet labeling and determine
2204 * the external SID for the packet.
2205 *
2206 */
2207void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2208{
2209 u32 xfrm_sid;
2210 u32 nlbl_sid;
2211
2212 selinux_skb_xfrm_sid(skb, &xfrm_sid);
2213 if (selinux_netlbl_skbuff_getsid(skb,
2214 (xfrm_sid == SECSID_NULL ?
2215 base_sid : xfrm_sid),
2216 &nlbl_sid) != 0)
2217 nlbl_sid = SECSID_NULL;
2218
2219 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
2220}
2221
2148#ifdef CONFIG_NETLABEL 2222#ifdef CONFIG_NETLABEL
2149/* 2223/*
2150 * This is the structure we store inside the NetLabel cache block. 2224 * This is the structure we store inside the NetLabel cache block.
@@ -2209,8 +2283,6 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2209 cache = kzalloc(sizeof(*cache), GFP_ATOMIC); 2283 cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
2210 if (cache == NULL) 2284 if (cache == NULL)
2211 goto netlbl_cache_add_return; 2285 goto netlbl_cache_add_return;
2212 secattr.cache->free = selinux_netlbl_cache_free;
2213 secattr.cache->data = (void *)cache;
2214 2286
2215 cache->type = NETLBL_CACHE_T_MLS; 2287 cache->type = NETLBL_CACHE_T_MLS;
2216 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, 2288 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
@@ -2223,6 +2295,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2223 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; 2295 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
2224 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; 2296 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
2225 2297
2298 secattr.cache->free = selinux_netlbl_cache_free;
2299 secattr.cache->data = (void *)cache;
2300 secattr.flags = NETLBL_SECATTR_CACHE;
2301
2226 netlbl_cache_add(skb, &secattr); 2302 netlbl_cache_add(skb, &secattr);
2227 2303
2228netlbl_cache_add_return: 2304netlbl_cache_add_return:
@@ -2268,7 +2344,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2268 2344
2269 POLICY_RDLOCK; 2345 POLICY_RDLOCK;
2270 2346
2271 if (secattr->cache) { 2347 if (secattr->flags & NETLBL_SECATTR_CACHE) {
2272 cache = NETLBL_CACHE(secattr->cache->data); 2348 cache = NETLBL_CACHE(secattr->cache->data);
2273 switch (cache->type) { 2349 switch (cache->type) {
2274 case NETLBL_CACHE_T_SID: 2350 case NETLBL_CACHE_T_SID:
@@ -2301,7 +2377,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2301 default: 2377 default:
2302 goto netlbl_secattr_to_sid_return; 2378 goto netlbl_secattr_to_sid_return;
2303 } 2379 }
2304 } else if (secattr->mls_lvl_vld) { 2380 } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
2305 ctx = sidtab_search(&sidtab, base_sid); 2381 ctx = sidtab_search(&sidtab, base_sid);
2306 if (ctx == NULL) 2382 if (ctx == NULL)
2307 goto netlbl_secattr_to_sid_return; 2383 goto netlbl_secattr_to_sid_return;
@@ -2309,13 +2385,10 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2309 ctx_new.user = ctx->user; 2385 ctx_new.user = ctx->user;
2310 ctx_new.role = ctx->role; 2386 ctx_new.role = ctx->role;
2311 ctx_new.type = ctx->type; 2387 ctx_new.type = ctx->type;
2312 mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl); 2388 mls_import_netlbl_lvl(&ctx_new, secattr);
2313 if (secattr->mls_cat) { 2389 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
2314 if (mls_import_cat(&ctx_new, 2390 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
2315 secattr->mls_cat, 2391 secattr->mls_cat) != 0)
2316 secattr->mls_cat_len,
2317 NULL,
2318 0) != 0)
2319 goto netlbl_secattr_to_sid_return; 2392 goto netlbl_secattr_to_sid_return;
2320 ctx_new.range.level[1].cat.highbit = 2393 ctx_new.range.level[1].cat.highbit =
2321 ctx_new.range.level[0].cat.highbit; 2394 ctx_new.range.level[0].cat.highbit;
@@ -2360,20 +2433,20 @@ netlbl_secattr_to_sid_return_cleanup:
2360 * assign to the packet. Returns zero on success, negative values on failure. 2433 * assign to the packet. Returns zero on success, negative values on failure.
2361 * 2434 *
2362 */ 2435 */
2363static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 2436int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2364 u32 base_sid,
2365 u32 *sid)
2366{ 2437{
2367 int rc; 2438 int rc;
2368 struct netlbl_lsm_secattr secattr; 2439 struct netlbl_lsm_secattr secattr;
2369 2440
2370 netlbl_secattr_init(&secattr); 2441 netlbl_secattr_init(&secattr);
2371 rc = netlbl_skbuff_getattr(skb, &secattr); 2442 rc = netlbl_skbuff_getattr(skb, &secattr);
2372 if (rc == 0) 2443 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
2373 rc = selinux_netlbl_secattr_to_sid(skb, 2444 rc = selinux_netlbl_secattr_to_sid(skb,
2374 &secattr, 2445 &secattr,
2375 base_sid, 2446 base_sid,
2376 sid); 2447 sid);
2448 else
2449 *sid = SECSID_NULL;
2377 netlbl_secattr_destroy(&secattr); 2450 netlbl_secattr_destroy(&secattr);
2378 2451
2379 return rc; 2452 return rc;
@@ -2386,7 +2459,9 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
2386 * 2459 *
2387 * Description: 2460 * Description:
2388 * Attempt to label a socket using the NetLabel mechanism using the given 2461 * Attempt to label a socket using the NetLabel mechanism using the given
2389 * SID. Returns zero values on success, negative values on failure. 2462 * SID. Returns zero values on success, negative values on failure. The
2463 * caller is responsibile for calling rcu_read_lock() before calling this
2464 * this function and rcu_read_unlock() after this function returns.
2390 * 2465 *
2391 */ 2466 */
2392static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) 2467static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
@@ -2409,19 +2484,18 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
2409 2484
2410 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], 2485 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2411 GFP_ATOMIC); 2486 GFP_ATOMIC);
2412 mls_export_lvl(ctx, &secattr.mls_lvl, NULL); 2487 secattr.flags |= NETLBL_SECATTR_DOMAIN;
2413 secattr.mls_lvl_vld = 1; 2488 mls_export_netlbl_lvl(ctx, &secattr);
2414 rc = mls_export_cat(ctx, 2489 rc = mls_export_netlbl_cat(ctx, &secattr);
2415 &secattr.mls_cat,
2416 &secattr.mls_cat_len,
2417 NULL,
2418 NULL);
2419 if (rc != 0) 2490 if (rc != 0)
2420 goto netlbl_socket_setsid_return; 2491 goto netlbl_socket_setsid_return;
2421 2492
2422 rc = netlbl_socket_setattr(sock, &secattr); 2493 rc = netlbl_socket_setattr(sock, &secattr);
2423 if (rc == 0) 2494 if (rc == 0) {
2495 spin_lock(&sksec->nlbl_lock);
2424 sksec->nlbl_state = NLBL_LABELED; 2496 sksec->nlbl_state = NLBL_LABELED;
2497 spin_unlock(&sksec->nlbl_lock);
2498 }
2425 2499
2426netlbl_socket_setsid_return: 2500netlbl_socket_setsid_return:
2427 POLICY_RDUNLOCK; 2501 POLICY_RDUNLOCK;
@@ -2430,6 +2504,25 @@ netlbl_socket_setsid_return:
2430} 2504}
2431 2505
2432/** 2506/**
2507 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
2508 * @ssec: the sk_security_struct
2509 * @family: the socket family
2510 *
2511 * Description:
2512 * Called when the NetLabel state of a sk_security_struct needs to be reset.
2513 * The caller is responsibile for all the NetLabel sk_security_struct locking.
2514 *
2515 */
2516void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
2517 int family)
2518{
2519 if (family == PF_INET)
2520 ssec->nlbl_state = NLBL_REQUIRE;
2521 else
2522 ssec->nlbl_state = NLBL_UNSET;
2523}
2524
2525/**
2433 * selinux_netlbl_sk_security_init - Setup the NetLabel fields 2526 * selinux_netlbl_sk_security_init - Setup the NetLabel fields
2434 * @ssec: the sk_security_struct 2527 * @ssec: the sk_security_struct
2435 * @family: the socket family 2528 * @family: the socket family
@@ -2442,14 +2535,13 @@ netlbl_socket_setsid_return:
2442void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, 2535void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
2443 int family) 2536 int family)
2444{ 2537{
2445 if (family == PF_INET) 2538 /* No locking needed, we are the only one who has access to ssec */
2446 ssec->nlbl_state = NLBL_REQUIRE; 2539 selinux_netlbl_sk_security_reset(ssec, family);
2447 else 2540 spin_lock_init(&ssec->nlbl_lock);
2448 ssec->nlbl_state = NLBL_UNSET;
2449} 2541}
2450 2542
2451/** 2543/**
2452 * selinux_netlbl_sk_clone_security - Copy the NetLabel fields 2544 * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
2453 * @ssec: the original sk_security_struct 2545 * @ssec: the original sk_security_struct
2454 * @newssec: the cloned sk_security_struct 2546 * @newssec: the cloned sk_security_struct
2455 * 2547 *
@@ -2458,41 +2550,41 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
2458 * @newssec. 2550 * @newssec.
2459 * 2551 *
2460 */ 2552 */
2461void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, 2553void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
2462 struct sk_security_struct *newssec) 2554 struct sk_security_struct *newssec)
2463{ 2555{
2556 /* We don't need to take newssec->nlbl_lock because we are the only
2557 * thread with access to newssec, but we do need to take the RCU read
2558 * lock as other threads could have access to ssec */
2559 rcu_read_lock();
2560 selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
2464 newssec->sclass = ssec->sclass; 2561 newssec->sclass = ssec->sclass;
2465 if (ssec->nlbl_state != NLBL_UNSET) 2562 rcu_read_unlock();
2466 newssec->nlbl_state = NLBL_REQUIRE;
2467 else
2468 newssec->nlbl_state = NLBL_UNSET;
2469} 2563}
2470 2564
2471/** 2565/**
2472 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 2566 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
2473 * @sock: the socket to label 2567 * @sock: the socket to label
2474 * @sock_family: the socket family
2475 * @sid: the SID to use
2476 * 2568 *
2477 * Description: 2569 * Description:
2478 * Attempt to label a socket using the NetLabel mechanism using the given 2570 * Attempt to label a socket using the NetLabel mechanism using the given
2479 * SID. Returns zero values on success, negative values on failure. 2571 * SID. Returns zero values on success, negative values on failure.
2480 * 2572 *
2481 */ 2573 */
2482int selinux_netlbl_socket_post_create(struct socket *sock, 2574int selinux_netlbl_socket_post_create(struct socket *sock)
2483 int sock_family,
2484 u32 sid)
2485{ 2575{
2576 int rc = 0;
2486 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; 2577 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2487 struct sk_security_struct *sksec = sock->sk->sk_security; 2578 struct sk_security_struct *sksec = sock->sk->sk_security;
2488 2579
2489 sksec->sclass = isec->sclass; 2580 sksec->sclass = isec->sclass;
2490 2581
2491 if (sock_family != PF_INET) 2582 rcu_read_lock();
2492 return 0; 2583 if (sksec->nlbl_state == NLBL_REQUIRE)
2584 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2585 rcu_read_unlock();
2493 2586
2494 sksec->nlbl_state = NLBL_REQUIRE; 2587 return rc;
2495 return selinux_netlbl_socket_setsid(sock, sid);
2496} 2588}
2497 2589
2498/** 2590/**
@@ -2514,11 +2606,16 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2514 2606
2515 sksec->sclass = isec->sclass; 2607 sksec->sclass = isec->sclass;
2516 2608
2517 if (sk->sk_family != PF_INET) 2609 rcu_read_lock();
2610
2611 if (sksec->nlbl_state != NLBL_REQUIRE) {
2612 rcu_read_unlock();
2518 return; 2613 return;
2614 }
2519 2615
2520 netlbl_secattr_init(&secattr); 2616 netlbl_secattr_init(&secattr);
2521 if (netlbl_sock_getattr(sk, &secattr) == 0 && 2617 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
2618 secattr.flags != NETLBL_SECATTR_NONE &&
2522 selinux_netlbl_secattr_to_sid(NULL, 2619 selinux_netlbl_secattr_to_sid(NULL,
2523 &secattr, 2620 &secattr,
2524 SECINITSID_UNLABELED, 2621 SECINITSID_UNLABELED,
@@ -2526,35 +2623,12 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2526 sksec->peer_sid = nlbl_peer_sid; 2623 sksec->peer_sid = nlbl_peer_sid;
2527 netlbl_secattr_destroy(&secattr); 2624 netlbl_secattr_destroy(&secattr);
2528 2625
2529 sksec->nlbl_state = NLBL_REQUIRE;
2530
2531 /* Try to set the NetLabel on the socket to save time later, if we fail 2626 /* Try to set the NetLabel on the socket to save time later, if we fail
2532 * here we will pick up the pieces in later calls to 2627 * here we will pick up the pieces in later calls to
2533 * selinux_netlbl_inode_permission(). */ 2628 * selinux_netlbl_inode_permission(). */
2534 selinux_netlbl_socket_setsid(sock, sksec->sid); 2629 selinux_netlbl_socket_setsid(sock, sksec->sid);
2535}
2536
2537/**
2538 * selinux_netlbl_inet_conn_request - Handle a new connection request
2539 * @skb: the packet
2540 * @sock_sid: the SID of the parent socket
2541 *
2542 * Description:
2543 * If present, use the security attributes of the packet in @skb and the
2544 * parent sock's SID to arrive at a SID for the new child sock. Returns the
2545 * SID of the connection or SECSID_NULL on failure.
2546 *
2547 */
2548u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2549{
2550 int rc;
2551 u32 peer_sid;
2552
2553 rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid);
2554 if (rc != 0)
2555 return SECSID_NULL;
2556 2630
2557 return peer_sid; 2631 rcu_read_unlock();
2558} 2632}
2559 2633
2560/** 2634/**
@@ -2572,25 +2646,24 @@ u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2572int selinux_netlbl_inode_permission(struct inode *inode, int mask) 2646int selinux_netlbl_inode_permission(struct inode *inode, int mask)
2573{ 2647{
2574 int rc; 2648 int rc;
2575 struct inode_security_struct *isec;
2576 struct sk_security_struct *sksec; 2649 struct sk_security_struct *sksec;
2577 struct socket *sock; 2650 struct socket *sock;
2578 2651
2579 if (!S_ISSOCK(inode->i_mode)) 2652 if (!S_ISSOCK(inode->i_mode) ||
2653 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
2580 return 0; 2654 return 0;
2581
2582 sock = SOCKET_I(inode); 2655 sock = SOCKET_I(inode);
2583 isec = inode->i_security;
2584 sksec = sock->sk->sk_security; 2656 sksec = sock->sk->sk_security;
2585 mutex_lock(&isec->lock); 2657
2586 if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && 2658 rcu_read_lock();
2587 (mask & (MAY_WRITE | MAY_APPEND)))) { 2659 if (sksec->nlbl_state != NLBL_REQUIRE) {
2588 lock_sock(sock->sk); 2660 rcu_read_unlock();
2589 rc = selinux_netlbl_socket_setsid(sock, sksec->sid); 2661 return 0;
2590 release_sock(sock->sk); 2662 }
2591 } else 2663 lock_sock(sock->sk);
2592 rc = 0; 2664 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2593 mutex_unlock(&isec->lock); 2665 release_sock(sock->sk);
2666 rcu_read_unlock();
2594 2667
2595 return rc; 2668 return rc;
2596} 2669}
@@ -2648,42 +2721,6 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2648} 2721}
2649 2722
2650/** 2723/**
2651 * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID
2652 * @sock: the socket
2653 *
2654 * Description:
2655 * Examine @sock to find the connected peer's SID. Returns the SID on success
2656 * or SECSID_NULL on error.
2657 *
2658 */
2659u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
2660{
2661 struct sk_security_struct *sksec = sock->sk->sk_security;
2662 return sksec->peer_sid;
2663}
2664
2665/**
2666 * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
2667 * @skb: the packet
2668 *
2669 * Description:
2670 * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on
2671 * success, SECSID_NULL on error.
2672 *
2673 */
2674u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
2675{
2676 int peer_sid;
2677
2678 if (selinux_netlbl_skbuff_getsid(skb,
2679 SECINITSID_UNLABELED,
2680 &peer_sid) != 0)
2681 return SECSID_NULL;
2682
2683 return peer_sid;
2684}
2685
2686/**
2687 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel 2724 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
2688 * @sock: the socket 2725 * @sock: the socket
2689 * @level: the socket level or protocol 2726 * @level: the socket level or protocol
@@ -2701,21 +2738,19 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
2701 int optname) 2738 int optname)
2702{ 2739{
2703 int rc = 0; 2740 int rc = 0;
2704 struct inode *inode = SOCK_INODE(sock);
2705 struct sk_security_struct *sksec = sock->sk->sk_security; 2741 struct sk_security_struct *sksec = sock->sk->sk_security;
2706 struct inode_security_struct *isec = inode->i_security;
2707 struct netlbl_lsm_secattr secattr; 2742 struct netlbl_lsm_secattr secattr;
2708 2743
2709 mutex_lock(&isec->lock); 2744 rcu_read_lock();
2710 if (level == IPPROTO_IP && optname == IP_OPTIONS && 2745 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
2711 sksec->nlbl_state == NLBL_LABELED) { 2746 sksec->nlbl_state == NLBL_LABELED) {
2712 netlbl_secattr_init(&secattr); 2747 netlbl_secattr_init(&secattr);
2713 rc = netlbl_socket_getattr(sock, &secattr); 2748 rc = netlbl_socket_getattr(sock, &secattr);
2714 if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld)) 2749 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
2715 rc = -EACCES; 2750 rc = -EACCES;
2716 netlbl_secattr_destroy(&secattr); 2751 netlbl_secattr_destroy(&secattr);
2717 } 2752 }
2718 mutex_unlock(&isec->lock); 2753 rcu_read_unlock();
2719 2754
2720 return rc; 2755 return rc;
2721} 2756}