aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smackfs.c
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/smackfs.c
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/smackfs.c')
-rw-r--r--security/smack/smackfs.c993
1 files changed, 761 insertions, 232 deletions
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 038811cb7e62..1810c9a4ed48 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