aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2008-12-31 12:54:12 -0500
committerPaul Moore <paul.moore@hp.com>2008-12-31 12:54:12 -0500
commit6d3dc07cbb1e88deed2e8710e215f232a56b1dce (patch)
tree4c294d1ddac8c9f417bcd406771993aa58106f6d
parent277d342fc423fca5e66e677fe629d1b2f8f1b9e2 (diff)
smack: Add support for unlabeled network hosts and networks
Add support for unlabeled network hosts and networks. Relies heavily on Paul Moore's netlabel support. Creates a new entry in /smack called netlabel. Writes to /smack/netlabel take the form: A.B.C.D LABEL or A.B.C.D/N LABEL where A.B.C.D is a network address, N is an integer between 0-32, and LABEL is the Smack label to be used. If /N is omitted /32 is assumed. N designates the netmask for the address. Entries are matched by the most specific address/mask pair. 0.0.0.0/0 will match everything, while 192.168.1.117/32 will match exactly one host. A new system label "@", pronounced "web", is defined. Processes can not be assigned the web label. An address assigned the web label can be written to by any process, and packets coming from a web address can be written to any socket. Use of the web label is a violation of any strict MAC policy, but the web label has been requested many times. The nltype entry has been removed from /smack. It did not work right and the netlabel interface can be used to specify that all hosts be treated as unlabeled. CIPSO labels on incoming packets will be honored, even from designated single label hosts. Single label hosts can only be written to by processes with labels that can write to the label of the host. Packets sent to single label hosts will always be unlabeled. Once added a single label designation cannot be removed, however the label may be changed. The behavior of the ambient label remains unchanged. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Signed-off-by: Paul Moore <paul.moore@hp.com>
-rw-r--r--security/smack/smack.h31
-rw-r--r--security/smack/smack_access.c28
-rw-r--r--security/smack/smack_lsm.c310
-rw-r--r--security/smack/smackfs.c364
4 files changed, 538 insertions, 195 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 31dce559595a..b79582e4fbfd 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -16,6 +16,7 @@
16#include <linux/capability.h> 16#include <linux/capability.h>
17#include <linux/spinlock.h> 17#include <linux/spinlock.h>
18#include <linux/security.h> 18#include <linux/security.h>
19#include <linux/in.h>
19#include <net/netlabel.h> 20#include <net/netlabel.h>
20 21
21/* 22/*
@@ -39,6 +40,7 @@ struct superblock_smack {
39struct socket_smack { 40struct socket_smack {
40 char *smk_out; /* outbound label */ 41 char *smk_out; /* outbound label */
41 char *smk_in; /* inbound label */ 42 char *smk_in; /* inbound label */
43 int smk_labeled; /* label scheme */
42 char smk_packet[SMK_LABELLEN]; /* TCP peer label */ 44 char smk_packet[SMK_LABELLEN]; /* TCP peer label */
43}; 45};
44 46
@@ -80,6 +82,16 @@ struct smack_cipso {
80}; 82};
81 83
82/* 84/*
85 * An entry in the table identifying hosts.
86 */
87struct smk_netlbladdr {
88 struct smk_netlbladdr *smk_next;
89 struct sockaddr_in smk_host; /* network address */
90 struct in_addr smk_mask; /* network mask */
91 char *smk_label; /* label */
92};
93
94/*
83 * This is the repository for labels seen so that it is 95 * This is the repository for labels seen so that it is
84 * not necessary to keep allocating tiny chuncks of memory 96 * not necessary to keep allocating tiny chuncks of memory
85 * and so that they can be shared. 97 * and so that they can be shared.
@@ -127,6 +139,20 @@ struct smack_known {
127#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT 139#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
128 140
129/* 141/*
142 * How communications on this socket are treated.
143 * Usually it's determined by the underlying netlabel code
144 * but there are certain cases, including single label hosts
145 * and potentially single label interfaces for which the
146 * treatment can not be known in advance.
147 *
148 * The possibility of additional labeling schemes being
149 * introduced in the future exists as well.
150 */
151#define SMACK_UNLABELED_SOCKET 0
152#define SMACK_CIPSO_SOCKET 1
153
154/*
155 * smackfs magic number
130 * smackfs macic number 156 * smackfs macic number
131 */ 157 */
132#define SMACK_MAGIC 0x43415d53 /* "SMAC" */ 158#define SMACK_MAGIC 0x43415d53 /* "SMAC" */
@@ -141,6 +167,7 @@ struct smack_known {
141 * CIPSO defaults. 167 * CIPSO defaults.
142 */ 168 */
143#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ 169#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
170#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */
144#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ 171#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */
145#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ 172#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */
146#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ 173#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
@@ -176,7 +203,6 @@ u32 smack_to_secid(const char *);
176 * Shared data. 203 * Shared data.
177 */ 204 */
178extern int smack_cipso_direct; 205extern int smack_cipso_direct;
179extern int smack_net_nltype;
180extern char *smack_net_ambient; 206extern char *smack_net_ambient;
181extern char *smack_onlycap; 207extern char *smack_onlycap;
182 208
@@ -186,9 +212,10 @@ extern struct smack_known smack_known_hat;
186extern struct smack_known smack_known_huh; 212extern struct smack_known smack_known_huh;
187extern struct smack_known smack_known_invalid; 213extern struct smack_known smack_known_invalid;
188extern struct smack_known smack_known_star; 214extern struct smack_known smack_known_star;
189extern struct smack_known smack_known_unset; 215extern struct smack_known smack_known_web;
190 216
191extern struct smk_list_entry *smack_list; 217extern struct smk_list_entry *smack_list;
218extern struct smk_netlbladdr *smack_netlbladdrs;
192extern struct security_operations smack_ops; 219extern struct security_operations smack_ops;
193 220
194/* 221/*
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 247cec3b5a43..2e0b83e77ffe 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -15,15 +15,8 @@
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include "smack.h" 16#include "smack.h"
17 17
18struct smack_known smack_known_unset = {
19 .smk_next = NULL,
20 .smk_known = "UNSET",
21 .smk_secid = 1,
22 .smk_cipso = NULL,
23};
24
25struct smack_known smack_known_huh = { 18struct smack_known smack_known_huh = {
26 .smk_next = &smack_known_unset, 19 .smk_next = NULL,
27 .smk_known = "?", 20 .smk_known = "?",
28 .smk_secid = 2, 21 .smk_secid = 2,
29 .smk_cipso = NULL, 22 .smk_cipso = NULL,
@@ -57,7 +50,14 @@ struct smack_known smack_known_invalid = {
57 .smk_cipso = NULL, 50 .smk_cipso = NULL,
58}; 51};
59 52
60struct smack_known *smack_known = &smack_known_invalid; 53struct smack_known smack_known_web = {
54 .smk_next = &smack_known_invalid,
55 .smk_known = "@",
56 .smk_secid = 7,
57 .smk_cipso = NULL,
58};
59
60struct smack_known *smack_known = &smack_known_web;
61 61
62/* 62/*
63 * The initial value needs to be bigger than any of the 63 * The initial value needs to be bigger than any of the
@@ -99,6 +99,16 @@ int smk_access(char *subject_label, char *object_label, int request)
99 strcmp(subject_label, smack_known_star.smk_known) == 0) 99 strcmp(subject_label, smack_known_star.smk_known) == 0)
100 return -EACCES; 100 return -EACCES;
101 /* 101 /*
102 * An internet object can be accessed by any subject.
103 * Tasks cannot be assigned the internet label.
104 * An internet subject can access any object.
105 */
106 if (object_label == smack_known_web.smk_known ||
107 subject_label == smack_known_web.smk_known ||
108 strcmp(object_label, smack_known_web.smk_known) == 0 ||
109 strcmp(subject_label, smack_known_web.smk_known) == 0)
110 return 0;
111 /*
102 * A star object can be accessed by any subject. 112 * A star object can be accessed by any subject.
103 */ 113 */
104 if (object_label == smack_known_star.smk_known || 114 if (object_label == smack_known_star.smk_known ||
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1b5551dfc1f7..6bfaba6177c2 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);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 594e934f1385..bf107a389ac1 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -20,6 +20,7 @@
20#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
21#include <linux/security.h> 21#include <linux/security.h>
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <net/net_namespace.h>
23#include <net/netlabel.h> 24#include <net/netlabel.h>
24#include <net/cipso_ipv4.h> 25#include <net/cipso_ipv4.h>
25#include <linux/seq_file.h> 26#include <linux/seq_file.h>
@@ -38,7 +39,7 @@ enum smk_inos {
38 SMK_DOI = 5, /* CIPSO DOI */ 39 SMK_DOI = 5, /* CIPSO DOI */
39 SMK_DIRECT = 6, /* CIPSO level indicating direct label */ 40 SMK_DIRECT = 6, /* CIPSO level indicating direct label */
40 SMK_AMBIENT = 7, /* internet ambient label */ 41 SMK_AMBIENT = 7, /* internet ambient label */
41 SMK_NLTYPE = 8, /* label scheme to use by default */ 42 SMK_NETLBLADDR = 8, /* single label hosts */
42 SMK_ONLYCAP = 9, /* the only "capable" label */ 43 SMK_ONLYCAP = 9, /* the only "capable" label */
43}; 44};
44 45
@@ -48,6 +49,7 @@ enum smk_inos {
48static DEFINE_MUTEX(smack_list_lock); 49static DEFINE_MUTEX(smack_list_lock);
49static DEFINE_MUTEX(smack_cipso_lock); 50static DEFINE_MUTEX(smack_cipso_lock);
50static DEFINE_MUTEX(smack_ambient_lock); 51static DEFINE_MUTEX(smack_ambient_lock);
52static DEFINE_MUTEX(smk_netlbladdr_lock);
51 53
52/* 54/*
53 * This is the "ambient" label for network traffic. 55 * This is the "ambient" label for network traffic.
@@ -57,12 +59,6 @@ static DEFINE_MUTEX(smack_ambient_lock);
57char *smack_net_ambient = smack_known_floor.smk_known; 59char *smack_net_ambient = smack_known_floor.smk_known;
58 60
59/* 61/*
60 * This is the default packet marking scheme for network traffic.
61 * It can be reset via smackfs/nltype
62 */
63int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;
64
65/*
66 * This is the level in a CIPSO header that indicates a 62 * This is the level in a CIPSO header that indicates a
67 * smack label is contained directly in the category set. 63 * smack label is contained directly in the category set.
68 * It can be reset via smackfs/direct 64 * It can be reset via smackfs/direct
@@ -79,6 +75,13 @@ int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
79 */ 75 */
80char *smack_onlycap; 76char *smack_onlycap;
81 77
78/*
79 * Certain IP addresses may be designated as single label hosts.
80 * Packets are sent there unlabeled, but only from tasks that
81 * can write to the specified label.
82 */
83struct smk_netlbladdr *smack_netlbladdrs;
84
82static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 85static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
83struct smk_list_entry *smack_list; 86struct smk_list_entry *smack_list;
84 87
@@ -104,6 +107,24 @@ struct smk_list_entry *smack_list;
104#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) 107#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
105#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) 108#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
106 109
110/**
111 * smk_netlabel_audit_set - fill a netlbl_audit struct
112 * @nap: structure to fill
113 */
114static void smk_netlabel_audit_set(struct netlbl_audit *nap)
115{
116 nap->loginuid = audit_get_loginuid(current);
117 nap->sessionid = audit_get_sessionid(current);
118 nap->secid = smack_to_secid(current_security());
119}
120
121/*
122 * Values for parsing single label host rules
123 * "1.2.3.4 X"
124 * "192.168.138.129/32 abcdefghijklmnopqrstuvw"
125 */
126#define SMK_NETLBLADDRMIN 9
127#define SMK_NETLBLADDRMAX 42
107 128
108/* 129/*
109 * Seq_file read operations for /smack/load 130 * Seq_file read operations for /smack/load
@@ -344,13 +365,11 @@ static void smk_cipso_doi(void)
344{ 365{
345 int rc; 366 int rc;
346 struct cipso_v4_doi *doip; 367 struct cipso_v4_doi *doip;
347 struct netlbl_audit audit_info; 368 struct netlbl_audit nai;
348 369
349 audit_info.loginuid = audit_get_loginuid(current); 370 smk_netlabel_audit_set(&nai);
350 audit_info.sessionid = audit_get_sessionid(current);
351 audit_info.secid = smack_to_secid(current_security());
352 371
353 rc = netlbl_cfg_map_del(NULL, PF_UNSPEC, NULL, NULL, &audit_info); 372 rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
354 if (rc != 0) 373 if (rc != 0)
355 printk(KERN_WARNING "%s:%d remove rc = %d\n", 374 printk(KERN_WARNING "%s:%d remove rc = %d\n",
356 __func__, __LINE__, rc); 375 __func__, __LINE__, rc);
@@ -365,15 +384,14 @@ static void smk_cipso_doi(void)
365 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++) 384 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
366 doip->tags[rc] = CIPSO_V4_TAG_INVALID; 385 doip->tags[rc] = CIPSO_V4_TAG_INVALID;
367 386
368 rc = netlbl_cfg_cipsov4_add(doip, &audit_info); 387 rc = netlbl_cfg_cipsov4_add(doip, &nai);
369 if (rc != 0) { 388 if (rc != 0) {
370 printk(KERN_WARNING "%s:%d cipso add rc = %d\n", 389 printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
371 __func__, __LINE__, rc); 390 __func__, __LINE__, rc);
372 kfree(doip); 391 kfree(doip);
373 return; 392 return;
374 } 393 }
375 rc = netlbl_cfg_cipsov4_map_add(doip->doi, 394 rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
376 NULL, NULL, NULL, &audit_info);
377 if (rc != 0) { 395 if (rc != 0) {
378 printk(KERN_WARNING "%s:%d map add rc = %d\n", 396 printk(KERN_WARNING "%s:%d map add rc = %d\n",
379 __func__, __LINE__, rc); 397 __func__, __LINE__, rc);
@@ -388,22 +406,19 @@ static void smk_cipso_doi(void)
388static void smk_unlbl_ambient(char *oldambient) 406static void smk_unlbl_ambient(char *oldambient)
389{ 407{
390 int rc; 408 int rc;
391 struct netlbl_audit audit_info; 409 struct netlbl_audit nai;
392 410
393 audit_info.loginuid = audit_get_loginuid(current); 411 smk_netlabel_audit_set(&nai);
394 audit_info.sessionid = audit_get_sessionid(current);
395 audit_info.secid = smack_to_secid(current_security());
396 412
397 if (oldambient != NULL) { 413 if (oldambient != NULL) {
398 rc = netlbl_cfg_map_del(oldambient, 414 rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
399 PF_UNSPEC, NULL, NULL, &audit_info);
400 if (rc != 0) 415 if (rc != 0)
401 printk(KERN_WARNING "%s:%d remove rc = %d\n", 416 printk(KERN_WARNING "%s:%d remove rc = %d\n",
402 __func__, __LINE__, rc); 417 __func__, __LINE__, rc);
403 } 418 }
404 419
405 rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, 420 rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
406 PF_INET, NULL, NULL, &audit_info); 421 NULL, NULL, &nai);
407 if (rc != 0) 422 if (rc != 0)
408 printk(KERN_WARNING "%s:%d add rc = %d\n", 423 printk(KERN_WARNING "%s:%d add rc = %d\n",
409 __func__, __LINE__, rc); 424 __func__, __LINE__, rc);
@@ -614,6 +629,201 @@ static const struct file_operations smk_cipso_ops = {
614 .release = seq_release, 629 .release = seq_release,
615}; 630};
616 631
632/*
633 * Seq_file read operations for /smack/netlabel
634 */
635
636static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
637{
638 if (*pos == SEQ_READ_FINISHED)
639 return NULL;
640
641 return smack_netlbladdrs;
642}
643
644static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
645{
646 struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next;
647
648 if (skp == NULL)
649 *pos = SEQ_READ_FINISHED;
650
651 return skp;
652}
653/*
654#define BEMASK 0x80000000
655*/
656#define BEMASK 0x00000001
657#define BEBITS (sizeof(__be32) * 8)
658
659/*
660 * Print host/label pairs
661 */
662static int netlbladdr_seq_show(struct seq_file *s, void *v)
663{
664 struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
665 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
666 __be32 bebits;
667 int maskn = 0;
668
669 for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1)
670 if ((skp->smk_mask.s_addr & bebits) == 0)
671 break;
672
673 seq_printf(s, "%u.%u.%u.%u/%d %s\n",
674 hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
675
676 return 0;
677}
678
679static void netlbladdr_seq_stop(struct seq_file *s, void *v)
680{
681 /* No-op */
682}
683
684static struct seq_operations netlbladdr_seq_ops = {
685 .start = netlbladdr_seq_start,
686 .stop = netlbladdr_seq_stop,
687 .next = netlbladdr_seq_next,
688 .show = netlbladdr_seq_show,
689};
690
691/**
692 * smk_open_netlbladdr - open() for /smack/netlabel
693 * @inode: inode structure representing file
694 * @file: "netlabel" file pointer
695 *
696 * Connect our netlbladdr_seq_* operations with /smack/netlabel
697 * file_operations
698 */
699static int smk_open_netlbladdr(struct inode *inode, struct file *file)
700{
701 return seq_open(file, &netlbladdr_seq_ops);
702}
703
704/**
705 * smk_write_netlbladdr - write() for /smack/netlabel
706 * @filp: file pointer, not actually used
707 * @buf: where to get the data from
708 * @count: bytes sent
709 * @ppos: where to start
710 *
711 * Accepts only one netlbladdr per write call.
712 * Returns number of bytes written or error code, as appropriate
713 */
714static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
715 size_t count, loff_t *ppos)
716{
717 struct smk_netlbladdr *skp;
718 struct sockaddr_in newname;
719 char smack[SMK_LABELLEN];
720 char *sp;
721 char data[SMK_NETLBLADDRMAX];
722 char *host = (char *)&newname.sin_addr.s_addr;
723 int rc;
724 struct netlbl_audit audit_info;
725 struct in_addr mask;
726 unsigned int m;
727 __be32 bebits = BEMASK;
728 __be32 nsa;
729
730 /*
731 * Must have privilege.
732 * No partial writes.
733 * Enough data must be present.
734 * "<addr/mask, as a.b.c.d/e><space><label>"
735 * "<addr, as a.b.c.d><space><label>"
736 */
737 if (!capable(CAP_MAC_ADMIN))
738 return -EPERM;
739 if (*ppos != 0)
740 return -EINVAL;
741 if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX)
742 return -EINVAL;
743 if (copy_from_user(data, buf, count) != 0)
744 return -EFAULT;
745
746 data[count] = '\0';
747
748 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",
749 &host[0], &host[1], &host[2], &host[3], &m, smack);
750 if (rc != 6) {
751 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
752 &host[0], &host[1], &host[2], &host[3], smack);
753 if (rc != 5)
754 return -EINVAL;
755 m = BEBITS;
756 }
757 if (m > BEBITS)
758 return -EINVAL;
759
760 sp = smk_import(smack, 0);
761 if (sp == NULL)
762 return -EINVAL;
763
764 for (mask.s_addr = 0; m > 0; m--) {
765 mask.s_addr |= bebits;
766 bebits <<= 1;
767 }
768 /*
769 * Only allow one writer at a time. Writes should be
770 * quite rare and small in any case.
771 */
772 mutex_lock(&smk_netlbladdr_lock);
773
774 nsa = newname.sin_addr.s_addr;
775 for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
776 if (skp->smk_host.sin_addr.s_addr == nsa &&
777 skp->smk_mask.s_addr == mask.s_addr)
778 break;
779
780 smk_netlabel_audit_set(&audit_info);
781
782 if (skp == NULL) {
783 skp = kzalloc(sizeof(*skp), GFP_KERNEL);
784 if (skp == NULL)
785 rc = -ENOMEM;
786 else {
787 rc = 0;
788 skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
789 skp->smk_mask.s_addr = mask.s_addr;
790 skp->smk_next = smack_netlbladdrs;
791 skp->smk_label = sp;
792 smack_netlbladdrs = skp;
793 }
794 } else {
795 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
796 &skp->smk_host.sin_addr, &skp->smk_mask,
797 PF_INET, &audit_info);
798 skp->smk_label = sp;
799 }
800
801 /*
802 * Now tell netlabel about the single label nature of
803 * this host so that incoming packets get labeled.
804 */
805
806 if (rc == 0)
807 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
808 &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
809 smack_to_secid(skp->smk_label), &audit_info);
810
811 if (rc == 0)
812 rc = count;
813
814 mutex_unlock(&smk_netlbladdr_lock);
815
816 return rc;
817}
818
819static const struct file_operations smk_netlbladdr_ops = {
820 .open = smk_open_netlbladdr,
821 .read = seq_read,
822 .llseek = seq_lseek,
823 .write = smk_write_netlbladdr,
824 .release = seq_release,
825};
826
617/** 827/**
618 * smk_read_doi - read() for /smack/doi 828 * smk_read_doi - read() for /smack/doi
619 * @filp: file pointer, not actually used 829 * @filp: file pointer, not actually used
@@ -902,110 +1112,6 @@ static const struct file_operations smk_onlycap_ops = {
902 .write = smk_write_onlycap, 1112 .write = smk_write_onlycap,
903}; 1113};
904 1114
905struct option_names {
906 int o_number;
907 char *o_name;
908 char *o_alias;
909};
910
911static struct option_names netlbl_choices[] = {
912 { NETLBL_NLTYPE_RIPSO,
913 NETLBL_NLTYPE_RIPSO_NAME, "ripso" },
914 { NETLBL_NLTYPE_CIPSOV4,
915 NETLBL_NLTYPE_CIPSOV4_NAME, "cipsov4" },
916 { NETLBL_NLTYPE_CIPSOV4,
917 NETLBL_NLTYPE_CIPSOV4_NAME, "cipso" },
918 { NETLBL_NLTYPE_CIPSOV6,
919 NETLBL_NLTYPE_CIPSOV6_NAME, "cipsov6" },
920 { NETLBL_NLTYPE_UNLABELED,
921 NETLBL_NLTYPE_UNLABELED_NAME, "unlabeled" },
922};
923
924/**
925 * smk_read_nltype - read() for /smack/nltype
926 * @filp: file pointer, not actually used
927 * @buf: where to put the result
928 * @count: maximum to send along
929 * @ppos: where to start
930 *
931 * Returns number of bytes read or error code, as appropriate
932 */
933static ssize_t smk_read_nltype(struct file *filp, char __user *buf,
934 size_t count, loff_t *ppos)
935{
936 char bound[40];
937 ssize_t rc;
938 int i;
939
940 if (count < SMK_LABELLEN)
941 return -EINVAL;
942
943 if (*ppos != 0)
944 return 0;
945
946 sprintf(bound, "unknown");
947
948 for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
949 if (smack_net_nltype == netlbl_choices[i].o_number) {
950 sprintf(bound, "%s", netlbl_choices[i].o_name);
951 break;
952 }
953
954 rc = simple_read_from_buffer(buf, count, ppos, bound, strlen(bound));
955
956 return rc;
957}
958
959/**
960 * smk_write_nltype - write() for /smack/nltype
961 * @filp: file pointer, not actually used
962 * @buf: where to get the data from
963 * @count: bytes sent
964 * @ppos: where to start
965 *
966 * Returns number of bytes written or error code, as appropriate
967 */
968static ssize_t smk_write_nltype(struct file *file, const char __user *buf,
969 size_t count, loff_t *ppos)
970{
971 char bound[40];
972 char *cp;
973 int i;
974
975 if (!capable(CAP_MAC_ADMIN))
976 return -EPERM;
977
978 if (count >= 40)
979 return -EINVAL;
980
981 if (copy_from_user(bound, buf, count) != 0)
982 return -EFAULT;
983
984 bound[count] = '\0';
985 cp = strchr(bound, ' ');
986 if (cp != NULL)
987 *cp = '\0';
988 cp = strchr(bound, '\n');
989 if (cp != NULL)
990 *cp = '\0';
991
992 for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
993 if (strcmp(bound, netlbl_choices[i].o_name) == 0 ||
994 strcmp(bound, netlbl_choices[i].o_alias) == 0) {
995 smack_net_nltype = netlbl_choices[i].o_number;
996 return count;
997 }
998 /*
999 * Not a valid choice.
1000 */
1001 return -EINVAL;
1002}
1003
1004static const struct file_operations smk_nltype_ops = {
1005 .read = smk_read_nltype,
1006 .write = smk_write_nltype,
1007};
1008
1009/** 1115/**
1010 * smk_fill_super - fill the /smackfs superblock 1116 * smk_fill_super - fill the /smackfs superblock
1011 * @sb: the empty superblock 1117 * @sb: the empty superblock
@@ -1032,8 +1138,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
1032 {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, 1138 {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
1033 [SMK_AMBIENT] = 1139 [SMK_AMBIENT] =
1034 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, 1140 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
1035 [SMK_NLTYPE] = 1141 [SMK_NETLBLADDR] =
1036 {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, 1142 {"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
1037 [SMK_ONLYCAP] = 1143 [SMK_ONLYCAP] =
1038 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, 1144 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
1039 /* last one */ {""} 1145 /* last one */ {""}