aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2012-05-06 18:22:02 -0400
committerCasey Schaufler <cschaufler@vaio-ubuntu.(none)>2012-05-15 01:48:38 -0400
commitf7112e6c9abf1c70f001dcf097c1d6e218a93f5c (patch)
tree8ddcab31388e3f220f3ef911f4ec9dce8ac4be92 /security/smack
parentceffec5541cc22486d3ff492e3d76a33a68fbfa3 (diff)
Smack: allow for significantly longer Smack labels v4
V4 updated to current linux-security#next Targeted for git://gitorious.org/smack-next/kernel.git Modern application runtime environments like to use naming schemes that are structured and generated without human intervention. Even though the Smack limit of 23 characters for a label name is perfectly rational for human use there have been complaints that the limit is a problem in environments where names are composed from a set or sources, including vendor, author, distribution channel and application name. Names like softwarehouse-pgwodehouse-coolappstore-mellowmuskrats are becoming harder to avoid. This patch introduces long label support in Smack. Labels are now limited to 255 characters instead of the old 23. The primary reason for limiting the labels to 23 characters was so they could be directly contained in CIPSO category sets. This is still done were possible, but for labels that are too large a mapping is required. This is perfectly safe for communication that stays "on the box" and doesn't require much coordination between boxes beyond what would have been required to keep label names consistent. The bulk of this patch is in smackfs, adding and updating administrative interfaces. Because existing APIs can't be changed new ones that do much the same things as old ones have been introduced. The Smack specific CIPSO data representation has been removed and replaced with the data format used by netlabel. The CIPSO header is now computed when a label is imported rather than on use. This results in improved IP performance. The smack label is now allocated separately from the containing structure, allowing for larger strings. Four new /smack interfaces have been introduced as four of the old interfaces strictly required labels be specified in fixed length arrays. The access interface is supplemented with the check interface: access "Subject Object rwxat" access2 "Subject Object rwaxt" The load interface is supplemented with the rules interface: load "Subject Object rwxat" load2 "Subject Object rwaxt" The load-self interface is supplemented with the self-rules interface: load-self "Subject Object rwxat" load-self2 "Subject Object rwaxt" The cipso interface is supplemented with the wire interface: cipso "Subject lvl cnt c1 c2 ..." cipso2 "Subject lvl cnt c1 c2 ..." The old interfaces are maintained for compatibility. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h56
-rw-r--r--security/smack/smack_access.c233
-rw-r--r--security/smack/smack_lsm.c185
-rw-r--r--security/smack/smackfs.c993
4 files changed, 941 insertions, 526 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index cf2594dfa93..5e031a2e4c3 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -23,13 +23,19 @@
23#include <linux/lsm_audit.h> 23#include <linux/lsm_audit.h>
24 24
25/* 25/*
26 * Smack labels were limited to 23 characters for a long time.
27 */
28#define SMK_LABELLEN 24
29#define SMK_LONGLABEL 256
30
31/*
32 * Maximum number of bytes for the levels in a CIPSO IP option.
26 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is 33 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
27 * bigger than can be used, and 24 is the next lower multiple 34 * bigger than can be used, and 24 is the next lower multiple
28 * of 8, and there are too many issues if there isn't space set 35 * of 8, and there are too many issues if there isn't space set
29 * aside for the terminating null byte. 36 * aside for the terminating null byte.
30 */ 37 */
31#define SMK_MAXLEN 23 38#define SMK_CIPSOLEN 24
32#define SMK_LABELLEN (SMK_MAXLEN+1)
33 39
34struct superblock_smack { 40struct superblock_smack {
35 char *smk_root; 41 char *smk_root;
@@ -79,15 +85,6 @@ struct smack_rule {
79}; 85};
80 86
81/* 87/*
82 * An entry in the table mapping smack values to
83 * CIPSO level/category-set values.
84 */
85struct smack_cipso {
86 int smk_level;
87 char smk_catset[SMK_LABELLEN];
88};
89
90/*
91 * An entry in the table identifying hosts. 88 * An entry in the table identifying hosts.
92 */ 89 */
93struct smk_netlbladdr { 90struct smk_netlbladdr {
@@ -114,22 +111,19 @@ struct smk_netlbladdr {
114 * interfaces don't. The secid should go away when all of 111 * interfaces don't. The secid should go away when all of
115 * these components have been repaired. 112 * these components have been repaired.
116 * 113 *
117 * If there is a cipso value associated with the label it 114 * The cipso value associated with the label gets stored here, too.
118 * gets stored here, too. This will most likely be rare as
119 * the cipso direct mapping in used internally.
120 * 115 *
121 * Keep the access rules for this subject label here so that 116 * Keep the access rules for this subject label here so that
122 * the entire set of rules does not need to be examined every 117 * the entire set of rules does not need to be examined every
123 * time. 118 * time.
124 */ 119 */
125struct smack_known { 120struct smack_known {
126 struct list_head list; 121 struct list_head list;
127 char smk_known[SMK_LABELLEN]; 122 char *smk_known;
128 u32 smk_secid; 123 u32 smk_secid;
129 struct smack_cipso *smk_cipso; 124 struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */
130 spinlock_t smk_cipsolock; /* for changing cipso map */ 125 struct list_head smk_rules; /* access rules */
131 struct list_head smk_rules; /* access rules */ 126 struct mutex smk_rules_lock; /* lock for rules */
132 struct mutex smk_rules_lock; /* lock for the rules */
133}; 127};
134 128
135/* 129/*
@@ -166,6 +160,7 @@ struct smack_known {
166#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ 160#define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
167#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ 161#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */
168#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ 162#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */
163#define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */
169#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ 164#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */
170#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ 165#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
171#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ 166#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */
@@ -216,10 +211,9 @@ struct inode_smack *new_inode_smack(char *);
216int smk_access_entry(char *, char *, struct list_head *); 211int smk_access_entry(char *, char *, struct list_head *);
217int smk_access(char *, char *, int, struct smk_audit_info *); 212int smk_access(char *, char *, int, struct smk_audit_info *);
218int smk_curacc(char *, u32, struct smk_audit_info *); 213int smk_curacc(char *, u32, struct smk_audit_info *);
219int smack_to_cipso(const char *, struct smack_cipso *);
220char *smack_from_cipso(u32, char *);
221char *smack_from_secid(const u32); 214char *smack_from_secid(const u32);
222void smk_parse_smack(const char *string, int len, char *smack); 215char *smk_parse_smack(const char *string, int len);
216int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
223char *smk_import(const char *, int); 217char *smk_import(const char *, int);
224struct smack_known *smk_import_entry(const char *, int); 218struct smack_known *smk_import_entry(const char *, int);
225struct smack_known *smk_find_entry(const char *); 219struct smack_known *smk_find_entry(const char *);
@@ -229,6 +223,7 @@ u32 smack_to_secid(const char *);
229 * Shared data. 223 * Shared data.
230 */ 224 */
231extern int smack_cipso_direct; 225extern int smack_cipso_direct;
226extern int smack_cipso_mapped;
232extern char *smack_net_ambient; 227extern char *smack_net_ambient;
233extern char *smack_onlycap; 228extern char *smack_onlycap;
234extern const char *smack_cipso_option; 229extern const char *smack_cipso_option;
@@ -240,24 +235,13 @@ extern struct smack_known smack_known_invalid;
240extern struct smack_known smack_known_star; 235extern struct smack_known smack_known_star;
241extern struct smack_known smack_known_web; 236extern struct smack_known smack_known_web;
242 237
238extern struct mutex smack_known_lock;
243extern struct list_head smack_known_list; 239extern struct list_head smack_known_list;
244extern struct list_head smk_netlbladdr_list; 240extern struct list_head smk_netlbladdr_list;
245 241
246extern struct security_operations smack_ops; 242extern struct security_operations smack_ops;
247 243
248/* 244/*
249 * Stricly for CIPSO level manipulation.
250 * Set the category bit number in a smack label sized buffer.
251 */
252static inline void smack_catset_bit(int cat, char *catsetp)
253{
254 if (cat > SMK_LABELLEN * 8)
255 return;
256
257 catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
258}
259
260/*
261 * Is the directory transmuting? 245 * Is the directory transmuting?
262 */ 246 */
263static inline int smk_inode_transmutable(const struct inode *isp) 247static inline int smk_inode_transmutable(const struct inode *isp)
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index c8115f7308f..9f3705e9271 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -19,37 +19,31 @@
19struct smack_known smack_known_huh = { 19struct smack_known smack_known_huh = {
20 .smk_known = "?", 20 .smk_known = "?",
21 .smk_secid = 2, 21 .smk_secid = 2,
22 .smk_cipso = NULL,
23}; 22};
24 23
25struct smack_known smack_known_hat = { 24struct smack_known smack_known_hat = {
26 .smk_known = "^", 25 .smk_known = "^",
27 .smk_secid = 3, 26 .smk_secid = 3,
28 .smk_cipso = NULL,
29}; 27};
30 28
31struct smack_known smack_known_star = { 29struct smack_known smack_known_star = {
32 .smk_known = "*", 30 .smk_known = "*",
33 .smk_secid = 4, 31 .smk_secid = 4,
34 .smk_cipso = NULL,
35}; 32};
36 33
37struct smack_known smack_known_floor = { 34struct smack_known smack_known_floor = {
38 .smk_known = "_", 35 .smk_known = "_",
39 .smk_secid = 5, 36 .smk_secid = 5,
40 .smk_cipso = NULL,
41}; 37};
42 38
43struct smack_known smack_known_invalid = { 39struct smack_known smack_known_invalid = {
44 .smk_known = "", 40 .smk_known = "",
45 .smk_secid = 6, 41 .smk_secid = 6,
46 .smk_cipso = NULL,
47}; 42};
48 43
49struct smack_known smack_known_web = { 44struct smack_known smack_known_web = {
50 .smk_known = "@", 45 .smk_known = "@",
51 .smk_secid = 7, 46 .smk_secid = 7,
52 .smk_cipso = NULL,
53}; 47};
54 48
55LIST_HEAD(smack_known_list); 49LIST_HEAD(smack_known_list);
@@ -331,7 +325,7 @@ void smack_log(char *subject_label, char *object_label, int request,
331} 325}
332#endif 326#endif
333 327
334static DEFINE_MUTEX(smack_known_lock); 328DEFINE_MUTEX(smack_known_lock);
335 329
336/** 330/**
337 * smk_find_entry - find a label on the list, return the list entry 331 * smk_find_entry - find a label on the list, return the list entry
@@ -345,7 +339,7 @@ struct smack_known *smk_find_entry(const char *string)
345 struct smack_known *skp; 339 struct smack_known *skp;
346 340
347 list_for_each_entry_rcu(skp, &smack_known_list, list) { 341 list_for_each_entry_rcu(skp, &smack_known_list, list) {
348 if (strncmp(skp->smk_known, string, SMK_MAXLEN) == 0) 342 if (strcmp(skp->smk_known, string) == 0)
349 return skp; 343 return skp;
350 } 344 }
351 345
@@ -356,27 +350,76 @@ struct smack_known *smk_find_entry(const char *string)
356 * smk_parse_smack - parse smack label from a text string 350 * smk_parse_smack - parse smack label from a text string
357 * @string: a text string that might contain a Smack label 351 * @string: a text string that might contain a Smack label
358 * @len: the maximum size, or zero if it is NULL terminated. 352 * @len: the maximum size, or zero if it is NULL terminated.
359 * @smack: parsed smack label, or NULL if parse error 353 *
354 * Returns a pointer to the clean label, or NULL
360 */ 355 */
361void smk_parse_smack(const char *string, int len, char *smack) 356char *smk_parse_smack(const char *string, int len)
362{ 357{
363 int found; 358 char *smack;
364 int i; 359 int i;
365 360
366 if (len <= 0 || len > SMK_MAXLEN) 361 if (len <= 0)
367 len = SMK_MAXLEN; 362 len = strlen(string) + 1;
368 363
369 for (i = 0, found = 0; i < SMK_LABELLEN; i++) { 364 /*
370 if (found) 365 * Reserve a leading '-' as an indicator that
371 smack[i] = '\0'; 366 * this isn't a label, but an option to interfaces
372 else if (i >= len || string[i] > '~' || string[i] <= ' ' || 367 * including /smack/cipso and /smack/cipso2
373 string[i] == '/' || string[i] == '"' || 368 */
374 string[i] == '\\' || string[i] == '\'') { 369 if (string[0] == '-')
375 smack[i] = '\0'; 370 return NULL;
376 found = 1; 371
377 } else 372 for (i = 0; i < len; i++)
378 smack[i] = string[i]; 373 if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' ||
374 string[i] == '"' || string[i] == '\\' || string[i] == '\'')
375 break;
376
377 if (i == 0 || i >= SMK_LONGLABEL)
378 return NULL;
379
380 smack = kzalloc(i + 1, GFP_KERNEL);
381 if (smack != NULL) {
382 strncpy(smack, string, i + 1);
383 smack[i] = '\0';
379 } 384 }
385 return smack;
386}
387
388/**
389 * smk_netlbl_mls - convert a catset to netlabel mls categories
390 * @catset: the Smack categories
391 * @sap: where to put the netlabel categories
392 *
393 * Allocates and fills attr.mls
394 * Returns 0 on success, error code on failure.
395 */
396int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
397 int len)
398{
399 unsigned char *cp;
400 unsigned char m;
401 int cat;
402 int rc;
403 int byte;
404
405 sap->flags |= NETLBL_SECATTR_MLS_CAT;
406 sap->attr.mls.lvl = level;
407 sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
408 sap->attr.mls.cat->startbit = 0;
409
410 for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++)
411 for (m = 0x80; m != 0; m >>= 1, cat++) {
412 if ((m & *cp) == 0)
413 continue;
414 rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
415 cat, GFP_ATOMIC);
416 if (rc < 0) {
417 netlbl_secattr_catmap_free(sap->attr.mls.cat);
418 return rc;
419 }
420 }
421
422 return 0;
380} 423}
381 424
382/** 425/**
@@ -390,33 +433,59 @@ void smk_parse_smack(const char *string, int len, char *smack)
390struct smack_known *smk_import_entry(const char *string, int len) 433struct smack_known *smk_import_entry(const char *string, int len)
391{ 434{
392 struct smack_known *skp; 435 struct smack_known *skp;
393 char smack[SMK_LABELLEN]; 436 char *smack;
437 int slen;
438 int rc;
394 439
395 smk_parse_smack(string, len, smack); 440 smack = smk_parse_smack(string, len);
396 if (smack[0] == '\0') 441 if (smack == NULL)
397 return NULL; 442 return NULL;
398 443
399 mutex_lock(&smack_known_lock); 444 mutex_lock(&smack_known_lock);
400 445
401 skp = smk_find_entry(smack); 446 skp = smk_find_entry(smack);
447 if (skp != NULL)
448 goto freeout;
402 449
403 if (skp == NULL) { 450 skp = kzalloc(sizeof(*skp), GFP_KERNEL);
404 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL); 451 if (skp == NULL)
405 if (skp != NULL) { 452 goto freeout;
406 strncpy(skp->smk_known, smack, SMK_MAXLEN);
407 skp->smk_secid = smack_next_secid++;
408 skp->smk_cipso = NULL;
409 INIT_LIST_HEAD(&skp->smk_rules);
410 spin_lock_init(&skp->smk_cipsolock);
411 mutex_init(&skp->smk_rules_lock);
412 /*
413 * Make sure that the entry is actually
414 * filled before putting it on the list.
415 */
416 list_add_rcu(&skp->list, &smack_known_list);
417 }
418 }
419 453
454 skp->smk_known = smack;
455 skp->smk_secid = smack_next_secid++;
456 skp->smk_netlabel.domain = skp->smk_known;
457 skp->smk_netlabel.flags =
458 NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
459 /*
460 * If direct labeling works use it.
461 * Otherwise use mapped labeling.
462 */
463 slen = strlen(smack);
464 if (slen < SMK_CIPSOLEN)
465 rc = smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
466 &skp->smk_netlabel, slen);
467 else
468 rc = smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid,
469 &skp->smk_netlabel, sizeof(skp->smk_secid));
470
471 if (rc >= 0) {
472 INIT_LIST_HEAD(&skp->smk_rules);
473 mutex_init(&skp->smk_rules_lock);
474 /*
475 * Make sure that the entry is actually
476 * filled before putting it on the list.
477 */
478 list_add_rcu(&skp->list, &smack_known_list);
479 goto unlockout;
480 }
481 /*
482 * smk_netlbl_mls failed.
483 */
484 kfree(skp);
485 skp = NULL;
486freeout:
487 kfree(smack);
488unlockout:
420 mutex_unlock(&smack_known_lock); 489 mutex_unlock(&smack_known_lock);
421 490
422 return skp; 491 return skp;
@@ -479,79 +548,9 @@ char *smack_from_secid(const u32 secid)
479 */ 548 */
480u32 smack_to_secid(const char *smack) 549u32 smack_to_secid(const char *smack)
481{ 550{
482 struct smack_known *skp; 551 struct smack_known *skp = smk_find_entry(smack);
483 552
484 rcu_read_lock(); 553 if (skp == NULL)
485 list_for_each_entry_rcu(skp, &smack_known_list, list) { 554 return 0;
486 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) { 555 return skp->smk_secid;
487 rcu_read_unlock();
488 return skp->smk_secid;
489 }
490 }
491 rcu_read_unlock();
492 return 0;
493}
494
495/**
496 * smack_from_cipso - find the Smack label associated with a CIPSO option
497 * @level: Bell & LaPadula level from the network
498 * @cp: Bell & LaPadula categories from the network
499 *
500 * This is a simple lookup in the label table.
501 *
502 * Return the matching label from the label list or NULL.
503 */
504char *smack_from_cipso(u32 level, char *cp)
505{
506 struct smack_known *kp;
507 char *final = NULL;
508
509 rcu_read_lock();
510 list_for_each_entry(kp, &smack_known_list, list) {
511 if (kp->smk_cipso == NULL)
512 continue;
513
514 spin_lock_bh(&kp->smk_cipsolock);
515
516 if (kp->smk_cipso->smk_level == level &&
517 memcmp(kp->smk_cipso->smk_catset, cp, SMK_LABELLEN) == 0)
518 final = kp->smk_known;
519
520 spin_unlock_bh(&kp->smk_cipsolock);
521
522 if (final != NULL)
523 break;
524 }
525 rcu_read_unlock();
526
527 return final;
528}
529
530/**
531 * smack_to_cipso - find the CIPSO option to go with a Smack label
532 * @smack: a pointer to the smack label in question
533 * @cp: where to put the result
534 *
535 * Returns zero if a value is available, non-zero otherwise.
536 */
537int smack_to_cipso(const char *smack, struct smack_cipso *cp)
538{
539 struct smack_known *kp;
540 int found = 0;
541
542 rcu_read_lock();
543 list_for_each_entry_rcu(kp, &smack_known_list, list) {
544 if (kp->smk_known == smack ||
545 strcmp(kp->smk_known, smack) == 0) {
546 found = 1;
547 break;
548 }
549 }
550 rcu_read_unlock();
551
552 if (found == 0 || kp->smk_cipso == NULL)
553 return -ENOENT;
554
555 memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
556 return 0;
557} 556}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 5f80075d771..952b1f41fc7 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -30,7 +30,6 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/pipe_fs_i.h> 32#include <linux/pipe_fs_i.h>
33#include <net/netlabel.h>
34#include <net/cipso_ipv4.h> 33#include <net/cipso_ipv4.h>
35#include <linux/audit.h> 34#include <linux/audit.h>
36#include <linux/magic.h> 35#include <linux/magic.h>
@@ -57,16 +56,23 @@
57static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) 56static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp)
58{ 57{
59 int rc; 58 int rc;
60 char in[SMK_LABELLEN]; 59 char *buffer;
60 char *result = NULL;
61 61
62 if (ip->i_op->getxattr == NULL) 62 if (ip->i_op->getxattr == NULL)
63 return NULL; 63 return NULL;
64 64
65 rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN); 65 buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
66 if (rc < 0) 66 if (buffer == NULL)
67 return NULL; 67 return NULL;
68 68
69 return smk_import(in, rc); 69 rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
70 if (rc > 0)
71 result = smk_import(buffer, rc);
72
73 kfree(buffer);
74
75 return result;
70} 76}
71 77
72/** 78/**
@@ -825,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
825 * check label validity here so import wont fail on 831 * check label validity here so import wont fail on
826 * post_setxattr 832 * post_setxattr
827 */ 833 */
828 if (size == 0 || size >= SMK_LABELLEN || 834 if (size == 0 || size >= SMK_LONGLABEL ||
829 smk_import(value, size) == NULL) 835 smk_import(value, size) == NULL)
830 rc = -EINVAL; 836 rc = -EINVAL;
831 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { 837 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
@@ -1824,65 +1830,6 @@ static char *smack_host_label(struct sockaddr_in *sip)
1824} 1830}
1825 1831
1826/** 1832/**
1827 * smack_set_catset - convert a capset to netlabel mls categories
1828 * @catset: the Smack categories
1829 * @sap: where to put the netlabel categories
1830 *
1831 * Allocates and fills attr.mls.cat
1832 */
1833static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
1834{
1835 unsigned char *cp;
1836 unsigned char m;
1837 int cat;
1838 int rc;
1839 int byte;
1840
1841 if (!catset)
1842 return;
1843
1844 sap->flags |= NETLBL_SECATTR_MLS_CAT;
1845 sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1846 sap->attr.mls.cat->startbit = 0;
1847
1848 for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++)
1849 for (m = 0x80; m != 0; m >>= 1, cat++) {
1850 if ((m & *cp) == 0)
1851 continue;
1852 rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
1853 cat, GFP_ATOMIC);
1854 }
1855}
1856
1857/**
1858 * smack_to_secattr - fill a secattr from a smack value
1859 * @smack: the smack value
1860 * @nlsp: where the result goes
1861 *
1862 * Casey says that CIPSO is good enough for now.
1863 * It can be used to effect.
1864 * It can also be abused to effect when necessary.
1865 * Apologies to the TSIG group in general and GW in particular.
1866 */
1867static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1868{
1869 struct smack_cipso cipso;
1870 int rc;
1871
1872 nlsp->domain = smack;
1873 nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1874
1875 rc = smack_to_cipso(smack, &cipso);
1876 if (rc == 0) {
1877 nlsp->attr.mls.lvl = cipso.smk_level;
1878 smack_set_catset(cipso.smk_catset, nlsp);
1879 } else {
1880 nlsp->attr.mls.lvl = smack_cipso_direct;
1881 smack_set_catset(smack, nlsp);
1882 }
1883}
1884
1885/**
1886 * smack_netlabel - Set the secattr on a socket 1833 * smack_netlabel - Set the secattr on a socket
1887 * @sk: the socket 1834 * @sk: the socket
1888 * @labeled: socket label scheme 1835 * @labeled: socket label scheme
@@ -1894,8 +1841,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1894 */ 1841 */
1895static int smack_netlabel(struct sock *sk, int labeled) 1842static int smack_netlabel(struct sock *sk, int labeled)
1896{ 1843{
1844 struct smack_known *skp;
1897 struct socket_smack *ssp = sk->sk_security; 1845 struct socket_smack *ssp = sk->sk_security;
1898 struct netlbl_lsm_secattr secattr;
1899 int rc = 0; 1846 int rc = 0;
1900 1847
1901 /* 1848 /*
@@ -1913,10 +1860,8 @@ static int smack_netlabel(struct sock *sk, int labeled)
1913 labeled == SMACK_UNLABELED_SOCKET) 1860 labeled == SMACK_UNLABELED_SOCKET)
1914 netlbl_sock_delattr(sk); 1861 netlbl_sock_delattr(sk);
1915 else { 1862 else {
1916 netlbl_secattr_init(&secattr); 1863 skp = smk_find_entry(ssp->smk_out);
1917 smack_to_secattr(ssp->smk_out, &secattr); 1864 rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
1918 rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
1919 netlbl_secattr_destroy(&secattr);
1920 } 1865 }
1921 1866
1922 bh_unlock_sock(sk); 1867 bh_unlock_sock(sk);
@@ -1989,7 +1934,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1989 struct socket *sock; 1934 struct socket *sock;
1990 int rc = 0; 1935 int rc = 0;
1991 1936
1992 if (value == NULL || size > SMK_LABELLEN || size == 0) 1937 if (value == NULL || size > SMK_LONGLABEL || size == 0)
1993 return -EACCES; 1938 return -EACCES;
1994 1939
1995 sp = smk_import(value, size); 1940 sp = smk_import(value, size);
@@ -2785,7 +2730,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2785 if (!capable(CAP_MAC_ADMIN)) 2730 if (!capable(CAP_MAC_ADMIN))
2786 return -EPERM; 2731 return -EPERM;
2787 2732
2788 if (value == NULL || size == 0 || size >= SMK_LABELLEN) 2733 if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
2789 return -EINVAL; 2734 return -EINVAL;
2790 2735
2791 if (strcmp(name, "current") != 0) 2736 if (strcmp(name, "current") != 0)
@@ -2921,10 +2866,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2921static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, 2866static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
2922 struct socket_smack *ssp) 2867 struct socket_smack *ssp)
2923{ 2868{
2924 struct smack_known *skp; 2869 struct smack_known *kp;
2925 char smack[SMK_LABELLEN];
2926 char *sp; 2870 char *sp;
2927 int pcat; 2871 int found = 0;
2928 2872
2929 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { 2873 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
2930 /* 2874 /*
@@ -2932,59 +2876,27 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
2932 * If there are flags but no level netlabel isn't 2876 * If there are flags but no level netlabel isn't
2933 * behaving the way we expect it to. 2877 * behaving the way we expect it to.
2934 * 2878 *
2935 * Get the categories, if any 2879 * Look it up in the label table
2936 * Without guidance regarding the smack value 2880 * Without guidance regarding the smack value
2937 * for the packet fall back on the network 2881 * for the packet fall back on the network
2938 * ambient value. 2882 * ambient value.
2939 */ 2883 */
2940 memset(smack, '\0', SMK_LABELLEN); 2884 rcu_read_lock();
2941 if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) 2885 list_for_each_entry(kp, &smack_known_list, list) {
2942 for (pcat = -1;;) { 2886 if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl)
2943 pcat = netlbl_secattr_catmap_walk( 2887 continue;
2944 sap->attr.mls.cat, pcat + 1); 2888 if (memcmp(sap->attr.mls.cat,
2945 if (pcat < 0) 2889 kp->smk_netlabel.attr.mls.cat,
2946 break; 2890 SMK_CIPSOLEN) != 0)
2947 smack_catset_bit(pcat, smack); 2891 continue;
2948 } 2892 found = 1;
2949 /* 2893 break;
2950 * If it is CIPSO using smack direct mapping
2951 * we are already done. WeeHee.
2952 */
2953 if (sap->attr.mls.lvl == smack_cipso_direct) {
2954 /*
2955 * The label sent is usually on the label list.
2956 *
2957 * If it is not we may still want to allow the
2958 * delivery.
2959 *
2960 * If the recipient is accepting all packets
2961 * because it is using the star ("*") label
2962 * for SMACK64IPIN provide the web ("@") label
2963 * so that a directed response will succeed.
2964 * This is not very correct from a MAC point
2965 * of view, but gets around the problem that
2966 * locking prevents adding the newly discovered
2967 * label to the list.
2968 * The case where the recipient is not using
2969 * the star label should obviously fail.
2970 * The easy way to do this is to provide the
2971 * star label as the subject label.
2972 */
2973 skp = smk_find_entry(smack);
2974 if (skp != NULL)
2975 return skp->smk_known;
2976 if (ssp != NULL &&
2977 ssp->smk_in == smack_known_star.smk_known)
2978 return smack_known_web.smk_known;
2979 return smack_known_star.smk_known;
2980 } 2894 }
2981 /* 2895 rcu_read_unlock();
2982 * Look it up in the supplied table if it is not 2896
2983 * a direct mapping. 2897 if (found)
2984 */ 2898 return kp->smk_known;
2985 sp = smack_from_cipso(sap->attr.mls.lvl, smack); 2899
2986 if (sp != NULL)
2987 return sp;
2988 if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) 2900 if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
2989 return smack_known_web.smk_known; 2901 return smack_known_web.smk_known;
2990 return smack_known_star.smk_known; 2902 return smack_known_star.smk_known;
@@ -3184,11 +3096,13 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3184 struct request_sock *req) 3096 struct request_sock *req)
3185{ 3097{
3186 u16 family = sk->sk_family; 3098 u16 family = sk->sk_family;
3099 struct smack_known *skp;
3187 struct socket_smack *ssp = sk->sk_security; 3100 struct socket_smack *ssp = sk->sk_security;
3188 struct netlbl_lsm_secattr secattr; 3101 struct netlbl_lsm_secattr secattr;
3189 struct sockaddr_in addr; 3102 struct sockaddr_in addr;
3190 struct iphdr *hdr; 3103 struct iphdr *hdr;
3191 char *sp; 3104 char *sp;
3105 char *hsp;
3192 int rc; 3106 int rc;
3193 struct smk_audit_info ad; 3107 struct smk_audit_info ad;
3194#ifdef CONFIG_AUDIT 3108#ifdef CONFIG_AUDIT
@@ -3235,16 +3149,14 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3235 hdr = ip_hdr(skb); 3149 hdr = ip_hdr(skb);
3236 addr.sin_addr.s_addr = hdr->saddr; 3150 addr.sin_addr.s_addr = hdr->saddr;
3237 rcu_read_lock(); 3151 rcu_read_lock();
3238 if (smack_host_label(&addr) == NULL) { 3152 hsp = smack_host_label(&addr);
3239 rcu_read_unlock(); 3153 rcu_read_unlock();
3240 netlbl_secattr_init(&secattr); 3154
3241 smack_to_secattr(sp, &secattr); 3155 if (hsp == NULL) {
3242 rc = netlbl_req_setattr(req, &secattr); 3156 skp = smk_find_entry(sp);
3243 netlbl_secattr_destroy(&secattr); 3157 rc = netlbl_req_setattr(req, &skp->smk_netlabel);
3244 } else { 3158 } else
3245 rcu_read_unlock();
3246 netlbl_req_delattr(req); 3159 netlbl_req_delattr(req);
3247 }
3248 3160
3249 return rc; 3161 return rc;
3250} 3162}
@@ -3669,15 +3581,6 @@ struct security_operations smack_ops = {
3669static __init void init_smack_known_list(void) 3581static __init void init_smack_known_list(void)
3670{ 3582{
3671 /* 3583 /*
3672 * Initialize CIPSO locks
3673 */
3674 spin_lock_init(&smack_known_huh.smk_cipsolock);
3675 spin_lock_init(&smack_known_hat.smk_cipsolock);
3676 spin_lock_init(&smack_known_star.smk_cipsolock);
3677 spin_lock_init(&smack_known_floor.smk_cipsolock);
3678 spin_lock_init(&smack_known_invalid.smk_cipsolock);
3679 spin_lock_init(&smack_known_web.smk_cipsolock);
3680 /*
3681 * Initialize rule list locks 3584 * Initialize rule list locks
3682 */ 3585 */
3683 mutex_init(&smack_known_huh.smk_rules_lock); 3586 mutex_init(&smack_known_huh.smk_rules_lock);
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 038811cb7e6..1810c9a4ed4 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -22,7 +22,6 @@
22#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <net/net_namespace.h> 24#include <net/net_namespace.h>
25#include <net/netlabel.h>
26#include <net/cipso_ipv4.h> 25#include <net/cipso_ipv4.h>
27#include <linux/seq_file.h> 26#include <linux/seq_file.h>
28#include <linux/ctype.h> 27#include <linux/ctype.h>
@@ -45,6 +44,11 @@ enum smk_inos {
45 SMK_LOGGING = 10, /* logging */ 44 SMK_LOGGING = 10, /* logging */
46 SMK_LOAD_SELF = 11, /* task specific rules */ 45 SMK_LOAD_SELF = 11, /* task specific rules */
47 SMK_ACCESSES = 12, /* access policy */ 46 SMK_ACCESSES = 12, /* access policy */
47 SMK_MAPPED = 13, /* CIPSO level indicating mapped label */
48 SMK_LOAD2 = 14, /* load policy with long labels */
49 SMK_LOAD_SELF2 = 15, /* load task specific rules with long labels */
50 SMK_ACCESS2 = 16, /* make an access check with long labels */
51 SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */
48}; 52};
49 53
50/* 54/*
@@ -60,7 +64,7 @@ static DEFINE_MUTEX(smk_netlbladdr_lock);
60 * If it isn't somehow marked, use this. 64 * If it isn't somehow marked, use this.
61 * It can be reset via smackfs/ambient 65 * It can be reset via smackfs/ambient
62 */ 66 */
63char *smack_net_ambient = smack_known_floor.smk_known; 67char *smack_net_ambient;
64 68
65/* 69/*
66 * This is the level in a CIPSO header that indicates a 70 * This is the level in a CIPSO header that indicates a
@@ -70,6 +74,13 @@ char *smack_net_ambient = smack_known_floor.smk_known;
70int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; 74int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
71 75
72/* 76/*
77 * This is the level in a CIPSO header that indicates a
78 * secid is contained directly in the category set.
79 * It can be reset via smackfs/mapped
80 */
81int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
82
83/*
73 * Unless a process is running with this label even 84 * Unless a process is running with this label even
74 * having CAP_MAC_OVERRIDE isn't enough to grant 85 * having CAP_MAC_OVERRIDE isn't enough to grant
75 * privilege to violate MAC policy. If no label is 86 * privilege to violate MAC policy. If no label is
@@ -89,7 +100,7 @@ LIST_HEAD(smk_netlbladdr_list);
89 100
90/* 101/*
91 * Rule lists are maintained for each label. 102 * Rule lists are maintained for each label.
92 * This master list is just for reading /smack/load. 103 * This master list is just for reading /smack/load and /smack/load2.
93 */ 104 */
94struct smack_master_list { 105struct smack_master_list {
95 struct list_head list; 106 struct list_head list;
@@ -125,6 +136,18 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION;
125#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) 136#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
126#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) 137#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
127 138
139/*
140 * Stricly for CIPSO level manipulation.
141 * Set the category bit number in a smack label sized buffer.
142 */
143static inline void smack_catset_bit(unsigned int cat, char *catsetp)
144{
145 if (cat == 0 || cat > (SMK_CIPSOLEN * 8))
146 return;
147
148 catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
149}
150
128/** 151/**
129 * smk_netlabel_audit_set - fill a netlbl_audit struct 152 * smk_netlabel_audit_set - fill a netlbl_audit struct
130 * @nap: structure to fill 153 * @nap: structure to fill
@@ -137,12 +160,10 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
137} 160}
138 161
139/* 162/*
140 * Values for parsing single label host rules 163 * Value for parsing single label host rules
141 * "1.2.3.4 X" 164 * "1.2.3.4 X"
142 * "192.168.138.129/32 abcdefghijklmnopqrstuvw"
143 */ 165 */
144#define SMK_NETLBLADDRMIN 9 166#define SMK_NETLBLADDRMIN 9
145#define SMK_NETLBLADDRMAX 42
146 167
147/** 168/**
148 * smk_set_access - add a rule to the rule list 169 * smk_set_access - add a rule to the rule list
@@ -188,33 +209,47 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
188} 209}
189 210
190/** 211/**
191 * smk_parse_rule - parse Smack rule from load string 212 * smk_fill_rule - Fill Smack rule from strings
192 * @data: string to be parsed whose size is SMK_LOADLEN 213 * @subject: subject label string
214 * @object: object label string
215 * @access: access string
193 * @rule: Smack rule 216 * @rule: Smack rule
194 * @import: if non-zero, import labels 217 * @import: if non-zero, import labels
218 *
219 * Returns 0 on success, -1 on failure
195 */ 220 */
196static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) 221static int smk_fill_rule(const char *subject, const char *object,
222 const char *access, struct smack_rule *rule,
223 int import)
197{ 224{
198 char smack[SMK_LABELLEN]; 225 int rc = -1;
226 int done;
227 const char *cp;
199 struct smack_known *skp; 228 struct smack_known *skp;
200 229
201 if (import) { 230 if (import) {
202 rule->smk_subject = smk_import(data, 0); 231 rule->smk_subject = smk_import(subject, 0);
203 if (rule->smk_subject == NULL) 232 if (rule->smk_subject == NULL)
204 return -1; 233 return -1;
205 234
206 rule->smk_object = smk_import(data + SMK_LABELLEN, 0); 235 rule->smk_object = smk_import(object, 0);
207 if (rule->smk_object == NULL) 236 if (rule->smk_object == NULL)
208 return -1; 237 return -1;
209 } else { 238 } else {
210 smk_parse_smack(data, 0, smack); 239 cp = smk_parse_smack(subject, 0);
211 skp = smk_find_entry(smack); 240 if (cp == NULL)
241 return -1;
242 skp = smk_find_entry(cp);
243 kfree(cp);
212 if (skp == NULL) 244 if (skp == NULL)
213 return -1; 245 return -1;
214 rule->smk_subject = skp->smk_known; 246 rule->smk_subject = skp->smk_known;
215 247
216 smk_parse_smack(data + SMK_LABELLEN, 0, smack); 248 cp = smk_parse_smack(object, 0);
217 skp = smk_find_entry(smack); 249 if (cp == NULL)
250 return -1;
251 skp = smk_find_entry(cp);
252 kfree(cp);
218 if (skp == NULL) 253 if (skp == NULL)
219 return -1; 254 return -1;
220 rule->smk_object = skp->smk_known; 255 rule->smk_object = skp->smk_known;
@@ -222,90 +257,127 @@ static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
222 257
223 rule->smk_access = 0; 258 rule->smk_access = 0;
224 259
225 switch (data[SMK_LABELLEN + SMK_LABELLEN]) { 260 for (cp = access, done = 0; *cp && !done; cp++) {
226 case '-': 261 switch (*cp) {
227 break; 262 case '-':
228 case 'r': 263 break;
229 case 'R': 264 case 'r':
230 rule->smk_access |= MAY_READ; 265 case 'R':
231 break; 266 rule->smk_access |= MAY_READ;
232 default: 267 break;
233 return -1; 268 case 'w':
269 case 'W':
270 rule->smk_access |= MAY_WRITE;
271 break;
272 case 'x':
273 case 'X':
274 rule->smk_access |= MAY_EXEC;
275 break;
276 case 'a':
277 case 'A':
278 rule->smk_access |= MAY_APPEND;
279 break;
280 case 't':
281 case 'T':
282 rule->smk_access |= MAY_TRANSMUTE;
283 break;
284 default:
285 done = 1;
286 break;
287 }
234 } 288 }
289 rc = 0;
235 290
236 switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) { 291 return rc;
237 case '-': 292}
238 break;
239 case 'w':
240 case 'W':
241 rule->smk_access |= MAY_WRITE;
242 break;
243 default:
244 return -1;
245 }
246 293
247 switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) { 294/**
248 case '-': 295 * smk_parse_rule - parse Smack rule from load string
249 break; 296 * @data: string to be parsed whose size is SMK_LOADLEN
250 case 'x': 297 * @rule: Smack rule
251 case 'X': 298 * @import: if non-zero, import labels
252 rule->smk_access |= MAY_EXEC; 299 *
253 break; 300 * Returns 0 on success, -1 on errors.
254 default: 301 */
255 return -1; 302static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
256 } 303{
304 int rc;
257 305
258 switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) { 306 rc = smk_fill_rule(data, data + SMK_LABELLEN,
259 case '-': 307 data + SMK_LABELLEN + SMK_LABELLEN, rule, import);
260 break; 308 return rc;
261 case 'a': 309}
262 case 'A':
263 rule->smk_access |= MAY_APPEND;
264 break;
265 default:
266 return -1;
267 }
268 310
269 switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) { 311/**
270 case '-': 312 * smk_parse_long_rule - parse Smack rule from rule string
271 break; 313 * @data: string to be parsed, null terminated
272 case 't': 314 * @rule: Smack rule
273 case 'T': 315 * @import: if non-zero, import labels
274 rule->smk_access |= MAY_TRANSMUTE; 316 *
275 break; 317 * Returns 0 on success, -1 on failure
276 default: 318 */
277 return -1; 319static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
278 } 320 int import)
321{
322 char *subject;
323 char *object;
324 char *access;
325 int datalen;
326 int rc = -1;
279 327
280 return 0; 328 /*
329 * This is probably inefficient, but safe.
330 */
331 datalen = strlen(data);
332 subject = kzalloc(datalen, GFP_KERNEL);
333 if (subject == NULL)
334 return -1;
335 object = kzalloc(datalen, GFP_KERNEL);
336 if (object == NULL)
337 goto free_out_s;
338 access = kzalloc(datalen, GFP_KERNEL);
339 if (access == NULL)
340 goto free_out_o;
341
342 if (sscanf(data, "%s %s %s", subject, object, access) == 3)
343 rc = smk_fill_rule(subject, object, access, rule, import);
344
345 kfree(access);
346free_out_o:
347 kfree(object);
348free_out_s:
349 kfree(subject);
350 return rc;
281} 351}
282 352
353#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */
354#define SMK_LONG_FMT 1 /* Variable long label format */
283/** 355/**
284 * smk_write_load_list - write() for any /smack/load 356 * smk_write_rules_list - write() for any /smack rule file
285 * @file: file pointer, not actually used 357 * @file: file pointer, not actually used
286 * @buf: where to get the data from 358 * @buf: where to get the data from
287 * @count: bytes sent 359 * @count: bytes sent
288 * @ppos: where to start - must be 0 360 * @ppos: where to start - must be 0
289 * @rule_list: the list of rules to write to 361 * @rule_list: the list of rules to write to
290 * @rule_lock: lock for the rule list 362 * @rule_lock: lock for the rule list
363 * @format: /smack/load or /smack/load2 format.
291 * 364 *
292 * Get one smack access rule from above. 365 * Get one smack access rule from above.
293 * The format is exactly: 366 * The format for SMK_LONG_FMT is:
294 * char subject[SMK_LABELLEN] 367 * "subject<whitespace>object<whitespace>access[<whitespace>...]"
295 * char object[SMK_LABELLEN] 368 * The format for SMK_FIXED24_FMT is exactly:
296 * char access[SMK_ACCESSLEN] 369 * "subject object rwxat"
297 *
298 * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
299 */ 370 */
300static ssize_t smk_write_load_list(struct file *file, const char __user *buf, 371static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
301 size_t count, loff_t *ppos, 372 size_t count, loff_t *ppos,
302 struct list_head *rule_list, 373 struct list_head *rule_list,
303 struct mutex *rule_lock) 374 struct mutex *rule_lock, int format)
304{ 375{
305 struct smack_master_list *smlp; 376 struct smack_master_list *smlp;
306 struct smack_known *skp; 377 struct smack_known *skp;
307 struct smack_rule *rule; 378 struct smack_rule *rule;
308 char *data; 379 char *data;
380 int datalen;
309 int rc = -EINVAL; 381 int rc = -EINVAL;
310 int load = 0; 382 int load = 0;
311 383
@@ -315,13 +387,18 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
315 */ 387 */
316 if (*ppos != 0) 388 if (*ppos != 0)
317 return -EINVAL; 389 return -EINVAL;
318 /*
319 * Minor hack for backward compatibility
320 */
321 if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN)
322 return -EINVAL;
323 390
324 data = kzalloc(SMK_LOADLEN, GFP_KERNEL); 391 if (format == SMK_FIXED24_FMT) {
392 /*
393 * Minor hack for backward compatibility
394 */
395 if (count != SMK_OLOADLEN && count != SMK_LOADLEN)
396 return -EINVAL;
397 datalen = SMK_LOADLEN;
398 } else
399 datalen = count + 1;
400
401 data = kzalloc(datalen, GFP_KERNEL);
325 if (data == NULL) 402 if (data == NULL)
326 return -ENOMEM; 403 return -ENOMEM;
327 404
@@ -330,20 +407,29 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
330 goto out; 407 goto out;
331 } 408 }
332 409
333 /*
334 * More on the minor hack for backward compatibility
335 */
336 if (count == (SMK_OLOADLEN))
337 data[SMK_OLOADLEN] = '-';
338
339 rule = kzalloc(sizeof(*rule), GFP_KERNEL); 410 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
340 if (rule == NULL) { 411 if (rule == NULL) {
341 rc = -ENOMEM; 412 rc = -ENOMEM;
342 goto out; 413 goto out;
343 } 414 }
344 415
345 if (smk_parse_rule(data, rule, 1)) 416 if (format == SMK_LONG_FMT) {
346 goto out_free_rule; 417 /*
418 * Be sure the data string is terminated.
419 */
420 data[count] = '\0';
421 if (smk_parse_long_rule(data, rule, 1))
422 goto out_free_rule;
423 } else {
424 /*
425 * More on the minor hack for backward compatibility
426 */
427 if (count == (SMK_OLOADLEN))
428 data[SMK_OLOADLEN] = '-';
429 if (smk_parse_rule(data, rule, 1))
430 goto out_free_rule;
431 }
432
347 433
348 if (rule_list == NULL) { 434 if (rule_list == NULL) {
349 load = 1; 435 load = 1;
@@ -354,18 +440,20 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
354 440
355 rc = count; 441 rc = count;
356 /* 442 /*
357 * If this is "load" as opposed to "load-self" and a new rule 443 * If this is a global as opposed to self and a new rule
358 * it needs to get added for reporting. 444 * it needs to get added for reporting.
359 * smk_set_access returns true if there was already a rule 445 * smk_set_access returns true if there was already a rule
360 * for the subject/object pair, and false if it was new. 446 * for the subject/object pair, and false if it was new.
361 */ 447 */
362 if (load && !smk_set_access(rule, rule_list, rule_lock)) { 448 if (!smk_set_access(rule, rule_list, rule_lock)) {
363 smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); 449 if (load) {
364 if (smlp != NULL) { 450 smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
365 smlp->smk_rule = rule; 451 if (smlp != NULL) {
366 list_add_rcu(&smlp->list, &smack_rule_list); 452 smlp->smk_rule = rule;
367 } else 453 list_add_rcu(&smlp->list, &smack_rule_list);
368 rc = -ENOMEM; 454 } else
455 rc = -ENOMEM;
456 }
369 goto out; 457 goto out;
370 } 458 }
371 459
@@ -421,29 +509,18 @@ static void smk_seq_stop(struct seq_file *s, void *v)
421 /* No-op */ 509 /* No-op */
422} 510}
423 511
424/* 512static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
425 * Seq_file read operations for /smack/load
426 */
427
428static void *load_seq_start(struct seq_file *s, loff_t *pos)
429{
430 return smk_seq_start(s, pos, &smack_rule_list);
431}
432
433static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
434{ 513{
435 return smk_seq_next(s, v, pos, &smack_rule_list); 514 /*
436} 515 * Don't show any rules with label names too long for
437 516 * interface file (/smack/load or /smack/load2)
438static int load_seq_show(struct seq_file *s, void *v) 517 * because you should expect to be able to write
439{ 518 * anything you read back.
440 struct list_head *list = v; 519 */
441 struct smack_master_list *smlp = 520 if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max)
442 list_entry(list, struct smack_master_list, list); 521 return;
443 struct smack_rule *srp = smlp->smk_rule;
444 522
445 seq_printf(s, "%s %s", (char *)srp->smk_subject, 523 seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object);
446 (char *)srp->smk_object);
447 524
448 seq_putc(s, ' '); 525 seq_putc(s, ' ');
449 526
@@ -461,13 +538,36 @@ static int load_seq_show(struct seq_file *s, void *v)
461 seq_putc(s, '-'); 538 seq_putc(s, '-');
462 539
463 seq_putc(s, '\n'); 540 seq_putc(s, '\n');
541}
542
543/*
544 * Seq_file read operations for /smack/load
545 */
546
547static void *load2_seq_start(struct seq_file *s, loff_t *pos)
548{
549 return smk_seq_start(s, pos, &smack_rule_list);
550}
551
552static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos)
553{
554 return smk_seq_next(s, v, pos, &smack_rule_list);
555}
556
557static int load_seq_show(struct seq_file *s, void *v)
558{
559 struct list_head *list = v;
560 struct smack_master_list *smlp =
561 list_entry(list, struct smack_master_list, list);
562
563 smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN);
464 564
465 return 0; 565 return 0;
466} 566}
467 567
468static const struct seq_operations load_seq_ops = { 568static const struct seq_operations load_seq_ops = {
469 .start = load_seq_start, 569 .start = load2_seq_start,
470 .next = load_seq_next, 570 .next = load2_seq_next,
471 .show = load_seq_show, 571 .show = load_seq_show,
472 .stop = smk_seq_stop, 572 .stop = smk_seq_stop,
473}; 573};
@@ -504,7 +604,8 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
504 if (!capable(CAP_MAC_ADMIN)) 604 if (!capable(CAP_MAC_ADMIN))
505 return -EPERM; 605 return -EPERM;
506 606
507 return smk_write_load_list(file, buf, count, ppos, NULL, NULL); 607 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
608 SMK_FIXED24_FMT);
508} 609}
509 610
510static const struct file_operations smk_load_ops = { 611static const struct file_operations smk_load_ops = {
@@ -574,6 +675,8 @@ static void smk_unlbl_ambient(char *oldambient)
574 printk(KERN_WARNING "%s:%d remove rc = %d\n", 675 printk(KERN_WARNING "%s:%d remove rc = %d\n",
575 __func__, __LINE__, rc); 676 __func__, __LINE__, rc);
576 } 677 }
678 if (smack_net_ambient == NULL)
679 smack_net_ambient = smack_known_floor.smk_known;
577 680
578 rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET, 681 rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
579 NULL, NULL, &nai); 682 NULL, NULL, &nai);
@@ -605,27 +708,28 @@ static int cipso_seq_show(struct seq_file *s, void *v)
605 struct list_head *list = v; 708 struct list_head *list = v;
606 struct smack_known *skp = 709 struct smack_known *skp =
607 list_entry(list, struct smack_known, list); 710 list_entry(list, struct smack_known, list);
608 struct smack_cipso *scp = skp->smk_cipso; 711 struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
609 char *cbp;
610 char sep = '/'; 712 char sep = '/';
611 int cat = 1;
612 int i; 713 int i;
613 unsigned char m;
614 714
615 if (scp == NULL) 715 /*
716 * Don't show a label that could not have been set using
717 * /smack/cipso. This is in support of the notion that
718 * anything read from /smack/cipso ought to be writeable
719 * to /smack/cipso.
720 *
721 * /smack/cipso2 should be used instead.
722 */
723 if (strlen(skp->smk_known) >= SMK_LABELLEN)
616 return 0; 724 return 0;
617 725
618 seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level); 726 seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
619 727
620 cbp = scp->smk_catset; 728 for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
621 for (i = 0; i < SMK_LABELLEN; i++) 729 i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
622 for (m = 0x80; m != 0; m >>= 1) { 730 seq_printf(s, "%c%d", sep, i);
623 if (m & cbp[i]) { 731 sep = ',';
624 seq_printf(s, "%c%d", sep, cat); 732 }
625 sep = ',';
626 }
627 cat++;
628 }
629 733
630 seq_putc(s, '\n'); 734 seq_putc(s, '\n');
631 735
@@ -653,23 +757,24 @@ static int smk_open_cipso(struct inode *inode, struct file *file)
653} 757}
654 758
655/** 759/**
656 * smk_write_cipso - write() for /smack/cipso 760 * smk_set_cipso - do the work for write() for cipso and cipso2
657 * @file: file pointer, not actually used 761 * @file: file pointer, not actually used
658 * @buf: where to get the data from 762 * @buf: where to get the data from
659 * @count: bytes sent 763 * @count: bytes sent
660 * @ppos: where to start 764 * @ppos: where to start
765 * @format: /smack/cipso or /smack/cipso2
661 * 766 *
662 * Accepts only one cipso rule per write call. 767 * Accepts only one cipso rule per write call.
663 * Returns number of bytes written or error code, as appropriate 768 * Returns number of bytes written or error code, as appropriate
664 */ 769 */
665static ssize_t smk_write_cipso(struct file *file, const char __user *buf, 770static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
666 size_t count, loff_t *ppos) 771 size_t count, loff_t *ppos, int format)
667{ 772{
668 struct smack_known *skp; 773 struct smack_known *skp;
669 struct smack_cipso *scp = NULL; 774 struct netlbl_lsm_secattr ncats;
670 char mapcatset[SMK_LABELLEN]; 775 char mapcatset[SMK_CIPSOLEN];
671 int maplevel; 776 int maplevel;
672 int cat; 777 unsigned int cat;
673 int catlen; 778 int catlen;
674 ssize_t rc = -EINVAL; 779 ssize_t rc = -EINVAL;
675 char *data = NULL; 780 char *data = NULL;
@@ -686,7 +791,8 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
686 return -EPERM; 791 return -EPERM;
687 if (*ppos != 0) 792 if (*ppos != 0)
688 return -EINVAL; 793 return -EINVAL;
689 if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX) 794 if (format == SMK_FIXED24_FMT &&
795 (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX))
690 return -EINVAL; 796 return -EINVAL;
691 797
692 data = kzalloc(count + 1, GFP_KERNEL); 798 data = kzalloc(count + 1, GFP_KERNEL);
@@ -698,11 +804,6 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
698 goto unlockedout; 804 goto unlockedout;
699 } 805 }
700 806
701 /* labels cannot begin with a '-' */
702 if (data[0] == '-') {
703 rc = -EINVAL;
704 goto unlockedout;
705 }
706 data[count] = '\0'; 807 data[count] = '\0';
707 rule = data; 808 rule = data;
708 /* 809 /*
@@ -715,7 +816,11 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
715 if (skp == NULL) 816 if (skp == NULL)
716 goto out; 817 goto out;
717 818
718 rule += SMK_LABELLEN; 819 if (format == SMK_FIXED24_FMT)
820 rule += SMK_LABELLEN;
821 else
822 rule += strlen(skp->smk_known);
823
719 ret = sscanf(rule, "%d", &maplevel); 824 ret = sscanf(rule, "%d", &maplevel);
720 if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) 825 if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
721 goto out; 826 goto out;
@@ -725,41 +830,29 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
725 if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) 830 if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
726 goto out; 831 goto out;
727 832
728 if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) 833 if (format == SMK_FIXED24_FMT &&
834 count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
729 goto out; 835 goto out;
730 836
731 memset(mapcatset, 0, sizeof(mapcatset)); 837 memset(mapcatset, 0, sizeof(mapcatset));
732 838
733 for (i = 0; i < catlen; i++) { 839 for (i = 0; i < catlen; i++) {
734 rule += SMK_DIGITLEN; 840 rule += SMK_DIGITLEN;
735 ret = sscanf(rule, "%d", &cat); 841 ret = sscanf(rule, "%u", &cat);
736 if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) 842 if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL)
737 goto out; 843 goto out;
738 844
739 smack_catset_bit(cat, mapcatset); 845 smack_catset_bit(cat, mapcatset);
740 } 846 }
741 847
742 if (skp->smk_cipso == NULL) { 848 rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
743 scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL); 849 if (rc >= 0) {
744 if (scp == NULL) { 850 netlbl_secattr_catmap_free(skp->smk_netlabel.attr.mls.cat);
745 rc = -ENOMEM; 851 skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat;
746 goto out; 852 skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
747 } 853 rc = count;
748 } 854 }
749 855
750 spin_lock_bh(&skp->smk_cipsolock);
751
752 if (scp == NULL)
753 scp = skp->smk_cipso;
754 else
755 skp->smk_cipso = scp;
756
757 scp->smk_level = maplevel;
758 memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset));
759
760 spin_unlock_bh(&skp->smk_cipsolock);
761
762 rc = count;
763out: 856out:
764 mutex_unlock(&smack_cipso_lock); 857 mutex_unlock(&smack_cipso_lock);
765unlockedout: 858unlockedout:
@@ -767,6 +860,22 @@ unlockedout:
767 return rc; 860 return rc;
768} 861}
769 862
863/**
864 * smk_write_cipso - write() for /smack/cipso
865 * @file: file pointer, not actually used
866 * @buf: where to get the data from
867 * @count: bytes sent
868 * @ppos: where to start
869 *
870 * Accepts only one cipso rule per write call.
871 * Returns number of bytes written or error code, as appropriate
872 */
873static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
874 size_t count, loff_t *ppos)
875{
876 return smk_set_cipso(file, buf, count, ppos, SMK_FIXED24_FMT);
877}
878
770static const struct file_operations smk_cipso_ops = { 879static const struct file_operations smk_cipso_ops = {
771 .open = smk_open_cipso, 880 .open = smk_open_cipso,
772 .read = seq_read, 881 .read = seq_read,
@@ -776,6 +885,80 @@ static const struct file_operations smk_cipso_ops = {
776}; 885};
777 886
778/* 887/*
888 * Seq_file read operations for /smack/cipso2
889 */
890
891/*
892 * Print cipso labels in format:
893 * label level[/cat[,cat]]
894 */
895static int cipso2_seq_show(struct seq_file *s, void *v)
896{
897 struct list_head *list = v;
898 struct smack_known *skp =
899 list_entry(list, struct smack_known, list);
900 struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
901 char sep = '/';
902 int i;
903
904 seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
905
906 for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
907 i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
908 seq_printf(s, "%c%d", sep, i);
909 sep = ',';
910 }
911
912 seq_putc(s, '\n');
913
914 return 0;
915}
916
917static const struct seq_operations cipso2_seq_ops = {
918 .start = cipso_seq_start,
919 .next = cipso_seq_next,
920 .show = cipso2_seq_show,
921 .stop = smk_seq_stop,
922};
923
924/**
925 * smk_open_cipso2 - open() for /smack/cipso2
926 * @inode: inode structure representing file
927 * @file: "cipso2" file pointer
928 *
929 * Connect our cipso_seq_* operations with /smack/cipso2
930 * file_operations
931 */
932static int smk_open_cipso2(struct inode *inode, struct file *file)
933{
934 return seq_open(file, &cipso2_seq_ops);
935}
936
937/**
938 * smk_write_cipso2 - write() for /smack/cipso2
939 * @file: file pointer, not actually used
940 * @buf: where to get the data from
941 * @count: bytes sent
942 * @ppos: where to start
943 *
944 * Accepts only one cipso rule per write call.
945 * Returns number of bytes written or error code, as appropriate
946 */
947static ssize_t smk_write_cipso2(struct file *file, const char __user *buf,
948 size_t count, loff_t *ppos)
949{
950 return smk_set_cipso(file, buf, count, ppos, SMK_LONG_FMT);
951}
952
953static const struct file_operations smk_cipso2_ops = {
954 .open = smk_open_cipso2,
955 .read = seq_read,
956 .llseek = seq_lseek,
957 .write = smk_write_cipso2,
958 .release = seq_release,
959};
960
961/*
779 * Seq_file read operations for /smack/netlabel 962 * Seq_file read operations for /smack/netlabel
780 */ 963 */
781 964
@@ -887,9 +1070,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
887{ 1070{
888 struct smk_netlbladdr *skp; 1071 struct smk_netlbladdr *skp;
889 struct sockaddr_in newname; 1072 struct sockaddr_in newname;
890 char smack[SMK_LABELLEN]; 1073 char *smack;
891 char *sp; 1074 char *sp;
892 char data[SMK_NETLBLADDRMAX + 1]; 1075 char *data;
893 char *host = (char *)&newname.sin_addr.s_addr; 1076 char *host = (char *)&newname.sin_addr.s_addr;
894 int rc; 1077 int rc;
895 struct netlbl_audit audit_info; 1078 struct netlbl_audit audit_info;
@@ -911,10 +1094,23 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
911 return -EPERM; 1094 return -EPERM;
912 if (*ppos != 0) 1095 if (*ppos != 0)
913 return -EINVAL; 1096 return -EINVAL;
914 if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX) 1097 if (count < SMK_NETLBLADDRMIN)
915 return -EINVAL; 1098 return -EINVAL;
916 if (copy_from_user(data, buf, count) != 0) 1099
917 return -EFAULT; 1100 data = kzalloc(count + 1, GFP_KERNEL);
1101 if (data == NULL)
1102 return -ENOMEM;
1103
1104 if (copy_from_user(data, buf, count) != 0) {
1105 rc = -EFAULT;
1106 goto free_data_out;
1107 }
1108
1109 smack = kzalloc(count + 1, GFP_KERNEL);
1110 if (smack == NULL) {
1111 rc = -ENOMEM;
1112 goto free_data_out;
1113 }
918 1114
919 data[count] = '\0'; 1115 data[count] = '\0';
920 1116
@@ -923,24 +1119,34 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
923 if (rc != 6) { 1119 if (rc != 6) {
924 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", 1120 rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
925 &host[0], &host[1], &host[2], &host[3], smack); 1121 &host[0], &host[1], &host[2], &host[3], smack);
926 if (rc != 5) 1122 if (rc != 5) {
927 return -EINVAL; 1123 rc = -EINVAL;
1124 goto free_out;
1125 }
928 m = BEBITS; 1126 m = BEBITS;
929 } 1127 }
930 if (m > BEBITS) 1128 if (m > BEBITS) {
931 return -EINVAL; 1129 rc = -EINVAL;
1130 goto free_out;
1131 }
932 1132
933 /* if smack begins with '-', its an option, don't import it */ 1133 /*
1134 * If smack begins with '-', it is an option, don't import it
1135 */
934 if (smack[0] != '-') { 1136 if (smack[0] != '-') {
935 sp = smk_import(smack, 0); 1137 sp = smk_import(smack, 0);
936 if (sp == NULL) 1138 if (sp == NULL) {
937 return -EINVAL; 1139 rc = -EINVAL;
1140 goto free_out;
1141 }
938 } else { 1142 } else {
939 /* check known options */ 1143 /* check known options */
940 if (strcmp(smack, smack_cipso_option) == 0) 1144 if (strcmp(smack, smack_cipso_option) == 0)
941 sp = (char *)smack_cipso_option; 1145 sp = (char *)smack_cipso_option;
942 else 1146 else {
943 return -EINVAL; 1147 rc = -EINVAL;
1148 goto free_out;
1149 }
944 } 1150 }
945 1151
946 for (temp_mask = 0; m > 0; m--) { 1152 for (temp_mask = 0; m > 0; m--) {
@@ -1006,6 +1212,11 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
1006 1212
1007 mutex_unlock(&smk_netlbladdr_lock); 1213 mutex_unlock(&smk_netlbladdr_lock);
1008 1214
1215free_out:
1216 kfree(smack);
1217free_data_out:
1218 kfree(data);
1219
1009 return rc; 1220 return rc;
1010} 1221}
1011 1222
@@ -1119,6 +1330,7 @@ static ssize_t smk_read_direct(struct file *filp, char __user *buf,
1119static ssize_t smk_write_direct(struct file *file, const char __user *buf, 1330static ssize_t smk_write_direct(struct file *file, const char __user *buf,
1120 size_t count, loff_t *ppos) 1331 size_t count, loff_t *ppos)
1121{ 1332{
1333 struct smack_known *skp;
1122 char temp[80]; 1334 char temp[80];
1123 int i; 1335 int i;
1124 1336
@@ -1136,7 +1348,20 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf,
1136 if (sscanf(temp, "%d", &i) != 1) 1348 if (sscanf(temp, "%d", &i) != 1)
1137 return -EINVAL; 1349 return -EINVAL;
1138 1350
1139 smack_cipso_direct = i; 1351 /*
1352 * Don't do anything if the value hasn't actually changed.
1353 * If it is changing reset the level on entries that were
1354 * set up to be direct when they were created.
1355 */
1356 if (smack_cipso_direct != i) {
1357 mutex_lock(&smack_known_lock);
1358 list_for_each_entry_rcu(skp, &smack_known_list, list)
1359 if (skp->smk_netlabel.attr.mls.lvl ==
1360 smack_cipso_direct)
1361 skp->smk_netlabel.attr.mls.lvl = i;
1362 smack_cipso_direct = i;
1363 mutex_unlock(&smack_known_lock);
1364 }
1140 1365
1141 return count; 1366 return count;
1142} 1367}
@@ -1148,6 +1373,84 @@ static const struct file_operations smk_direct_ops = {
1148}; 1373};
1149 1374
1150/** 1375/**
1376 * smk_read_mapped - read() for /smack/mapped
1377 * @filp: file pointer, not actually used
1378 * @buf: where to put the result
1379 * @count: maximum to send along
1380 * @ppos: where to start
1381 *
1382 * Returns number of bytes read or error code, as appropriate
1383 */
1384static ssize_t smk_read_mapped(struct file *filp, char __user *buf,
1385 size_t count, loff_t *ppos)
1386{
1387 char temp[80];
1388 ssize_t rc;
1389
1390 if (*ppos != 0)
1391 return 0;
1392
1393 sprintf(temp, "%d", smack_cipso_mapped);
1394 rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1395
1396 return rc;
1397}
1398
1399/**
1400 * smk_write_mapped - write() for /smack/mapped
1401 * @file: file pointer, not actually used
1402 * @buf: where to get the data from
1403 * @count: bytes sent
1404 * @ppos: where to start
1405 *
1406 * Returns number of bytes written or error code, as appropriate
1407 */
1408static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
1409 size_t count, loff_t *ppos)
1410{
1411 struct smack_known *skp;
1412 char temp[80];
1413 int i;
1414
1415 if (!capable(CAP_MAC_ADMIN))
1416 return -EPERM;
1417
1418 if (count >= sizeof(temp) || count == 0)
1419 return -EINVAL;
1420
1421 if (copy_from_user(temp, buf, count) != 0)
1422 return -EFAULT;
1423
1424 temp[count] = '\0';
1425
1426 if (sscanf(temp, "%d", &i) != 1)
1427 return -EINVAL;
1428
1429 /*
1430 * Don't do anything if the value hasn't actually changed.
1431 * If it is changing reset the level on entries that were
1432 * set up to be mapped when they were created.
1433 */
1434 if (smack_cipso_mapped != i) {
1435 mutex_lock(&smack_known_lock);
1436 list_for_each_entry_rcu(skp, &smack_known_list, list)
1437 if (skp->smk_netlabel.attr.mls.lvl ==
1438 smack_cipso_mapped)
1439 skp->smk_netlabel.attr.mls.lvl = i;
1440 smack_cipso_mapped = i;
1441 mutex_unlock(&smack_known_lock);
1442 }
1443
1444 return count;
1445}
1446
1447static const struct file_operations smk_mapped_ops = {
1448 .read = smk_read_mapped,
1449 .write = smk_write_mapped,
1450 .llseek = default_llseek,
1451};
1452
1453/**
1151 * smk_read_ambient - read() for /smack/ambient 1454 * smk_read_ambient - read() for /smack/ambient
1152 * @filp: file pointer, not actually used 1455 * @filp: file pointer, not actually used
1153 * @buf: where to put the result 1456 * @buf: where to put the result
@@ -1195,22 +1498,28 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
1195static ssize_t smk_write_ambient(struct file *file, const char __user *buf, 1498static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1196 size_t count, loff_t *ppos) 1499 size_t count, loff_t *ppos)
1197{ 1500{
1198 char in[SMK_LABELLEN];
1199 char *oldambient; 1501 char *oldambient;
1200 char *smack; 1502 char *smack = NULL;
1503 char *data;
1504 int rc = count;
1201 1505
1202 if (!capable(CAP_MAC_ADMIN)) 1506 if (!capable(CAP_MAC_ADMIN))
1203 return -EPERM; 1507 return -EPERM;
1204 1508
1205 if (count >= SMK_LABELLEN) 1509 data = kzalloc(count + 1, GFP_KERNEL);
1206 return -EINVAL; 1510 if (data == NULL)
1511 return -ENOMEM;
1207 1512
1208 if (copy_from_user(in, buf, count) != 0) 1513 if (copy_from_user(data, buf, count) != 0) {
1209 return -EFAULT; 1514 rc = -EFAULT;
1515 goto out;
1516 }
1210 1517
1211 smack = smk_import(in, count); 1518 smack = smk_import(data, count);
1212 if (smack == NULL) 1519 if (smack == NULL) {
1213 return -EINVAL; 1520 rc = -EINVAL;
1521 goto out;
1522 }
1214 1523
1215 mutex_lock(&smack_ambient_lock); 1524 mutex_lock(&smack_ambient_lock);
1216 1525
@@ -1220,7 +1529,9 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1220 1529
1221 mutex_unlock(&smack_ambient_lock); 1530 mutex_unlock(&smack_ambient_lock);
1222 1531
1223 return count; 1532out:
1533 kfree(data);
1534 return rc;
1224} 1535}
1225 1536
1226static const struct file_operations smk_ambient_ops = { 1537static const struct file_operations smk_ambient_ops = {
@@ -1271,8 +1582,9 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
1271static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, 1582static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1272 size_t count, loff_t *ppos) 1583 size_t count, loff_t *ppos)
1273{ 1584{
1274 char in[SMK_LABELLEN]; 1585 char *data;
1275 char *sp = smk_of_task(current->cred->security); 1586 char *sp = smk_of_task(current->cred->security);
1587 int rc = count;
1276 1588
1277 if (!capable(CAP_MAC_ADMIN)) 1589 if (!capable(CAP_MAC_ADMIN))
1278 return -EPERM; 1590 return -EPERM;
@@ -1285,11 +1597,9 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1285 if (smack_onlycap != NULL && smack_onlycap != sp) 1597 if (smack_onlycap != NULL && smack_onlycap != sp)
1286 return -EPERM; 1598 return -EPERM;
1287 1599
1288 if (count >= SMK_LABELLEN) 1600 data = kzalloc(count, GFP_KERNEL);
1289 return -EINVAL; 1601 if (data == NULL)
1290 1602 return -ENOMEM;
1291 if (copy_from_user(in, buf, count) != 0)
1292 return -EFAULT;
1293 1603
1294 /* 1604 /*
1295 * Should the null string be passed in unset the onlycap value. 1605 * Should the null string be passed in unset the onlycap value.
@@ -1297,10 +1607,17 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1297 * smk_import only expects to return NULL for errors. It 1607 * smk_import only expects to return NULL for errors. It
1298 * is usually the case that a nullstring or "\n" would be 1608 * is usually the case that a nullstring or "\n" would be
1299 * bad to pass to smk_import but in fact this is useful here. 1609 * bad to pass to smk_import but in fact this is useful here.
1610 *
1611 * smk_import will also reject a label beginning with '-',
1612 * so "-usecapabilities" will also work.
1300 */ 1613 */
1301 smack_onlycap = smk_import(in, count); 1614 if (copy_from_user(data, buf, count) != 0)
1615 rc = -EFAULT;
1616 else
1617 smack_onlycap = smk_import(data, count);
1302 1618
1303 return count; 1619 kfree(data);
1620 return rc;
1304} 1621}
1305 1622
1306static const struct file_operations smk_onlycap_ops = { 1623static const struct file_operations smk_onlycap_ops = {
@@ -1398,25 +1715,7 @@ static int load_self_seq_show(struct seq_file *s, void *v)
1398 struct smack_rule *srp = 1715 struct smack_rule *srp =
1399 list_entry(list, struct smack_rule, list); 1716 list_entry(list, struct smack_rule, list);
1400 1717
1401 seq_printf(s, "%s %s", (char *)srp->smk_subject, 1718 smk_rule_show(s, srp, SMK_LABELLEN);
1402 (char *)srp->smk_object);
1403
1404 seq_putc(s, ' ');
1405
1406 if (srp->smk_access & MAY_READ)
1407 seq_putc(s, 'r');
1408 if (srp->smk_access & MAY_WRITE)
1409 seq_putc(s, 'w');
1410 if (srp->smk_access & MAY_EXEC)
1411 seq_putc(s, 'x');
1412 if (srp->smk_access & MAY_APPEND)
1413 seq_putc(s, 'a');
1414 if (srp->smk_access & MAY_TRANSMUTE)
1415 seq_putc(s, 't');
1416 if (srp->smk_access == 0)
1417 seq_putc(s, '-');
1418
1419 seq_putc(s, '\n');
1420 1719
1421 return 0; 1720 return 0;
1422} 1721}
@@ -1430,7 +1729,7 @@ static const struct seq_operations load_self_seq_ops = {
1430 1729
1431 1730
1432/** 1731/**
1433 * smk_open_load_self - open() for /smack/load-self 1732 * smk_open_load_self - open() for /smack/load-self2
1434 * @inode: inode structure representing file 1733 * @inode: inode structure representing file
1435 * @file: "load" file pointer 1734 * @file: "load" file pointer
1436 * 1735 *
@@ -1454,8 +1753,8 @@ static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
1454{ 1753{
1455 struct task_smack *tsp = current_security(); 1754 struct task_smack *tsp = current_security();
1456 1755
1457 return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules, 1756 return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
1458 &tsp->smk_rules_lock); 1757 &tsp->smk_rules_lock, SMK_FIXED24_FMT);
1459} 1758}
1460 1759
1461static const struct file_operations smk_load_self_ops = { 1760static const struct file_operations smk_load_self_ops = {
@@ -1467,24 +1766,42 @@ static const struct file_operations smk_load_self_ops = {
1467}; 1766};
1468 1767
1469/** 1768/**
1470 * smk_write_access - handle access check transaction 1769 * smk_user_access - handle access check transaction
1471 * @file: file pointer 1770 * @file: file pointer
1472 * @buf: data from user space 1771 * @buf: data from user space
1473 * @count: bytes sent 1772 * @count: bytes sent
1474 * @ppos: where to start - must be 0 1773 * @ppos: where to start - must be 0
1475 */ 1774 */
1476static ssize_t smk_write_access(struct file *file, const char __user *buf, 1775static ssize_t smk_user_access(struct file *file, const char __user *buf,
1477 size_t count, loff_t *ppos) 1776 size_t count, loff_t *ppos, int format)
1478{ 1777{
1479 struct smack_rule rule; 1778 struct smack_rule rule;
1480 char *data; 1779 char *data;
1780 char *cod;
1481 int res; 1781 int res;
1482 1782
1483 data = simple_transaction_get(file, buf, count); 1783 data = simple_transaction_get(file, buf, count);
1484 if (IS_ERR(data)) 1784 if (IS_ERR(data))
1485 return PTR_ERR(data); 1785 return PTR_ERR(data);
1486 1786
1487 if (count < SMK_LOADLEN || smk_parse_rule(data, &rule, 0)) 1787 if (format == SMK_FIXED24_FMT) {
1788 if (count < SMK_LOADLEN)
1789 return -EINVAL;
1790 res = smk_parse_rule(data, &rule, 0);
1791 } else {
1792 /*
1793 * Copy the data to make sure the string is terminated.
1794 */
1795 cod = kzalloc(count + 1, GFP_KERNEL);
1796 if (cod == NULL)
1797 return -ENOMEM;
1798 memcpy(cod, data, count);
1799 cod[count] = '\0';
1800 res = smk_parse_long_rule(cod, &rule, 0);
1801 kfree(cod);
1802 }
1803
1804 if (res)
1488 return -EINVAL; 1805 return -EINVAL;
1489 1806
1490 res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access, 1807 res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access,
@@ -1493,7 +1810,23 @@ static ssize_t smk_write_access(struct file *file, const char __user *buf,
1493 data[1] = '\0'; 1810 data[1] = '\0';
1494 1811
1495 simple_transaction_set(file, 2); 1812 simple_transaction_set(file, 2);
1496 return SMK_LOADLEN; 1813
1814 if (format == SMK_FIXED24_FMT)
1815 return SMK_LOADLEN;
1816 return count;
1817}
1818
1819/**
1820 * smk_write_access - handle access check transaction
1821 * @file: file pointer
1822 * @buf: data from user space
1823 * @count: bytes sent
1824 * @ppos: where to start - must be 0
1825 */
1826static ssize_t smk_write_access(struct file *file, const char __user *buf,
1827 size_t count, loff_t *ppos)
1828{
1829 return smk_user_access(file, buf, count, ppos, SMK_FIXED24_FMT);
1497} 1830}
1498 1831
1499static const struct file_operations smk_access_ops = { 1832static const struct file_operations smk_access_ops = {
@@ -1503,6 +1836,163 @@ static const struct file_operations smk_access_ops = {
1503 .llseek = generic_file_llseek, 1836 .llseek = generic_file_llseek,
1504}; 1837};
1505 1838
1839
1840/*
1841 * Seq_file read operations for /smack/load2
1842 */
1843
1844static int load2_seq_show(struct seq_file *s, void *v)
1845{
1846 struct list_head *list = v;
1847 struct smack_master_list *smlp =
1848 list_entry(list, struct smack_master_list, list);
1849
1850 smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL);
1851
1852 return 0;
1853}
1854
1855static const struct seq_operations load2_seq_ops = {
1856 .start = load2_seq_start,
1857 .next = load2_seq_next,
1858 .show = load2_seq_show,
1859 .stop = smk_seq_stop,
1860};
1861
1862/**
1863 * smk_open_load2 - open() for /smack/load2
1864 * @inode: inode structure representing file
1865 * @file: "load2" file pointer
1866 *
1867 * For reading, use load2_seq_* seq_file reading operations.
1868 */
1869static int smk_open_load2(struct inode *inode, struct file *file)
1870{
1871 return seq_open(file, &load2_seq_ops);
1872}
1873
1874/**
1875 * smk_write_load2 - write() for /smack/load2
1876 * @file: file pointer, not actually used
1877 * @buf: where to get the data from
1878 * @count: bytes sent
1879 * @ppos: where to start - must be 0
1880 *
1881 */
1882static ssize_t smk_write_load2(struct file *file, const char __user *buf,
1883 size_t count, loff_t *ppos)
1884{
1885 /*
1886 * Must have privilege.
1887 */
1888 if (!capable(CAP_MAC_ADMIN))
1889 return -EPERM;
1890
1891 return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
1892 SMK_LONG_FMT);
1893}
1894
1895static const struct file_operations smk_load2_ops = {
1896 .open = smk_open_load2,
1897 .read = seq_read,
1898 .llseek = seq_lseek,
1899 .write = smk_write_load2,
1900 .release = seq_release,
1901};
1902
1903/*
1904 * Seq_file read operations for /smack/load-self2
1905 */
1906
1907static void *load_self2_seq_start(struct seq_file *s, loff_t *pos)
1908{
1909 struct task_smack *tsp = current_security();
1910
1911 return smk_seq_start(s, pos, &tsp->smk_rules);
1912}
1913
1914static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos)
1915{
1916 struct task_smack *tsp = current_security();
1917
1918 return smk_seq_next(s, v, pos, &tsp->smk_rules);
1919}
1920
1921static int load_self2_seq_show(struct seq_file *s, void *v)
1922{
1923 struct list_head *list = v;
1924 struct smack_rule *srp =
1925 list_entry(list, struct smack_rule, list);
1926
1927 smk_rule_show(s, srp, SMK_LONGLABEL);
1928
1929 return 0;
1930}
1931
1932static const struct seq_operations load_self2_seq_ops = {
1933 .start = load_self2_seq_start,
1934 .next = load_self2_seq_next,
1935 .show = load_self2_seq_show,
1936 .stop = smk_seq_stop,
1937};
1938
1939/**
1940 * smk_open_load_self2 - open() for /smack/load-self2
1941 * @inode: inode structure representing file
1942 * @file: "load" file pointer
1943 *
1944 * For reading, use load_seq_* seq_file reading operations.
1945 */
1946static int smk_open_load_self2(struct inode *inode, struct file *file)
1947{
1948 return seq_open(file, &load_self2_seq_ops);
1949}
1950
1951/**
1952 * smk_write_load_self2 - write() for /smack/load-self2
1953 * @file: file pointer, not actually used
1954 * @buf: where to get the data from
1955 * @count: bytes sent
1956 * @ppos: where to start - must be 0
1957 *
1958 */
1959static ssize_t smk_write_load_self2(struct file *file, const char __user *buf,
1960 size_t count, loff_t *ppos)
1961{
1962 struct task_smack *tsp = current_security();
1963
1964 return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
1965 &tsp->smk_rules_lock, SMK_LONG_FMT);
1966}
1967
1968static const struct file_operations smk_load_self2_ops = {
1969 .open = smk_open_load_self2,
1970 .read = seq_read,
1971 .llseek = seq_lseek,
1972 .write = smk_write_load_self2,
1973 .release = seq_release,
1974};
1975
1976/**
1977 * smk_write_access2 - handle access check transaction
1978 * @file: file pointer
1979 * @buf: data from user space
1980 * @count: bytes sent
1981 * @ppos: where to start - must be 0
1982 */
1983static ssize_t smk_write_access2(struct file *file, const char __user *buf,
1984 size_t count, loff_t *ppos)
1985{
1986 return smk_user_access(file, buf, count, ppos, SMK_LONG_FMT);
1987}
1988
1989static const struct file_operations smk_access2_ops = {
1990 .write = smk_write_access2,
1991 .read = simple_transaction_read,
1992 .release = simple_transaction_release,
1993 .llseek = generic_file_llseek,
1994};
1995
1506/** 1996/**
1507 * smk_fill_super - fill the /smackfs superblock 1997 * smk_fill_super - fill the /smackfs superblock
1508 * @sb: the empty superblock 1998 * @sb: the empty superblock
@@ -1539,6 +2029,16 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
1539 "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO}, 2029 "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
1540 [SMK_ACCESSES] = { 2030 [SMK_ACCESSES] = {
1541 "access", &smk_access_ops, S_IRUGO|S_IWUGO}, 2031 "access", &smk_access_ops, S_IRUGO|S_IWUGO},
2032 [SMK_MAPPED] = {
2033 "mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR},
2034 [SMK_LOAD2] = {
2035 "load2", &smk_load2_ops, S_IRUGO|S_IWUSR},
2036 [SMK_LOAD_SELF2] = {
2037 "load-self2", &smk_load_self2_ops, S_IRUGO|S_IWUGO},
2038 [SMK_ACCESS2] = {
2039 "access2", &smk_access2_ops, S_IRUGO|S_IWUGO},
2040 [SMK_CIPSO2] = {
2041 "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR},
1542 /* last one */ 2042 /* last one */
1543 {""} 2043 {""}
1544 }; 2044 };
@@ -1581,6 +2081,15 @@ static struct file_system_type smk_fs_type = {
1581 2081
1582static struct vfsmount *smackfs_mount; 2082static struct vfsmount *smackfs_mount;
1583 2083
2084static int __init smk_preset_netlabel(struct smack_known *skp)
2085{
2086 skp->smk_netlabel.domain = skp->smk_known;
2087 skp->smk_netlabel.flags =
2088 NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
2089 return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
2090 &skp->smk_netlabel, strlen(skp->smk_known));
2091}
2092
1584/** 2093/**
1585 * init_smk_fs - get the smackfs superblock 2094 * init_smk_fs - get the smackfs superblock
1586 * 2095 *
@@ -1597,6 +2106,7 @@ static struct vfsmount *smackfs_mount;
1597static int __init init_smk_fs(void) 2106static int __init init_smk_fs(void)
1598{ 2107{
1599 int err; 2108 int err;
2109 int rc;
1600 2110
1601 if (!security_module_enable(&smack_ops)) 2111 if (!security_module_enable(&smack_ops))
1602 return 0; 2112 return 0;
@@ -1614,6 +2124,25 @@ static int __init init_smk_fs(void)
1614 smk_cipso_doi(); 2124 smk_cipso_doi();
1615 smk_unlbl_ambient(NULL); 2125 smk_unlbl_ambient(NULL);
1616 2126
2127 rc = smk_preset_netlabel(&smack_known_floor);
2128 if (err == 0 && rc < 0)
2129 err = rc;
2130 rc = smk_preset_netlabel(&smack_known_hat);
2131 if (err == 0 && rc < 0)
2132 err = rc;
2133 rc = smk_preset_netlabel(&smack_known_huh);
2134 if (err == 0 && rc < 0)
2135 err = rc;
2136 rc = smk_preset_netlabel(&smack_known_invalid);
2137 if (err == 0 && rc < 0)
2138 err = rc;
2139 rc = smk_preset_netlabel(&smack_known_star);
2140 if (err == 0 && rc < 0)
2141 err = rc;
2142 rc = smk_preset_netlabel(&smack_known_web);
2143 if (err == 0 && rc < 0)
2144 err = rc;
2145
1617 return err; 2146 return err;
1618} 2147}
1619 2148