aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smack_lsm.c
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2009-01-06 17:58:22 -0500
committerJames Morris <jmorris@namei.org>2009-01-06 17:58:22 -0500
commitac8cc0fa5395fe2278e305a4cbed48e90d88d878 (patch)
tree515f577bfddd054ee4373228be7c974dfb8133af /security/smack/smack_lsm.c
parent238c6d54830c624f34ac9cf123ac04aebfca5013 (diff)
parent3699c53c485bf0168e6500d0ed18bf931584dd7c (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r--security/smack/smack_lsm.c310
1 files changed, 255 insertions, 55 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 848212fd4845..0278bc083044 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1277,6 +1277,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
1277 1277
1278 ssp->smk_in = csp; 1278 ssp->smk_in = csp;
1279 ssp->smk_out = csp; 1279 ssp->smk_out = csp;
1280 ssp->smk_labeled = SMACK_CIPSO_SOCKET;
1280 ssp->smk_packet[0] = '\0'; 1281 ssp->smk_packet[0] = '\0';
1281 1282
1282 sk->sk_security = ssp; 1283 sk->sk_security = ssp;
@@ -1341,45 +1342,69 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1341 struct smack_cipso cipso; 1342 struct smack_cipso cipso;
1342 int rc; 1343 int rc;
1343 1344
1344 switch (smack_net_nltype) { 1345 nlsp->domain = smack;
1345 case NETLBL_NLTYPE_CIPSOV4: 1346 nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1346 nlsp->domain = smack;
1347 nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1348 1347
1349 rc = smack_to_cipso(smack, &cipso); 1348 rc = smack_to_cipso(smack, &cipso);
1350 if (rc == 0) { 1349 if (rc == 0) {
1351 nlsp->attr.mls.lvl = cipso.smk_level; 1350 nlsp->attr.mls.lvl = cipso.smk_level;
1352 smack_set_catset(cipso.smk_catset, nlsp); 1351 smack_set_catset(cipso.smk_catset, nlsp);
1353 } else { 1352 } else {
1354 nlsp->attr.mls.lvl = smack_cipso_direct; 1353 nlsp->attr.mls.lvl = smack_cipso_direct;
1355 smack_set_catset(smack, nlsp); 1354 smack_set_catset(smack, nlsp);
1356 }
1357 break;
1358 default:
1359 break;
1360 } 1355 }
1361} 1356}
1362 1357
1363/** 1358/**
1364 * smack_netlabel - Set the secattr on a socket 1359 * smack_netlabel - Set the secattr on a socket
1365 * @sk: the socket 1360 * @sk: the socket
1361 * @labeled: socket label scheme
1366 * 1362 *
1367 * Convert the outbound smack value (smk_out) to a 1363 * Convert the outbound smack value (smk_out) to a
1368 * secattr and attach it to the socket. 1364 * secattr and attach it to the socket.
1369 * 1365 *
1370 * Returns 0 on success or an error code 1366 * Returns 0 on success or an error code
1371 */ 1367 */
1372static int smack_netlabel(struct sock *sk) 1368static int smack_netlabel(struct sock *sk, int labeled)
1373{ 1369{
1374 struct socket_smack *ssp; 1370 struct socket_smack *ssp;
1375 struct netlbl_lsm_secattr secattr; 1371 struct netlbl_lsm_secattr secattr;
1376 int rc; 1372 int rc = 0;
1377 1373
1378 ssp = sk->sk_security; 1374 ssp = sk->sk_security;
1379 netlbl_secattr_init(&secattr); 1375 /*
1380 smack_to_secattr(ssp->smk_out, &secattr); 1376 * Usually the netlabel code will handle changing the
1381 rc = netlbl_sock_setattr(sk, &secattr); 1377 * packet labeling based on the label.
1382 netlbl_secattr_destroy(&secattr); 1378 * The case of a single label host is different, because
1379 * a single label host should never get a labeled packet
1380 * even though the label is usually associated with a packet
1381 * label.
1382 */
1383 local_bh_disable();
1384 bh_lock_sock_nested(sk);
1385
1386 if (ssp->smk_out == smack_net_ambient ||
1387 labeled == SMACK_UNLABELED_SOCKET)
1388 netlbl_sock_delattr(sk);
1389 else {
1390 netlbl_secattr_init(&secattr);
1391 smack_to_secattr(ssp->smk_out, &secattr);
1392 rc = netlbl_sock_setattr(sk, &secattr);
1393 netlbl_secattr_destroy(&secattr);
1394 }
1395
1396 bh_unlock_sock(sk);
1397 local_bh_enable();
1398 /*
1399 * Remember the label scheme used so that it is not
1400 * necessary to do the netlabel setting if it has not
1401 * changed the next time through.
1402 *
1403 * The -EDESTADDRREQ case is an indication that there's
1404 * a single level host involved.
1405 */
1406 if (rc == 0)
1407 ssp->smk_labeled = labeled;
1383 1408
1384 return rc; 1409 return rc;
1385} 1410}
@@ -1432,7 +1457,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1432 ssp->smk_in = sp; 1457 ssp->smk_in = sp;
1433 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { 1458 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
1434 ssp->smk_out = sp; 1459 ssp->smk_out = sp;
1435 rc = smack_netlabel(sock->sk); 1460 rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1436 if (rc != 0) 1461 if (rc != 0)
1437 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", 1462 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
1438 __func__, -rc); 1463 __func__, -rc);
@@ -1462,7 +1487,108 @@ static int smack_socket_post_create(struct socket *sock, int family,
1462 /* 1487 /*
1463 * Set the outbound netlbl. 1488 * Set the outbound netlbl.
1464 */ 1489 */
1465 return smack_netlabel(sock->sk); 1490 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1491}
1492
1493
1494/**
1495 * smack_host_label - check host based restrictions
1496 * @sip: the object end
1497 *
1498 * looks for host based access restrictions
1499 *
1500 * This version will only be appropriate for really small
1501 * sets of single label hosts. Because of the masking
1502 * it cannot shortcut out on the first match. There are
1503 * numerious ways to address the problem, but none of them
1504 * have been applied here.
1505 *
1506 * Returns the label of the far end or NULL if it's not special.
1507 */
1508static char *smack_host_label(struct sockaddr_in *sip)
1509{
1510 struct smk_netlbladdr *snp;
1511 char *bestlabel = NULL;
1512 struct in_addr *siap = &sip->sin_addr;
1513 struct in_addr *liap;
1514 struct in_addr *miap;
1515 struct in_addr bestmask;
1516
1517 if (siap->s_addr == 0)
1518 return NULL;
1519
1520 bestmask.s_addr = 0;
1521
1522 for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
1523 liap = &snp->smk_host.sin_addr;
1524 miap = &snp->smk_mask;
1525 /*
1526 * If the addresses match after applying the list entry mask
1527 * the entry matches the address. If it doesn't move along to
1528 * the next entry.
1529 */
1530 if ((liap->s_addr & miap->s_addr) !=
1531 (siap->s_addr & miap->s_addr))
1532 continue;
1533 /*
1534 * If the list entry mask identifies a single address
1535 * it can't get any more specific.
1536 */
1537 if (miap->s_addr == 0xffffffff)
1538 return snp->smk_label;
1539 /*
1540 * If the list entry mask is less specific than the best
1541 * already found this entry is uninteresting.
1542 */
1543 if ((miap->s_addr | bestmask.s_addr) == bestmask.s_addr)
1544 continue;
1545 /*
1546 * This is better than any entry found so far.
1547 */
1548 bestmask.s_addr = miap->s_addr;
1549 bestlabel = snp->smk_label;
1550 }
1551
1552 return bestlabel;
1553}
1554
1555/**
1556 * smack_socket_connect - connect access check
1557 * @sock: the socket
1558 * @sap: the other end
1559 * @addrlen: size of sap
1560 *
1561 * Verifies that a connection may be possible
1562 *
1563 * Returns 0 on success, and error code otherwise
1564 */
1565static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
1566 int addrlen)
1567{
1568 struct socket_smack *ssp = sock->sk->sk_security;
1569 char *hostsp;
1570 int rc;
1571
1572 if (sock->sk == NULL || sock->sk->sk_family != PF_INET)
1573 return 0;
1574
1575 if (addrlen < sizeof(struct sockaddr_in))
1576 return -EINVAL;
1577
1578 hostsp = smack_host_label((struct sockaddr_in *)sap);
1579 if (hostsp == NULL) {
1580 if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
1581 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1582 return 0;
1583 }
1584
1585 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
1586 if (rc != 0)
1587 return rc;
1588
1589 if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
1590 return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
1591 return 0;
1466} 1592}
1467 1593
1468/** 1594/**
@@ -2101,8 +2227,14 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2101 if (newsmack == NULL) 2227 if (newsmack == NULL)
2102 return -EINVAL; 2228 return -EINVAL;
2103 2229
2230 /*
2231 * No process is ever allowed the web ("@") label.
2232 */
2233 if (newsmack == smack_known_web.smk_known)
2234 return -EPERM;
2235
2104 new = prepare_creds(); 2236 new = prepare_creds();
2105 if (!new) 2237 if (new == NULL)
2106 return -ENOMEM; 2238 return -ENOMEM;
2107 new->security = newsmack; 2239 new->security = newsmack;
2108 commit_creds(new); 2240 commit_creds(new);
@@ -2144,6 +2276,49 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
2144} 2276}
2145 2277
2146/** 2278/**
2279 * smack_socket_sendmsg - Smack check based on destination host
2280 * @sock: the socket
2281 * @msghdr: the message
2282 * @size: the size of the message
2283 *
2284 * Return 0 if the current subject can write to the destination
2285 * host. This is only a question if the destination is a single
2286 * label host.
2287 */
2288static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2289 int size)
2290{
2291 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
2292 struct socket_smack *ssp = sock->sk->sk_security;
2293 char *hostsp;
2294 int rc;
2295
2296 /*
2297 * Perfectly reasonable for this to be NULL
2298 */
2299 if (sip == NULL || sip->sin_family != PF_INET)
2300 return 0;
2301
2302 hostsp = smack_host_label(sip);
2303 if (hostsp == NULL) {
2304 if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
2305 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
2306 return 0;
2307 }
2308
2309 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
2310 if (rc != 0)
2311 return rc;
2312
2313 if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
2314 return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
2315
2316 return 0;
2317
2318}
2319
2320
2321/**
2147 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat 2322 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat
2148 * pair to smack 2323 * pair to smack
2149 * @sap: netlabel secattr 2324 * @sap: netlabel secattr
@@ -2154,44 +2329,66 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
2154static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) 2329static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
2155{ 2330{
2156 char smack[SMK_LABELLEN]; 2331 char smack[SMK_LABELLEN];
2332 char *sp;
2157 int pcat; 2333 int pcat;
2158 2334
2159 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) == 0) { 2335 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
2160 /* 2336 /*
2337 * Looks like a CIPSO packet.
2161 * If there are flags but no level netlabel isn't 2338 * If there are flags but no level netlabel isn't
2162 * behaving the way we expect it to. 2339 * behaving the way we expect it to.
2163 * 2340 *
2341 * Get the categories, if any
2164 * Without guidance regarding the smack value 2342 * Without guidance regarding the smack value
2165 * for the packet fall back on the network 2343 * for the packet fall back on the network
2166 * ambient value. 2344 * ambient value.
2167 */ 2345 */
2168 strncpy(sip, smack_net_ambient, SMK_MAXLEN); 2346 memset(smack, '\0', SMK_LABELLEN);
2347 if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
2348 for (pcat = -1;;) {
2349 pcat = netlbl_secattr_catmap_walk(
2350 sap->attr.mls.cat, pcat + 1);
2351 if (pcat < 0)
2352 break;
2353 smack_catset_bit(pcat, smack);
2354 }
2355 /*
2356 * If it is CIPSO using smack direct mapping
2357 * we are already done. WeeHee.
2358 */
2359 if (sap->attr.mls.lvl == smack_cipso_direct) {
2360 memcpy(sip, smack, SMK_MAXLEN);
2361 return;
2362 }
2363 /*
2364 * Look it up in the supplied table if it is not
2365 * a direct mapping.
2366 */
2367 smack_from_cipso(sap->attr.mls.lvl, smack, sip);
2169 return; 2368 return;
2170 } 2369 }
2171 /* 2370 if ((sap->flags & NETLBL_SECATTR_SECID) != 0) {
2172 * Get the categories, if any 2371 /*
2173 */ 2372 * Looks like a fallback, which gives us a secid.
2174 memset(smack, '\0', SMK_LABELLEN); 2373 */
2175 if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) 2374 sp = smack_from_secid(sap->attr.secid);
2176 for (pcat = -1;;) { 2375 /*
2177 pcat = netlbl_secattr_catmap_walk(sap->attr.mls.cat, 2376 * This has got to be a bug because it is
2178 pcat + 1); 2377 * impossible to specify a fallback without
2179 if (pcat < 0) 2378 * specifying the label, which will ensure
2180 break; 2379 * it has a secid, and the only way to get a
2181 smack_catset_bit(pcat, smack); 2380 * secid is from a fallback.
2182 } 2381 */
2183 /* 2382 BUG_ON(sp == NULL);
2184 * If it is CIPSO using smack direct mapping 2383 strncpy(sip, sp, SMK_MAXLEN);
2185 * we are already done. WeeHee.
2186 */
2187 if (sap->attr.mls.lvl == smack_cipso_direct) {
2188 memcpy(sip, smack, SMK_MAXLEN);
2189 return; 2384 return;
2190 } 2385 }
2191 /* 2386 /*
2192 * Look it up in the supplied table if it is not a direct mapping. 2387 * Without guidance regarding the smack value
2388 * for the packet fall back on the network
2389 * ambient value.
2193 */ 2390 */
2194 smack_from_cipso(sap->attr.mls.lvl, smack, sip); 2391 strncpy(sip, smack_net_ambient, SMK_MAXLEN);
2195 return; 2392 return;
2196} 2393}
2197 2394
@@ -2207,6 +2404,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2207 struct netlbl_lsm_secattr secattr; 2404 struct netlbl_lsm_secattr secattr;
2208 struct socket_smack *ssp = sk->sk_security; 2405 struct socket_smack *ssp = sk->sk_security;
2209 char smack[SMK_LABELLEN]; 2406 char smack[SMK_LABELLEN];
2407 char *csp;
2210 int rc; 2408 int rc;
2211 2409
2212 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) 2410 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
@@ -2215,21 +2413,24 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2215 /* 2413 /*
2216 * Translate what netlabel gave us. 2414 * Translate what netlabel gave us.
2217 */ 2415 */
2218 memset(smack, '\0', SMK_LABELLEN);
2219 netlbl_secattr_init(&secattr); 2416 netlbl_secattr_init(&secattr);
2417
2220 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); 2418 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
2221 if (rc == 0) 2419 if (rc == 0) {
2222 smack_from_secattr(&secattr, smack); 2420 smack_from_secattr(&secattr, smack);
2223 else 2421 csp = smack;
2224 strncpy(smack, smack_net_ambient, SMK_MAXLEN); 2422 } else
2423 csp = smack_net_ambient;
2424
2225 netlbl_secattr_destroy(&secattr); 2425 netlbl_secattr_destroy(&secattr);
2426
2226 /* 2427 /*
2227 * Receiving a packet requires that the other end 2428 * Receiving a packet requires that the other end
2228 * be able to write here. Read access is not required. 2429 * be able to write here. Read access is not required.
2229 * This is the simplist possible security model 2430 * This is the simplist possible security model
2230 * for networking. 2431 * for networking.
2231 */ 2432 */
2232 rc = smk_access(smack, ssp->smk_in, MAY_WRITE); 2433 rc = smk_access(csp, ssp->smk_in, MAY_WRITE);
2233 if (rc != 0) 2434 if (rc != 0)
2234 netlbl_skbuff_err(skb, rc, 0); 2435 netlbl_skbuff_err(skb, rc, 0);
2235 return rc; 2436 return rc;
@@ -2298,7 +2499,6 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
2298 /* 2499 /*
2299 * Translate what netlabel gave us. 2500 * Translate what netlabel gave us.
2300 */ 2501 */
2301 memset(smack, '\0', SMK_LABELLEN);
2302 netlbl_secattr_init(&secattr); 2502 netlbl_secattr_init(&secattr);
2303 rc = netlbl_skbuff_getattr(skb, family, &secattr); 2503 rc = netlbl_skbuff_getattr(skb, family, &secattr);
2304 if (rc == 0) 2504 if (rc == 0)
@@ -2341,7 +2541,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
2341 ssp->smk_in = ssp->smk_out = current_security(); 2541 ssp->smk_in = ssp->smk_out = current_security();
2342 ssp->smk_packet[0] = '\0'; 2542 ssp->smk_packet[0] = '\0';
2343 2543
2344 rc = smack_netlabel(sk); 2544 rc = smack_netlabel(sk, SMACK_CIPSO_SOCKET);
2345 if (rc != 0) 2545 if (rc != 0)
2346 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", 2546 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
2347 __func__, -rc); 2547 __func__, -rc);
@@ -2367,7 +2567,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
2367 if (skb == NULL) 2567 if (skb == NULL)
2368 return -EACCES; 2568 return -EACCES;
2369 2569
2370 memset(smack, '\0', SMK_LABELLEN);
2371 netlbl_secattr_init(&skb_secattr); 2570 netlbl_secattr_init(&skb_secattr);
2372 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr); 2571 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr);
2373 if (rc == 0) 2572 if (rc == 0)
@@ -2732,6 +2931,8 @@ struct security_operations smack_ops = {
2732 .unix_may_send = smack_unix_may_send, 2931 .unix_may_send = smack_unix_may_send,
2733 2932
2734 .socket_post_create = smack_socket_post_create, 2933 .socket_post_create = smack_socket_post_create,
2934 .socket_connect = smack_socket_connect,
2935 .socket_sendmsg = smack_socket_sendmsg,
2735 .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, 2936 .socket_sock_rcv_skb = smack_socket_sock_rcv_skb,
2736 .socket_getpeersec_stream = smack_socket_getpeersec_stream, 2937 .socket_getpeersec_stream = smack_socket_getpeersec_stream,
2737 .socket_getpeersec_dgram = smack_socket_getpeersec_dgram, 2938 .socket_getpeersec_dgram = smack_socket_getpeersec_dgram,
@@ -2783,7 +2984,6 @@ static __init int smack_init(void)
2783 /* 2984 /*
2784 * Initialize locks 2985 * Initialize locks
2785 */ 2986 */
2786 spin_lock_init(&smack_known_unset.smk_cipsolock);
2787 spin_lock_init(&smack_known_huh.smk_cipsolock); 2987 spin_lock_init(&smack_known_huh.smk_cipsolock);
2788 spin_lock_init(&smack_known_hat.smk_cipsolock); 2988 spin_lock_init(&smack_known_hat.smk_cipsolock);
2789 spin_lock_init(&smack_known_star.smk_cipsolock); 2989 spin_lock_init(&smack_known_star.smk_cipsolock);