Commit ac8cc0fa5395fe2278e305a4cbed48e90d88d878

Authored by James Morris

Merge branch 'next' into for-linus

Showing 26 changed files Side-by-side Diff

Documentation/feature-removal-schedule.txt
... ... @@ -315,4 +315,16 @@
315 315 Why: Deprecated by the new (standard) device driver binding model. Use
316 316 i2c_driver->probe() and ->remove() instead.
317 317 Who: Jean Delvare <khali@linux-fr.org>
  318 +
  319 +---------------------------
  320 +
  321 +What: SELinux "compat_net" functionality
  322 +When: 2.6.30 at the earliest
  323 +Why: In 2.6.18 the Secmark concept was introduced to replace the "compat_net"
  324 + network access control functionality of SELinux. Secmark offers both
  325 + better performance and greater flexibility than the "compat_net"
  326 + mechanism. Now that the major Linux distributions have moved to
  327 + Secmark, it is time to deprecate the older mechanism and start the
  328 + process of removing the old code.
  329 +Who: Paul Moore <paul.moore@hp.com>
include/linux/capability.h
... ... @@ -529,8 +529,21 @@
529 529 *
530 530 * Note that this does not set PF_SUPERPRIV on the task.
531 531 */
532   -#define has_capability(t, cap) (security_capable((t), (cap)) == 0)
533   -#define has_capability_noaudit(t, cap) (security_capable_noaudit((t), (cap)) == 0)
  532 +#define has_capability(t, cap) (security_real_capable((t), (cap)) == 0)
  533 +
  534 +/**
  535 + * has_capability_noaudit - Determine if a task has a superior capability available (unaudited)
  536 + * @t: The task in question
  537 + * @cap: The capability to be tested for
  538 + *
  539 + * Return true if the specified task has the given superior capability
  540 + * currently in effect, false if not, but don't write an audit message for the
  541 + * check.
  542 + *
  543 + * Note that this does not set PF_SUPERPRIV on the task.
  544 + */
  545 +#define has_capability_noaudit(t, cap) \
  546 + (security_real_capable_noaudit((t), (cap)) == 0)
534 547  
535 548 extern int capable(int cap);
536 549  
include/linux/security.h
... ... @@ -48,7 +48,8 @@
48 48 * These functions are in security/capability.c and are used
49 49 * as the default capabilities functions
50 50 */
51   -extern int cap_capable(struct task_struct *tsk, int cap, int audit);
  51 +extern int cap_capable(struct task_struct *tsk, const struct cred *cred,
  52 + int cap, int audit);
52 53 extern int cap_settime(struct timespec *ts, struct timezone *tz);
53 54 extern int cap_ptrace_may_access(struct task_struct *child, unsigned int mode);
54 55 extern int cap_ptrace_traceme(struct task_struct *parent);
55 56  
56 57  
... ... @@ -1251,9 +1252,12 @@
1251 1252 * @permitted contains the permitted capability set.
1252 1253 * Return 0 and update @new if permission is granted.
1253 1254 * @capable:
1254   - * Check whether the @tsk process has the @cap capability.
  1255 + * Check whether the @tsk process has the @cap capability in the indicated
  1256 + * credentials.
1255 1257 * @tsk contains the task_struct for the process.
  1258 + * @cred contains the credentials to use.
1256 1259 * @cap contains the capability <include/linux/capability.h>.
  1260 + * @audit: Whether to write an audit message or not
1257 1261 * Return 0 if the capability is granted for @tsk.
1258 1262 * @acct:
1259 1263 * Check permission before enabling or disabling process accounting. If
... ... @@ -1346,7 +1350,8 @@
1346 1350 const kernel_cap_t *effective,
1347 1351 const kernel_cap_t *inheritable,
1348 1352 const kernel_cap_t *permitted);
1349   - int (*capable) (struct task_struct *tsk, int cap, int audit);
  1353 + int (*capable) (struct task_struct *tsk, const struct cred *cred,
  1354 + int cap, int audit);
1350 1355 int (*acct) (struct file *file);
1351 1356 int (*sysctl) (struct ctl_table *table, int op);
1352 1357 int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
... ... @@ -1628,8 +1633,9 @@
1628 1633 const kernel_cap_t *effective,
1629 1634 const kernel_cap_t *inheritable,
1630 1635 const kernel_cap_t *permitted);
1631   -int security_capable(struct task_struct *tsk, int cap);
1632   -int security_capable_noaudit(struct task_struct *tsk, int cap);
  1636 +int security_capable(int cap);
  1637 +int security_real_capable(struct task_struct *tsk, int cap);
  1638 +int security_real_capable_noaudit(struct task_struct *tsk, int cap);
1633 1639 int security_acct(struct file *file);
1634 1640 int security_sysctl(struct ctl_table *table, int op);
1635 1641 int security_quotactl(int cmds, int type, int id, struct super_block *sb);
1636 1642  
1637 1643  
1638 1644  
... ... @@ -1826,14 +1832,31 @@
1826 1832 return cap_capset(new, old, effective, inheritable, permitted);
1827 1833 }
1828 1834  
1829   -static inline int security_capable(struct task_struct *tsk, int cap)
  1835 +static inline int security_capable(int cap)
1830 1836 {
1831   - return cap_capable(tsk, cap, SECURITY_CAP_AUDIT);
  1837 + return cap_capable(current, current_cred(), cap, SECURITY_CAP_AUDIT);
1832 1838 }
1833 1839  
1834   -static inline int security_capable_noaudit(struct task_struct *tsk, int cap)
  1840 +static inline int security_real_capable(struct task_struct *tsk, int cap)
1835 1841 {
1836   - return cap_capable(tsk, cap, SECURITY_CAP_NOAUDIT);
  1842 + int ret;
  1843 +
  1844 + rcu_read_lock();
  1845 + ret = cap_capable(tsk, __task_cred(tsk), cap, SECURITY_CAP_AUDIT);
  1846 + rcu_read_unlock();
  1847 + return ret;
  1848 +}
  1849 +
  1850 +static inline
  1851 +int security_real_capable_noaudit(struct task_struct *tsk, int cap)
  1852 +{
  1853 + int ret;
  1854 +
  1855 + rcu_read_lock();
  1856 + ret = cap_capable(tsk, __task_cred(tsk), cap,
  1857 + SECURITY_CAP_NOAUDIT);
  1858 + rcu_read_unlock();
  1859 + return ret;
1837 1860 }
1838 1861  
1839 1862 static inline int security_acct(struct file *file)
include/net/cipso_ipv4.h
... ... @@ -131,7 +131,8 @@
131 131 */
132 132  
133 133 #ifdef CONFIG_NETLABEL
134   -int cipso_v4_doi_add(struct cipso_v4_doi *doi_def);
  134 +int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
  135 + struct netlbl_audit *audit_info);
135 136 void cipso_v4_doi_free(struct cipso_v4_doi *doi_def);
136 137 int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info);
137 138 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
... ... @@ -140,7 +141,8 @@
140 141 int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
141 142 void *cb_arg);
142 143 #else
143   -static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
  144 +static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
  145 + struct netlbl_audit *audit_info)
144 146 {
145 147 return -ENOSYS;
146 148 }
include/net/netlabel.h
... ... @@ -33,6 +33,8 @@
33 33 #include <linux/types.h>
34 34 #include <linux/net.h>
35 35 #include <linux/skbuff.h>
  36 +#include <linux/in.h>
  37 +#include <linux/in6.h>
36 38 #include <net/netlink.h>
37 39 #include <asm/atomic.h>
38 40  
39 41  
40 42  
41 43  
... ... @@ -353,13 +355,37 @@
353 355 /*
354 356 * LSM configuration operations
355 357 */
356   -int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info);
357   -int netlbl_cfg_unlbl_add_map(const char *domain,
  358 +int netlbl_cfg_map_del(const char *domain,
  359 + u16 family,
  360 + const void *addr,
  361 + const void *mask,
  362 + struct netlbl_audit *audit_info);
  363 +int netlbl_cfg_unlbl_map_add(const char *domain,
  364 + u16 family,
  365 + const void *addr,
  366 + const void *mask,
358 367 struct netlbl_audit *audit_info);
359   -int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
  368 +int netlbl_cfg_unlbl_static_add(struct net *net,
  369 + const char *dev_name,
  370 + const void *addr,
  371 + const void *mask,
  372 + u16 family,
  373 + u32 secid,
  374 + struct netlbl_audit *audit_info);
  375 +int netlbl_cfg_unlbl_static_del(struct net *net,
  376 + const char *dev_name,
  377 + const void *addr,
  378 + const void *mask,
  379 + u16 family,
  380 + struct netlbl_audit *audit_info);
  381 +int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
  382 + struct netlbl_audit *audit_info);
  383 +void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info);
  384 +int netlbl_cfg_cipsov4_map_add(u32 doi,
360 385 const char *domain,
  386 + const struct in_addr *addr,
  387 + const struct in_addr *mask,
361 388 struct netlbl_audit *audit_info);
362   -
363 389 /*
364 390 * LSM security attribute operations
365 391 */
366 392  
367 393  
368 394  
369 395  
... ... @@ -401,19 +427,62 @@
401 427 void netlbl_cache_invalidate(void);
402 428 int netlbl_cache_add(const struct sk_buff *skb,
403 429 const struct netlbl_lsm_secattr *secattr);
  430 +
  431 +/*
  432 + * Protocol engine operations
  433 + */
  434 +struct audit_buffer *netlbl_audit_start(int type,
  435 + struct netlbl_audit *audit_info);
404 436 #else
405 437 static inline int netlbl_cfg_map_del(const char *domain,
  438 + u16 family,
  439 + const void *addr,
  440 + const void *mask,
406 441 struct netlbl_audit *audit_info)
407 442 {
408 443 return -ENOSYS;
409 444 }
410   -static inline int netlbl_cfg_unlbl_add_map(const char *domain,
  445 +static inline int netlbl_cfg_unlbl_map_add(const char *domain,
  446 + u16 family,
  447 + void *addr,
  448 + void *mask,
411 449 struct netlbl_audit *audit_info)
412 450 {
413 451 return -ENOSYS;
414 452 }
415   -static inline int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
  453 +static inline int netlbl_cfg_unlbl_static_add(struct net *net,
  454 + const char *dev_name,
  455 + const void *addr,
  456 + const void *mask,
  457 + u16 family,
  458 + u32 secid,
  459 + struct netlbl_audit *audit_info)
  460 +{
  461 + return -ENOSYS;
  462 +}
  463 +static inline int netlbl_cfg_unlbl_static_del(struct net *net,
  464 + const char *dev_name,
  465 + const void *addr,
  466 + const void *mask,
  467 + u16 family,
  468 + struct netlbl_audit *audit_info)
  469 +{
  470 + return -ENOSYS;
  471 +}
  472 +static inline int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
  473 + struct netlbl_audit *audit_info)
  474 +{
  475 + return -ENOSYS;
  476 +}
  477 +static inline void netlbl_cfg_cipsov4_del(u32 doi,
  478 + struct netlbl_audit *audit_info)
  479 +{
  480 + return;
  481 +}
  482 +static inline int netlbl_cfg_cipsov4_map_add(u32 doi,
416 483 const char *domain,
  484 + const struct in_addr *addr,
  485 + const struct in_addr *mask,
417 486 struct netlbl_audit *audit_info)
418 487 {
419 488 return -ENOSYS;
... ... @@ -494,6 +563,11 @@
494 563 const struct netlbl_lsm_secattr *secattr)
495 564 {
496 565 return 0;
  566 +}
  567 +static inline struct audit_buffer *netlbl_audit_start(int type,
  568 + struct netlbl_audit *audit_info)
  569 +{
  570 + return NULL;
497 571 }
498 572 #endif /* CONFIG_NETLABEL */
499 573  
... ... @@ -306,7 +306,7 @@
306 306 BUG();
307 307 }
308 308  
309   - if (has_capability(current, cap)) {
  309 + if (security_capable(cap) == 0) {
310 310 current->flags |= PF_SUPERPRIV;
311 311 return 1;
312 312 }
net/ipv4/cipso_ipv4.c
... ... @@ -38,6 +38,7 @@
38 38 #include <linux/spinlock.h>
39 39 #include <linux/string.h>
40 40 #include <linux/jhash.h>
  41 +#include <linux/audit.h>
41 42 #include <net/ip.h>
42 43 #include <net/icmp.h>
43 44 #include <net/tcp.h>
... ... @@ -449,6 +450,7 @@
449 450 /**
450 451 * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine
451 452 * @doi_def: the DOI structure
  453 + * @audit_info: NetLabel audit information
452 454 *
453 455 * Description:
454 456 * The caller defines a new DOI for use by the CIPSO engine and calls this
455 457  
456 458  
457 459  
458 460  
459 461  
460 462  
461 463  
462 464  
463 465  
464 466  
465 467  
466 468  
467 469  
... ... @@ -458,50 +460,78 @@
458 460 * zero on success and non-zero on failure.
459 461 *
460 462 */
461   -int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
  463 +int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
  464 + struct netlbl_audit *audit_info)
462 465 {
  466 + int ret_val = -EINVAL;
463 467 u32 iter;
  468 + u32 doi;
  469 + u32 doi_type;
  470 + struct audit_buffer *audit_buf;
464 471  
  472 + doi = doi_def->doi;
  473 + doi_type = doi_def->type;
  474 +
465 475 if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
466   - return -EINVAL;
  476 + goto doi_add_return;
467 477 for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {
468 478 switch (doi_def->tags[iter]) {
469 479 case CIPSO_V4_TAG_RBITMAP:
470 480 break;
471 481 case CIPSO_V4_TAG_RANGE:
472   - if (doi_def->type != CIPSO_V4_MAP_PASS)
473   - return -EINVAL;
474   - break;
475   - case CIPSO_V4_TAG_INVALID:
476   - if (iter == 0)
477   - return -EINVAL;
478   - break;
479 482 case CIPSO_V4_TAG_ENUM:
480 483 if (doi_def->type != CIPSO_V4_MAP_PASS)
481   - return -EINVAL;
  484 + goto doi_add_return;
482 485 break;
483 486 case CIPSO_V4_TAG_LOCAL:
484 487 if (doi_def->type != CIPSO_V4_MAP_LOCAL)
485   - return -EINVAL;
  488 + goto doi_add_return;
486 489 break;
  490 + case CIPSO_V4_TAG_INVALID:
  491 + if (iter == 0)
  492 + goto doi_add_return;
  493 + break;
487 494 default:
488   - return -EINVAL;
  495 + goto doi_add_return;
489 496 }
490 497 }
491 498  
492 499 atomic_set(&doi_def->refcount, 1);
493 500  
494 501 spin_lock(&cipso_v4_doi_list_lock);
495   - if (cipso_v4_doi_search(doi_def->doi) != NULL)
496   - goto doi_add_failure;
  502 + if (cipso_v4_doi_search(doi_def->doi) != NULL) {
  503 + spin_unlock(&cipso_v4_doi_list_lock);
  504 + ret_val = -EEXIST;
  505 + goto doi_add_return;
  506 + }
497 507 list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
498 508 spin_unlock(&cipso_v4_doi_list_lock);
  509 + ret_val = 0;
499 510  
500   - return 0;
  511 +doi_add_return:
  512 + audit_buf = netlbl_audit_start(AUDIT_MAC_CIPSOV4_ADD, audit_info);
  513 + if (audit_buf != NULL) {
  514 + const char *type_str;
  515 + switch (doi_type) {
  516 + case CIPSO_V4_MAP_TRANS:
  517 + type_str = "trans";
  518 + break;
  519 + case CIPSO_V4_MAP_PASS:
  520 + type_str = "pass";
  521 + break;
  522 + case CIPSO_V4_MAP_LOCAL:
  523 + type_str = "local";
  524 + break;
  525 + default:
  526 + type_str = "(unknown)";
  527 + }
  528 + audit_log_format(audit_buf,
  529 + " cipso_doi=%u cipso_type=%s res=%u",
  530 + doi, type_str, ret_val == 0 ? 1 : 0);
  531 + audit_log_end(audit_buf);
  532 + }
501 533  
502   -doi_add_failure:
503   - spin_unlock(&cipso_v4_doi_list_lock);
504   - return -EEXIST;
  534 + return ret_val;
505 535 }
506 536  
507 537 /**
508 538  
509 539  
510 540  
511 541  
512 542  
... ... @@ -559,25 +589,39 @@
559 589 */
560 590 int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info)
561 591 {
  592 + int ret_val;
562 593 struct cipso_v4_doi *doi_def;
  594 + struct audit_buffer *audit_buf;
563 595  
564 596 spin_lock(&cipso_v4_doi_list_lock);
565 597 doi_def = cipso_v4_doi_search(doi);
566 598 if (doi_def == NULL) {
567 599 spin_unlock(&cipso_v4_doi_list_lock);
568   - return -ENOENT;
  600 + ret_val = -ENOENT;
  601 + goto doi_remove_return;
569 602 }
570 603 if (!atomic_dec_and_test(&doi_def->refcount)) {
571 604 spin_unlock(&cipso_v4_doi_list_lock);
572   - return -EBUSY;
  605 + ret_val = -EBUSY;
  606 + goto doi_remove_return;
573 607 }
574 608 list_del_rcu(&doi_def->list);
575 609 spin_unlock(&cipso_v4_doi_list_lock);
576 610  
577 611 cipso_v4_cache_invalidate();
578 612 call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu);
  613 + ret_val = 0;
579 614  
580   - return 0;
  615 +doi_remove_return:
  616 + audit_buf = netlbl_audit_start(AUDIT_MAC_CIPSOV4_DEL, audit_info);
  617 + if (audit_buf != NULL) {
  618 + audit_log_format(audit_buf,
  619 + " cipso_doi=%u res=%u",
  620 + doi, ret_val == 0 ? 1 : 0);
  621 + audit_log_end(audit_buf);
  622 + }
  623 +
  624 + return ret_val;
581 625 }
582 626  
583 627 /**
net/netlabel/netlabel_cipso_v4.c
... ... @@ -130,6 +130,7 @@
130 130 /**
131 131 * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
132 132 * @info: the Generic NETLINK info block
  133 + * @audit_info: NetLabel audit information
133 134 *
134 135 * Description:
135 136 * Create a new CIPSO_V4_MAP_TRANS DOI definition based on the given ADD
... ... @@ -137,7 +138,8 @@
137 138 * non-zero on error.
138 139 *
139 140 */
140   -static int netlbl_cipsov4_add_std(struct genl_info *info)
  141 +static int netlbl_cipsov4_add_std(struct genl_info *info,
  142 + struct netlbl_audit *audit_info)
141 143 {
142 144 int ret_val = -EINVAL;
143 145 struct cipso_v4_doi *doi_def = NULL;
... ... @@ -316,7 +318,7 @@
316 318 }
317 319 }
318 320  
319   - ret_val = cipso_v4_doi_add(doi_def);
  321 + ret_val = cipso_v4_doi_add(doi_def, audit_info);
320 322 if (ret_val != 0)
321 323 goto add_std_failure;
322 324 return 0;
... ... @@ -330,6 +332,7 @@
330 332 /**
331 333 * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
332 334 * @info: the Generic NETLINK info block
  335 + * @audit_info: NetLabel audit information
333 336 *
334 337 * Description:
335 338 * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
... ... @@ -337,7 +340,8 @@
337 340 * error.
338 341 *
339 342 */
340   -static int netlbl_cipsov4_add_pass(struct genl_info *info)
  343 +static int netlbl_cipsov4_add_pass(struct genl_info *info,
  344 + struct netlbl_audit *audit_info)
341 345 {
342 346 int ret_val;
343 347 struct cipso_v4_doi *doi_def = NULL;
... ... @@ -354,7 +358,7 @@
354 358 if (ret_val != 0)
355 359 goto add_pass_failure;
356 360  
357   - ret_val = cipso_v4_doi_add(doi_def);
  361 + ret_val = cipso_v4_doi_add(doi_def, audit_info);
358 362 if (ret_val != 0)
359 363 goto add_pass_failure;
360 364 return 0;
... ... @@ -367,6 +371,7 @@
367 371 /**
368 372 * netlbl_cipsov4_add_local - Adds a CIPSO V4 DOI definition
369 373 * @info: the Generic NETLINK info block
  374 + * @audit_info: NetLabel audit information
370 375 *
371 376 * Description:
372 377 * Create a new CIPSO_V4_MAP_LOCAL DOI definition based on the given ADD
... ... @@ -374,7 +379,8 @@
374 379 * non-zero on error.
375 380 *
376 381 */
377   -static int netlbl_cipsov4_add_local(struct genl_info *info)
  382 +static int netlbl_cipsov4_add_local(struct genl_info *info,
  383 + struct netlbl_audit *audit_info)
378 384 {
379 385 int ret_val;
380 386 struct cipso_v4_doi *doi_def = NULL;
... ... @@ -391,7 +397,7 @@
391 397 if (ret_val != 0)
392 398 goto add_local_failure;
393 399  
394   - ret_val = cipso_v4_doi_add(doi_def);
  400 + ret_val = cipso_v4_doi_add(doi_def, audit_info);
395 401 if (ret_val != 0)
396 402 goto add_local_failure;
397 403 return 0;
398 404  
399 405  
400 406  
401 407  
402 408  
403 409  
404 410  
... ... @@ -415,48 +421,31 @@
415 421  
416 422 {
417 423 int ret_val = -EINVAL;
418   - u32 type;
419   - u32 doi;
420 424 const char *type_str = "(unknown)";
421   - struct audit_buffer *audit_buf;
422 425 struct netlbl_audit audit_info;
423 426  
424 427 if (!info->attrs[NLBL_CIPSOV4_A_DOI] ||
425 428 !info->attrs[NLBL_CIPSOV4_A_MTYPE])
426 429 return -EINVAL;
427 430  
428   - doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
429 431 netlbl_netlink_auditinfo(skb, &audit_info);
430   -
431   - type = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE]);
432   - switch (type) {
  432 + switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) {
433 433 case CIPSO_V4_MAP_TRANS:
434 434 type_str = "trans";
435   - ret_val = netlbl_cipsov4_add_std(info);
  435 + ret_val = netlbl_cipsov4_add_std(info, &audit_info);
436 436 break;
437 437 case CIPSO_V4_MAP_PASS:
438 438 type_str = "pass";
439   - ret_val = netlbl_cipsov4_add_pass(info);
  439 + ret_val = netlbl_cipsov4_add_pass(info, &audit_info);
440 440 break;
441 441 case CIPSO_V4_MAP_LOCAL:
442 442 type_str = "local";
443   - ret_val = netlbl_cipsov4_add_local(info);
  443 + ret_val = netlbl_cipsov4_add_local(info, &audit_info);
444 444 break;
445 445 }
446 446 if (ret_val == 0)
447 447 atomic_inc(&netlabel_mgmt_protocount);
448 448  
449   - audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
450   - &audit_info);
451   - if (audit_buf != NULL) {
452   - audit_log_format(audit_buf,
453   - " cipso_doi=%u cipso_type=%s res=%u",
454   - doi,
455   - type_str,
456   - ret_val == 0 ? 1 : 0);
457   - audit_log_end(audit_buf);
458   - }
459   -
460 449 return ret_val;
461 450 }
462 451  
463 452  
... ... @@ -725,9 +714,7 @@
725 714 static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
726 715 {
727 716 int ret_val = -EINVAL;
728   - u32 doi = 0;
729 717 struct netlbl_domhsh_walk_arg cb_arg;
730   - struct audit_buffer *audit_buf;
731 718 struct netlbl_audit audit_info;
732 719 u32 skip_bkt = 0;
733 720 u32 skip_chain = 0;
734 721  
735 722  
736 723  
... ... @@ -735,27 +722,15 @@
735 722 if (!info->attrs[NLBL_CIPSOV4_A_DOI])
736 723 return -EINVAL;
737 724  
738   - doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
739 725 netlbl_netlink_auditinfo(skb, &audit_info);
740   -
741   - cb_arg.doi = doi;
  726 + cb_arg.doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
742 727 cb_arg.audit_info = &audit_info;
743 728 ret_val = netlbl_domhsh_walk(&skip_bkt, &skip_chain,
744 729 netlbl_cipsov4_remove_cb, &cb_arg);
745 730 if (ret_val == 0 || ret_val == -ENOENT) {
746   - ret_val = cipso_v4_doi_remove(doi, &audit_info);
  731 + ret_val = cipso_v4_doi_remove(cb_arg.doi, &audit_info);
747 732 if (ret_val == 0)
748 733 atomic_dec(&netlabel_mgmt_protocount);
749   - }
750   -
751   - audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,
752   - &audit_info);
753   - if (audit_buf != NULL) {
754   - audit_log_format(audit_buf,
755   - " cipso_doi=%u res=%u",
756   - doi,
757   - ret_val == 0 ? 1 : 0);
758   - audit_log_end(audit_buf);
759 734 }
760 735  
761 736 return ret_val;
net/netlabel/netlabel_domainhash.c
... ... @@ -483,6 +483,73 @@
483 483 }
484 484  
485 485 /**
  486 + * netlbl_domhsh_remove_af4 - Removes an address selector entry
  487 + * @domain: the domain
  488 + * @addr: IPv4 address
  489 + * @mask: IPv4 address mask
  490 + * @audit_info: NetLabel audit information
  491 + *
  492 + * Description:
  493 + * Removes an individual address selector from a domain mapping and potentially
  494 + * the entire mapping if it is empty. Returns zero on success, negative values
  495 + * on failure.
  496 + *
  497 + */
  498 +int netlbl_domhsh_remove_af4(const char *domain,
  499 + const struct in_addr *addr,
  500 + const struct in_addr *mask,
  501 + struct netlbl_audit *audit_info)
  502 +{
  503 + struct netlbl_dom_map *entry_map;
  504 + struct netlbl_af4list *entry_addr;
  505 + struct netlbl_af4list *iter4;
  506 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  507 + struct netlbl_af6list *iter6;
  508 +#endif /* IPv6 */
  509 + struct netlbl_domaddr4_map *entry;
  510 +
  511 + rcu_read_lock();
  512 +
  513 + if (domain)
  514 + entry_map = netlbl_domhsh_search(domain);
  515 + else
  516 + entry_map = netlbl_domhsh_search_def(domain);
  517 + if (entry_map == NULL || entry_map->type != NETLBL_NLTYPE_ADDRSELECT)
  518 + goto remove_af4_failure;
  519 +
  520 + spin_lock(&netlbl_domhsh_lock);
  521 + entry_addr = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
  522 + &entry_map->type_def.addrsel->list4);
  523 + spin_unlock(&netlbl_domhsh_lock);
  524 +
  525 + if (entry_addr == NULL)
  526 + goto remove_af4_failure;
  527 + netlbl_af4list_foreach_rcu(iter4, &entry_map->type_def.addrsel->list4)
  528 + goto remove_af4_single_addr;
  529 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  530 + netlbl_af6list_foreach_rcu(iter6, &entry_map->type_def.addrsel->list6)
  531 + goto remove_af4_single_addr;
  532 +#endif /* IPv6 */
  533 + /* the domain mapping is empty so remove it from the mapping table */
  534 + netlbl_domhsh_remove_entry(entry_map, audit_info);
  535 +
  536 +remove_af4_single_addr:
  537 + rcu_read_unlock();
  538 + /* yick, we can't use call_rcu here because we don't have a rcu head
  539 + * pointer but hopefully this should be a rare case so the pause
  540 + * shouldn't be a problem */
  541 + synchronize_rcu();
  542 + entry = netlbl_domhsh_addr4_entry(entry_addr);
  543 + cipso_v4_doi_putdef(entry->type_def.cipsov4);
  544 + kfree(entry);
  545 + return 0;
  546 +
  547 +remove_af4_failure:
  548 + rcu_read_unlock();
  549 + return -ENOENT;
  550 +}
  551 +
  552 +/**
486 553 * netlbl_domhsh_remove - Removes an entry from the domain hash table
487 554 * @domain: the domain to remove
488 555 * @audit_info: NetLabel audit information
net/netlabel/netlabel_domainhash.h
... ... @@ -90,6 +90,10 @@
90 90 struct netlbl_audit *audit_info);
91 91 int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry,
92 92 struct netlbl_audit *audit_info);
  93 +int netlbl_domhsh_remove_af4(const char *domain,
  94 + const struct in_addr *addr,
  95 + const struct in_addr *mask,
  96 + struct netlbl_audit *audit_info);
93 97 int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
94 98 int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info);
95 99 struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
net/netlabel/netlabel_kapi.c
... ... @@ -31,7 +31,10 @@
31 31 #include <linux/init.h>
32 32 #include <linux/types.h>
33 33 #include <linux/audit.h>
  34 +#include <linux/in.h>
  35 +#include <linux/in6.h>
34 36 #include <net/ip.h>
  37 +#include <net/ipv6.h>
35 38 #include <net/netlabel.h>
36 39 #include <net/cipso_ipv4.h>
37 40 #include <asm/bug.h>
... ... @@ -42,6 +45,7 @@
42 45 #include "netlabel_cipso_v4.h"
43 46 #include "netlabel_user.h"
44 47 #include "netlabel_mgmt.h"
  48 +#include "netlabel_addrlist.h"
45 49  
46 50 /*
47 51 * Configuration Functions
... ... @@ -50,6 +54,9 @@
50 54 /**
51 55 * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
52 56 * @domain: the domain mapping to remove
  57 + * @family: address family
  58 + * @addr: IP address
  59 + * @mask: IP address mask
53 60 * @audit_info: NetLabel audit information
54 61 *
55 62 * Description:
56 63  
57 64  
58 65  
... ... @@ -58,14 +65,32 @@
58 65 * values on failure.
59 66 *
60 67 */
61   -int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info)
  68 +int netlbl_cfg_map_del(const char *domain,
  69 + u16 family,
  70 + const void *addr,
  71 + const void *mask,
  72 + struct netlbl_audit *audit_info)
62 73 {
63   - return netlbl_domhsh_remove(domain, audit_info);
  74 + if (addr == NULL && mask == NULL) {
  75 + return netlbl_domhsh_remove(domain, audit_info);
  76 + } else if (addr != NULL && mask != NULL) {
  77 + switch (family) {
  78 + case AF_INET:
  79 + return netlbl_domhsh_remove_af4(domain, addr, mask,
  80 + audit_info);
  81 + default:
  82 + return -EPFNOSUPPORT;
  83 + }
  84 + } else
  85 + return -EINVAL;
64 86 }
65 87  
66 88 /**
67   - * netlbl_cfg_unlbl_add_map - Add an unlabeled NetLabel/LSM domain mapping
  89 + * netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping
68 90 * @domain: the domain mapping to add
  91 + * @family: address family
  92 + * @addr: IP address
  93 + * @mask: IP address mask
69 94 * @audit_info: NetLabel audit information
70 95 *
71 96 * Description:
72 97  
... ... @@ -74,11 +99,19 @@
74 99 * negative values on failure.
75 100 *
76 101 */
77   -int netlbl_cfg_unlbl_add_map(const char *domain,
  102 +int netlbl_cfg_unlbl_map_add(const char *domain,
  103 + u16 family,
  104 + const void *addr,
  105 + const void *mask,
78 106 struct netlbl_audit *audit_info)
79 107 {
80 108 int ret_val = -ENOMEM;
81 109 struct netlbl_dom_map *entry;
  110 + struct netlbl_domaddr_map *addrmap = NULL;
  111 + struct netlbl_domaddr4_map *map4 = NULL;
  112 + struct netlbl_domaddr6_map *map6 = NULL;
  113 + const struct in_addr *addr4, *mask4;
  114 + const struct in6_addr *addr6, *mask6;
82 115  
83 116 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
84 117 if (entry == NULL)
85 118  
86 119  
87 120  
88 121  
89 122  
90 123  
91 124  
92 125  
93 126  
94 127  
95 128  
96 129  
97 130  
98 131  
... ... @@ -86,49 +119,225 @@
86 119 if (domain != NULL) {
87 120 entry->domain = kstrdup(domain, GFP_ATOMIC);
88 121 if (entry->domain == NULL)
89   - goto cfg_unlbl_add_map_failure;
  122 + goto cfg_unlbl_map_add_failure;
90 123 }
91   - entry->type = NETLBL_NLTYPE_UNLABELED;
92 124  
  125 + if (addr == NULL && mask == NULL)
  126 + entry->type = NETLBL_NLTYPE_UNLABELED;
  127 + else if (addr != NULL && mask != NULL) {
  128 + addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
  129 + if (addrmap == NULL)
  130 + goto cfg_unlbl_map_add_failure;
  131 + INIT_LIST_HEAD(&addrmap->list4);
  132 + INIT_LIST_HEAD(&addrmap->list6);
  133 +
  134 + switch (family) {
  135 + case AF_INET:
  136 + addr4 = addr;
  137 + mask4 = mask;
  138 + map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
  139 + if (map4 == NULL)
  140 + goto cfg_unlbl_map_add_failure;
  141 + map4->type = NETLBL_NLTYPE_UNLABELED;
  142 + map4->list.addr = addr4->s_addr & mask4->s_addr;
  143 + map4->list.mask = mask4->s_addr;
  144 + map4->list.valid = 1;
  145 + ret_val = netlbl_af4list_add(&map4->list,
  146 + &addrmap->list4);
  147 + if (ret_val != 0)
  148 + goto cfg_unlbl_map_add_failure;
  149 + break;
  150 + case AF_INET6:
  151 + addr6 = addr;
  152 + mask6 = mask;
  153 + map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
  154 + if (map4 == NULL)
  155 + goto cfg_unlbl_map_add_failure;
  156 + map6->type = NETLBL_NLTYPE_UNLABELED;
  157 + ipv6_addr_copy(&map6->list.addr, addr6);
  158 + map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
  159 + map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
  160 + map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
  161 + map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
  162 + ipv6_addr_copy(&map6->list.mask, mask6);
  163 + map6->list.valid = 1;
  164 + ret_val = netlbl_af4list_add(&map4->list,
  165 + &addrmap->list4);
  166 + if (ret_val != 0)
  167 + goto cfg_unlbl_map_add_failure;
  168 + break;
  169 + default:
  170 + goto cfg_unlbl_map_add_failure;
  171 + break;
  172 + }
  173 +
  174 + entry->type_def.addrsel = addrmap;
  175 + entry->type = NETLBL_NLTYPE_ADDRSELECT;
  176 + } else {
  177 + ret_val = -EINVAL;
  178 + goto cfg_unlbl_map_add_failure;
  179 + }
  180 +
93 181 ret_val = netlbl_domhsh_add(entry, audit_info);
94 182 if (ret_val != 0)
95   - goto cfg_unlbl_add_map_failure;
  183 + goto cfg_unlbl_map_add_failure;
96 184  
97 185 return 0;
98 186  
99   -cfg_unlbl_add_map_failure:
  187 +cfg_unlbl_map_add_failure:
100 188 if (entry != NULL)
101 189 kfree(entry->domain);
102 190 kfree(entry);
  191 + kfree(addrmap);
  192 + kfree(map4);
  193 + kfree(map6);
103 194 return ret_val;
104 195 }
105 196  
  197 +
106 198 /**
107   - * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping
108   - * @doi_def: the DOI definition
  199 + * netlbl_cfg_unlbl_static_add - Adds a new static label
  200 + * @net: network namespace
  201 + * @dev_name: interface name
  202 + * @addr: IP address in network byte order (struct in[6]_addr)
  203 + * @mask: address mask in network byte order (struct in[6]_addr)
  204 + * @family: address family
  205 + * @secid: LSM secid value for the entry
  206 + * @audit_info: NetLabel audit information
  207 + *
  208 + * Description:
  209 + * Adds a new NetLabel static label to be used when protocol provided labels
  210 + * are not present on incoming traffic. If @dev_name is NULL then the default
  211 + * interface will be used. Returns zero on success, negative values on failure.
  212 + *
  213 + */
  214 +int netlbl_cfg_unlbl_static_add(struct net *net,
  215 + const char *dev_name,
  216 + const void *addr,
  217 + const void *mask,
  218 + u16 family,
  219 + u32 secid,
  220 + struct netlbl_audit *audit_info)
  221 +{
  222 + u32 addr_len;
  223 +
  224 + switch (family) {
  225 + case AF_INET:
  226 + addr_len = sizeof(struct in_addr);
  227 + break;
  228 + case AF_INET6:
  229 + addr_len = sizeof(struct in6_addr);
  230 + break;
  231 + default:
  232 + return -EPFNOSUPPORT;
  233 + }
  234 +
  235 + return netlbl_unlhsh_add(net,
  236 + dev_name, addr, mask, addr_len,
  237 + secid, audit_info);
  238 +}
  239 +
  240 +/**
  241 + * netlbl_cfg_unlbl_static_del - Removes an existing static label
  242 + * @net: network namespace
  243 + * @dev_name: interface name
  244 + * @addr: IP address in network byte order (struct in[6]_addr)
  245 + * @mask: address mask in network byte order (struct in[6]_addr)
  246 + * @family: address family
  247 + * @secid: LSM secid value for the entry
  248 + * @audit_info: NetLabel audit information
  249 + *
  250 + * Description:
  251 + * Removes an existing NetLabel static label used when protocol provided labels
  252 + * are not present on incoming traffic. If @dev_name is NULL then the default
  253 + * interface will be used. Returns zero on success, negative values on failure.
  254 + *
  255 + */
  256 +int netlbl_cfg_unlbl_static_del(struct net *net,
  257 + const char *dev_name,
  258 + const void *addr,
  259 + const void *mask,
  260 + u16 family,
  261 + struct netlbl_audit *audit_info)
  262 +{
  263 + u32 addr_len;
  264 +
  265 + switch (family) {
  266 + case AF_INET:
  267 + addr_len = sizeof(struct in_addr);
  268 + break;
  269 + case AF_INET6:
  270 + addr_len = sizeof(struct in6_addr);
  271 + break;
  272 + default:
  273 + return -EPFNOSUPPORT;
  274 + }
  275 +
  276 + return netlbl_unlhsh_remove(net,
  277 + dev_name, addr, mask, addr_len,
  278 + audit_info);
  279 +}
  280 +
  281 +/**
  282 + * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
  283 + * @doi_def: CIPSO DOI definition
  284 + * @audit_info: NetLabel audit information
  285 + *
  286 + * Description:
  287 + * Add a new CIPSO DOI definition as defined by @doi_def. Returns zero on
  288 + * success and negative values on failure.
  289 + *
  290 + */
  291 +int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
  292 + struct netlbl_audit *audit_info)
  293 +{
  294 + return cipso_v4_doi_add(doi_def, audit_info);
  295 +}
  296 +
  297 +/**
  298 + * netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition
  299 + * @doi: CIPSO DOI
  300 + * @audit_info: NetLabel audit information
  301 + *
  302 + * Description:
  303 + * Remove an existing CIPSO DOI definition matching @doi. Returns zero on
  304 + * success and negative values on failure.
  305 + *
  306 + */
  307 +void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
  308 +{
  309 + cipso_v4_doi_remove(doi, audit_info);
  310 +}
  311 +
  312 +/**
  313 + * netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping
  314 + * @doi: the CIPSO DOI
109 315 * @domain: the domain mapping to add
  316 + * @addr: IP address
  317 + * @mask: IP address mask
110 318 * @audit_info: NetLabel audit information
111 319 *
112 320 * Description:
113   - * Add a new CIPSOv4 DOI definition and NetLabel/LSM domain mapping for this
114   - * new DOI definition to the NetLabel subsystem. A @domain value of NULL adds
115   - * a new default domain mapping. Returns zero on success, negative values on
116   - * failure.
  321 + * Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
  322 + * subsystem. A @domain value of NULL adds a new default domain mapping.
  323 + * Returns zero on success, negative values on failure.
117 324 *
118 325 */
119   -int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
  326 +int netlbl_cfg_cipsov4_map_add(u32 doi,
120 327 const char *domain,
  328 + const struct in_addr *addr,
  329 + const struct in_addr *mask,
121 330 struct netlbl_audit *audit_info)
122 331 {
123 332 int ret_val = -ENOMEM;
124   - u32 doi;
125   - u32 doi_type;
  333 + struct cipso_v4_doi *doi_def;
126 334 struct netlbl_dom_map *entry;
127   - const char *type_str;
128   - struct audit_buffer *audit_buf;
  335 + struct netlbl_domaddr_map *addrmap = NULL;
  336 + struct netlbl_domaddr4_map *addrinfo = NULL;
129 337  
130   - doi = doi_def->doi;
131   - doi_type = doi_def->type;
  338 + doi_def = cipso_v4_doi_getdef(doi);
  339 + if (doi_def == NULL)
  340 + return -ENOENT;
132 341  
133 342 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
134 343 if (entry == NULL)
135 344  
136 345  
137 346  
138 347  
139 348  
140 349  
141 350  
... ... @@ -136,56 +345,52 @@
136 345 if (domain != NULL) {
137 346 entry->domain = kstrdup(domain, GFP_ATOMIC);
138 347 if (entry->domain == NULL)
139   - goto cfg_cipsov4_add_map_failure;
  348 + goto cfg_cipsov4_map_add_failure;
140 349 }
141 350  
142   - ret_val = cipso_v4_doi_add(doi_def);
143   - if (ret_val != 0)
144   - goto cfg_cipsov4_add_map_failure_remove_doi;
145   - entry->type = NETLBL_NLTYPE_CIPSOV4;
146   - entry->type_def.cipsov4 = cipso_v4_doi_getdef(doi);
147   - if (entry->type_def.cipsov4 == NULL) {
148   - ret_val = -ENOENT;
149   - goto cfg_cipsov4_add_map_failure_remove_doi;
  351 + if (addr == NULL && mask == NULL) {
  352 + entry->type_def.cipsov4 = doi_def;
  353 + entry->type = NETLBL_NLTYPE_CIPSOV4;
  354 + } else if (addr != NULL && mask != NULL) {
  355 + addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
  356 + if (addrmap == NULL)
  357 + goto cfg_cipsov4_map_add_failure;
  358 + INIT_LIST_HEAD(&addrmap->list4);
  359 + INIT_LIST_HEAD(&addrmap->list6);
  360 +
  361 + addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
  362 + if (addrinfo == NULL)
  363 + goto cfg_cipsov4_map_add_failure;
  364 + addrinfo->type_def.cipsov4 = doi_def;
  365 + addrinfo->type = NETLBL_NLTYPE_CIPSOV4;
  366 + addrinfo->list.addr = addr->s_addr & mask->s_addr;
  367 + addrinfo->list.mask = mask->s_addr;
  368 + addrinfo->list.valid = 1;
  369 + ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
  370 + if (ret_val != 0)
  371 + goto cfg_cipsov4_map_add_failure;
  372 +
  373 + entry->type_def.addrsel = addrmap;
  374 + entry->type = NETLBL_NLTYPE_ADDRSELECT;
  375 + } else {
  376 + ret_val = -EINVAL;
  377 + goto cfg_cipsov4_map_add_failure;
150 378 }
  379 +
151 380 ret_val = netlbl_domhsh_add(entry, audit_info);
152 381 if (ret_val != 0)
153   - goto cfg_cipsov4_add_map_failure_release_doi;
  382 + goto cfg_cipsov4_map_add_failure;
154 383  
155   -cfg_cipsov4_add_map_return:
156   - audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
157   - audit_info);
158   - if (audit_buf != NULL) {
159   - switch (doi_type) {
160   - case CIPSO_V4_MAP_TRANS:
161   - type_str = "trans";
162   - break;
163   - case CIPSO_V4_MAP_PASS:
164   - type_str = "pass";
165   - break;
166   - case CIPSO_V4_MAP_LOCAL:
167   - type_str = "local";
168   - break;
169   - default:
170   - type_str = "(unknown)";
171   - }
172   - audit_log_format(audit_buf,
173   - " cipso_doi=%u cipso_type=%s res=%u",
174   - doi, type_str, ret_val == 0 ? 1 : 0);
175   - audit_log_end(audit_buf);
176   - }
  384 + return 0;
177 385  
178   - return ret_val;
179   -
180   -cfg_cipsov4_add_map_failure_release_doi:
  386 +cfg_cipsov4_map_add_failure:
181 387 cipso_v4_doi_putdef(doi_def);
182   -cfg_cipsov4_add_map_failure_remove_doi:
183   - cipso_v4_doi_remove(doi, audit_info);
184   -cfg_cipsov4_add_map_failure:
185 388 if (entry != NULL)
186 389 kfree(entry->domain);
187 390 kfree(entry);
188   - goto cfg_cipsov4_add_map_return;
  391 + kfree(addrmap);
  392 + kfree(addrinfo);
  393 + return ret_val;
189 394 }
190 395  
191 396 /*
... ... @@ -688,6 +893,28 @@
688 893 return cipso_v4_cache_add(skb, secattr);
689 894  
690 895 return -ENOMSG;
  896 +}
  897 +
  898 +/*
  899 + * Protocol Engine Functions
  900 + */
  901 +
  902 +/**
  903 + * netlbl_audit_start - Start an audit message
  904 + * @type: audit message type
  905 + * @audit_info: NetLabel audit information
  906 + *
  907 + * Description:
  908 + * Start an audit message using the type specified in @type and fill the audit
  909 + * message with some fields common to all NetLabel audit messages. This
  910 + * function should only be used by protocol engines, not LSMs. Returns a
  911 + * pointer to the audit buffer on success, NULL on failure.
  912 + *
  913 + */
  914 +struct audit_buffer *netlbl_audit_start(int type,
  915 + struct netlbl_audit *audit_info)
  916 +{
  917 + return netlbl_audit_start_common(type, audit_info);
691 918 }
692 919  
693 920 /*
net/netlabel/netlabel_unlabeled.c
... ... @@ -450,13 +450,13 @@
450 450 * success, negative values on failure.
451 451 *
452 452 */
453   -static int netlbl_unlhsh_add(struct net *net,
454   - const char *dev_name,
455   - const void *addr,
456   - const void *mask,
457   - u32 addr_len,
458   - u32 secid,
459   - struct netlbl_audit *audit_info)
  453 +int netlbl_unlhsh_add(struct net *net,
  454 + const char *dev_name,
  455 + const void *addr,
  456 + const void *mask,
  457 + u32 addr_len,
  458 + u32 secid,
  459 + struct netlbl_audit *audit_info)
460 460 {
461 461 int ret_val;
462 462 int ifindex;
... ... @@ -720,12 +720,12 @@
720 720 * Returns zero on success, negative values on failure.
721 721 *
722 722 */
723   -static int netlbl_unlhsh_remove(struct net *net,
724   - const char *dev_name,
725   - const void *addr,
726   - const void *mask,
727   - u32 addr_len,
728   - struct netlbl_audit *audit_info)
  723 +int netlbl_unlhsh_remove(struct net *net,
  724 + const char *dev_name,
  725 + const void *addr,
  726 + const void *mask,
  727 + u32 addr_len,
  728 + struct netlbl_audit *audit_info)
729 729 {
730 730 int ret_val;
731 731 struct net_device *dev;
net/netlabel/netlabel_unlabeled.h
... ... @@ -221,6 +221,21 @@
221 221 /* General Unlabeled init function */
222 222 int netlbl_unlabel_init(u32 size);
223 223  
  224 +/* Static/Fallback label management functions */
  225 +int netlbl_unlhsh_add(struct net *net,
  226 + const char *dev_name,
  227 + const void *addr,
  228 + const void *mask,
  229 + u32 addr_len,
  230 + u32 secid,
  231 + struct netlbl_audit *audit_info);
  232 +int netlbl_unlhsh_remove(struct net *net,
  233 + const char *dev_name,
  234 + const void *addr,
  235 + const void *mask,
  236 + u32 addr_len,
  237 + struct netlbl_audit *audit_info);
  238 +
224 239 /* Process Unlabeled incoming network packets */
225 240 int netlbl_unlabel_getattr(const struct sk_buff *skb,
226 241 u16 family,
security/commoncap.c
... ... @@ -45,26 +45,22 @@
45 45 /**
46 46 * cap_capable - Determine whether a task has a particular effective capability
47 47 * @tsk: The task to query
  48 + * @cred: The credentials to use
48 49 * @cap: The capability to check for
49 50 * @audit: Whether to write an audit message or not
50 51 *
51 52 * Determine whether the nominated task has the specified capability amongst
52 53 * its effective set, returning 0 if it does, -ve if it does not.
53 54 *
54   - * NOTE WELL: cap_capable() cannot be used like the kernel's capable()
55   - * function. That is, it has the reverse semantics: cap_capable() returns 0
56   - * when a task has a capability, but the kernel's capable() returns 1 for this
57   - * case.
  55 + * NOTE WELL: cap_has_capability() cannot be used like the kernel's capable()
  56 + * and has_capability() functions. That is, it has the reverse semantics:
  57 + * cap_has_capability() returns 0 when a task has a capability, but the
  58 + * kernel's capable() and has_capability() returns 1 for this case.
58 59 */
59   -int cap_capable(struct task_struct *tsk, int cap, int audit)
  60 +int cap_capable(struct task_struct *tsk, const struct cred *cred, int cap,
  61 + int audit)
60 62 {
61   - __u32 cap_raised;
62   -
63   - /* Derived from include/linux/sched.h:capable. */
64   - rcu_read_lock();
65   - cap_raised = cap_raised(__task_cred(tsk)->cap_effective, cap);
66   - rcu_read_unlock();
67   - return cap_raised ? 0 : -EPERM;
  63 + return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM;
68 64 }
69 65  
70 66 /**
... ... @@ -160,7 +156,8 @@
160 156 /* they are so limited unless the current task has the CAP_SETPCAP
161 157 * capability
162 158 */
163   - if (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0)
  159 + if (cap_capable(current, current_cred(), CAP_SETPCAP,
  160 + SECURITY_CAP_AUDIT) == 0)
164 161 return 0;
165 162 #endif
166 163 return 1;
... ... @@ -869,7 +866,8 @@
869 866 & (new->securebits ^ arg2)) /*[1]*/
870 867 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/
871 868 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
872   - || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0) /*[4]*/
  869 + || (cap_capable(current, current_cred(), CAP_SETPCAP,
  870 + SECURITY_CAP_AUDIT) != 0) /*[4]*/
873 871 /*
874 872 * [1] no changing of bits that are locked
875 873 * [2] no unlocking of locks
... ... @@ -950,7 +948,8 @@
950 948 {
951 949 int cap_sys_admin = 0;
952 950  
953   - if (cap_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT) == 0)
  951 + if (cap_capable(current, current_cred(), CAP_SYS_ADMIN,
  952 + SECURITY_CAP_NOAUDIT) == 0)
954 953 cap_sys_admin = 1;
955 954 return __vm_enough_memory(mm, pages, cap_sys_admin);
956 955 }
security/keys/keyctl.c
... ... @@ -1294,7 +1294,7 @@
1294 1294  
1295 1295 case KEYCTL_GET_SECURITY:
1296 1296 return keyctl_get_security((key_serial_t) arg2,
1297   - (char *) arg3,
  1297 + (char __user *) arg3,
1298 1298 (size_t) arg4);
1299 1299  
1300 1300 default:
... ... @@ -154,14 +154,32 @@
154 154 effective, inheritable, permitted);
155 155 }
156 156  
157   -int security_capable(struct task_struct *tsk, int cap)
  157 +int security_capable(int cap)
158 158 {
159   - return security_ops->capable(tsk, cap, SECURITY_CAP_AUDIT);
  159 + return security_ops->capable(current, current_cred(), cap,
  160 + SECURITY_CAP_AUDIT);
160 161 }
161 162  
162   -int security_capable_noaudit(struct task_struct *tsk, int cap)
  163 +int security_real_capable(struct task_struct *tsk, int cap)
163 164 {
164   - return security_ops->capable(tsk, cap, SECURITY_CAP_NOAUDIT);
  165 + const struct cred *cred;
  166 + int ret;
  167 +
  168 + cred = get_task_cred(tsk);
  169 + ret = security_ops->capable(tsk, cred, cap, SECURITY_CAP_AUDIT);
  170 + put_cred(cred);
  171 + return ret;
  172 +}
  173 +
  174 +int security_real_capable_noaudit(struct task_struct *tsk, int cap)
  175 +{
  176 + const struct cred *cred;
  177 + int ret;
  178 +
  179 + cred = get_task_cred(tsk);
  180 + ret = security_ops->capable(tsk, cred, cap, SECURITY_CAP_NOAUDIT);
  181 + put_cred(cred);
  182 + return ret;
165 183 }
166 184  
167 185 int security_acct(struct file *file)
security/selinux/Kconfig
... ... @@ -94,33 +94,6 @@
94 94  
95 95 If you are unsure how to answer this question, answer 1.
96 96  
97   -config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
98   - bool "NSA SELinux enable new secmark network controls by default"
99   - depends on SECURITY_SELINUX
100   - default n
101   - help
102   - This option determines whether the new secmark-based network
103   - controls will be enabled by default. If not, the old internal
104   - per-packet controls will be enabled by default, preserving
105   - old behavior.
106   -
107   - If you enable the new controls, you will need updated
108   - SELinux userspace libraries, tools and policy. Typically,
109   - your distribution will provide these and enable the new controls
110   - in the kernel they also distribute.
111   -
112   - Note that this option can be overridden at boot with the
113   - selinux_compat_net parameter, and after boot via
114   - /selinux/compat_net. See Documentation/kernel-parameters.txt
115   - for details on this parameter.
116   -
117   - If you enable the new network controls, you will likely
118   - also require the SECMARK and CONNSECMARK targets, as
119   - well as any conntrack helpers for protocols which you
120   - wish to control.
121   -
122   - If you are unsure what to do here, select N.
123   -
124 97 config SECURITY_SELINUX_POLICYDB_VERSION_MAX
125 98 bool "NSA SELinux maximum supported policy format version"
126 99 depends on SECURITY_SELINUX
security/selinux/avc.c
... ... @@ -53,18 +53,20 @@
53 53 #undef S_
54 54  
55 55 static const struct av_inherit av_inherit[] = {
56   -#define S_(c, i, b) { c, common_##i##_perm_to_string, b },
  56 +#define S_(c, i, b) { .tclass = c,\
  57 + .common_pts = common_##i##_perm_to_string,\
  58 + .common_base = b },
57 59 #include "av_inherit.h"
58 60 #undef S_
59 61 };
60 62  
61 63 const struct selinux_class_perm selinux_class_perm = {
62   - av_perm_to_string,
63   - ARRAY_SIZE(av_perm_to_string),
64   - class_to_string,
65   - ARRAY_SIZE(class_to_string),
66   - av_inherit,
67   - ARRAY_SIZE(av_inherit)
  64 + .av_perm_to_string = av_perm_to_string,
  65 + .av_pts_len = ARRAY_SIZE(av_perm_to_string),
  66 + .class_to_string = class_to_string,
  67 + .cts_len = ARRAY_SIZE(class_to_string),
  68 + .av_inherit = av_inherit,
  69 + .av_inherit_len = ARRAY_SIZE(av_inherit)
68 70 };
69 71  
70 72 #define AVC_CACHE_SLOTS 512
security/selinux/hooks.c
... ... @@ -1433,12 +1433,13 @@
1433 1433  
1434 1434 /* Check whether a task is allowed to use a capability. */
1435 1435 static int task_has_capability(struct task_struct *tsk,
  1436 + const struct cred *cred,
1436 1437 int cap, int audit)
1437 1438 {
1438 1439 struct avc_audit_data ad;
1439 1440 struct av_decision avd;
1440 1441 u16 sclass;
1441   - u32 sid = task_sid(tsk);
  1442 + u32 sid = cred_sid(cred);
1442 1443 u32 av = CAP_TO_MASK(cap);
1443 1444 int rc;
1444 1445  
1445 1446  
1446 1447  
... ... @@ -1865,15 +1866,16 @@
1865 1866 return cred_has_perm(old, new, PROCESS__SETCAP);
1866 1867 }
1867 1868  
1868   -static int selinux_capable(struct task_struct *tsk, int cap, int audit)
  1869 +static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
  1870 + int cap, int audit)
1869 1871 {
1870 1872 int rc;
1871 1873  
1872   - rc = secondary_ops->capable(tsk, cap, audit);
  1874 + rc = secondary_ops->capable(tsk, cred, cap, audit);
1873 1875 if (rc)
1874 1876 return rc;
1875 1877  
1876   - return task_has_capability(tsk, cap, audit);
  1878 + return task_has_capability(tsk, cred, cap, audit);
1877 1879 }
1878 1880  
1879 1881 static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
... ... @@ -2037,7 +2039,8 @@
2037 2039 {
2038 2040 int rc, cap_sys_admin = 0;
2039 2041  
2040   - rc = selinux_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT);
  2042 + rc = selinux_capable(current, current_cred(), CAP_SYS_ADMIN,
  2043 + SECURITY_CAP_NOAUDIT);
2041 2044 if (rc == 0)
2042 2045 cap_sys_admin = 1;
2043 2046  
... ... @@ -2880,7 +2883,8 @@
2880 2883 * and lack of permission just means that we fall back to the
2881 2884 * in-core context value, not a denial.
2882 2885 */
2883   - error = selinux_capable(current, CAP_MAC_ADMIN, SECURITY_CAP_NOAUDIT);
  2886 + error = selinux_capable(current, current_cred(), CAP_MAC_ADMIN,
  2887 + SECURITY_CAP_NOAUDIT);
2884 2888 if (!error)
2885 2889 error = security_sid_to_context_force(isec->sid, &context,
2886 2890 &size);
... ... @@ -4185,7 +4189,7 @@
4185 4189 static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4186 4190 u16 family)
4187 4191 {
4188   - int err;
  4192 + int err = 0;
4189 4193 struct sk_security_struct *sksec = sk->sk_security;
4190 4194 u32 peer_sid;
4191 4195 u32 sk_sid = sksec->sid;
... ... @@ -4202,7 +4206,7 @@
4202 4206 if (selinux_compat_net)
4203 4207 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
4204 4208 family, addrp);
4205   - else
  4209 + else if (selinux_secmark_enabled())
4206 4210 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4207 4211 PACKET__RECV, &ad);
4208 4212 if (err)
... ... @@ -4705,7 +4709,7 @@
4705 4709 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4706 4710 &ad, family, addrp))
4707 4711 return NF_DROP;
4708   - } else {
  4712 + } else if (selinux_secmark_enabled()) {
4709 4713 if (avc_has_perm(sksec->sid, skb->secmark,
4710 4714 SECCLASS_PACKET, PACKET__SEND, &ad))
4711 4715 return NF_DROP;
security/selinux/include/avc_ss.h
... ... @@ -17,16 +17,16 @@
17 17 };
18 18  
19 19 struct av_inherit {
20   - u16 tclass;
21 20 const char **common_pts;
22 21 u32 common_base;
  22 + u16 tclass;
23 23 };
24 24  
25 25 struct selinux_class_perm {
26 26 const struct av_perm_to_string *av_perm_to_string;
27 27 u32 av_pts_len;
28   - const char **class_to_string;
29 28 u32 cts_len;
  29 + const char **class_to_string;
30 30 const struct av_inherit *av_inherit;
31 31 u32 av_inherit_len;
32 32 };
security/selinux/selinuxfs.c
... ... @@ -47,14 +47,8 @@
47 47  
48 48 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
49 49  
50   -#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
51   -#define SELINUX_COMPAT_NET_VALUE 0
52   -#else
53   -#define SELINUX_COMPAT_NET_VALUE 1
54   -#endif
  50 +int selinux_compat_net = 0;
55 51  
56   -int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
57   -
58 52 static int __init checkreqprot_setup(char *str)
59 53 {
60 54 unsigned long checkreqprot;
... ... @@ -494,7 +488,13 @@
494 488 if (sscanf(page, "%d", &new_value) != 1)
495 489 goto out;
496 490  
497   - selinux_compat_net = new_value ? 1 : 0;
  491 + if (new_value) {
  492 + printk(KERN_NOTICE
  493 + "SELinux: compat_net is deprecated, please use secmark"
  494 + " instead\n");
  495 + selinux_compat_net = 1;
  496 + } else
  497 + selinux_compat_net = 0;
498 498 length = count;
499 499 out:
500 500 free_page((unsigned long) page);
security/selinux/ss/context.h
... ... @@ -27,9 +27,9 @@
27 27 u32 user;
28 28 u32 role;
29 29 u32 type;
  30 + u32 len; /* length of string in bytes */
30 31 struct mls_range range;
31 32 char *str; /* string representation if context cannot be mapped. */
32   - u32 len; /* length of string in bytes */
33 33 };
34 34  
35 35 static inline void mls_context_init(struct context *c)
security/smack/smack.h
... ... @@ -16,6 +16,7 @@
16 16 #include <linux/capability.h>
17 17 #include <linux/spinlock.h>
18 18 #include <linux/security.h>
  19 +#include <linux/in.h>
19 20 #include <net/netlabel.h>
20 21  
21 22 /*
... ... @@ -39,6 +40,7 @@
39 40 struct socket_smack {
40 41 char *smk_out; /* outbound label */
41 42 char *smk_in; /* inbound label */
  43 + int smk_labeled; /* label scheme */
42 44 char smk_packet[SMK_LABELLEN]; /* TCP peer label */
43 45 };
44 46  
... ... @@ -80,6 +82,16 @@
80 82 };
81 83  
82 84 /*
  85 + * An entry in the table identifying hosts.
  86 + */
  87 +struct smk_netlbladdr {
  88 + struct smk_netlbladdr *smk_next;
  89 + struct sockaddr_in smk_host; /* network address */
  90 + struct in_addr smk_mask; /* network mask */
  91 + char *smk_label; /* label */
  92 +};
  93 +
  94 +/*
83 95 * This is the repository for labels seen so that it is
84 96 * not necessary to keep allocating tiny chuncks of memory
85 97 * and so that they can be shared.
... ... @@ -127,6 +139,20 @@
127 139 #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
128 140  
129 141 /*
  142 + * How communications on this socket are treated.
  143 + * Usually it's determined by the underlying netlabel code
  144 + * but there are certain cases, including single label hosts
  145 + * and potentially single label interfaces for which the
  146 + * treatment can not be known in advance.
  147 + *
  148 + * The possibility of additional labeling schemes being
  149 + * introduced in the future exists as well.
  150 + */
  151 +#define SMACK_UNLABELED_SOCKET 0
  152 +#define SMACK_CIPSO_SOCKET 1
  153 +
  154 +/*
  155 + * smackfs magic number
130 156 * smackfs macic number
131 157 */
132 158 #define SMACK_MAGIC 0x43415d53 /* "SMAC" */
... ... @@ -141,6 +167,7 @@
141 167 * CIPSO defaults.
142 168 */
143 169 #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */
  170 +#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */
144 171 #define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */
145 172 #define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */
146 173 #define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
... ... @@ -176,7 +203,6 @@
176 203 * Shared data.
177 204 */
178 205 extern int smack_cipso_direct;
179   -extern int smack_net_nltype;
180 206 extern char *smack_net_ambient;
181 207 extern char *smack_onlycap;
182 208  
183 209  
... ... @@ -186,9 +212,10 @@
186 212 extern struct smack_known smack_known_huh;
187 213 extern struct smack_known smack_known_invalid;
188 214 extern struct smack_known smack_known_star;
189   -extern struct smack_known smack_known_unset;
  215 +extern struct smack_known smack_known_web;
190 216  
191 217 extern struct smk_list_entry *smack_list;
  218 +extern struct smk_netlbladdr *smack_netlbladdrs;
192 219 extern struct security_operations smack_ops;
193 220  
194 221 /*
security/smack/smack_access.c
... ... @@ -15,15 +15,8 @@
15 15 #include <linux/sched.h>
16 16 #include "smack.h"
17 17  
18   -struct smack_known smack_known_unset = {
19   - .smk_next = NULL,
20   - .smk_known = "UNSET",
21   - .smk_secid = 1,
22   - .smk_cipso = NULL,
23   -};
24   -
25 18 struct smack_known smack_known_huh = {
26   - .smk_next = &smack_known_unset,
  19 + .smk_next = NULL,
27 20 .smk_known = "?",
28 21 .smk_secid = 2,
29 22 .smk_cipso = NULL,
30 23  
... ... @@ -57,8 +50,15 @@
57 50 .smk_cipso = NULL,
58 51 };
59 52  
60   -struct smack_known *smack_known = &smack_known_invalid;
  53 +struct smack_known smack_known_web = {
  54 + .smk_next = &smack_known_invalid,
  55 + .smk_known = "@",
  56 + .smk_secid = 7,
  57 + .smk_cipso = NULL,
  58 +};
61 59  
  60 +struct smack_known *smack_known = &smack_known_web;
  61 +
62 62 /*
63 63 * The initial value needs to be bigger than any of the
64 64 * known values above.
... ... @@ -98,6 +98,16 @@
98 98 if (subject_label == smack_known_star.smk_known ||
99 99 strcmp(subject_label, smack_known_star.smk_known) == 0)
100 100 return -EACCES;
  101 + /*
  102 + * An internet object can be accessed by any subject.
  103 + * Tasks cannot be assigned the internet label.
  104 + * An internet subject can access any object.
  105 + */
  106 + if (object_label == smack_known_web.smk_known ||
  107 + subject_label == smack_known_web.smk_known ||
  108 + strcmp(object_label, smack_known_web.smk_known) == 0 ||
  109 + strcmp(subject_label, smack_known_web.smk_known) == 0)
  110 + return 0;
101 111 /*
102 112 * A star object can be accessed by any subject.
103 113 */
security/smack/smack_lsm.c
... ... @@ -1277,6 +1277,7 @@
1277 1277  
1278 1278 ssp->smk_in = csp;
1279 1279 ssp->smk_out = csp;
  1280 + ssp->smk_labeled = SMACK_CIPSO_SOCKET;
1280 1281 ssp->smk_packet[0] = '\0';
1281 1282  
1282 1283 sk->sk_security = ssp;
1283 1284  
1284 1285  
1285 1286  
1286 1287  
1287 1288  
1288 1289  
... ... @@ -1341,46 +1342,70 @@
1341 1342 struct smack_cipso cipso;
1342 1343 int rc;
1343 1344  
1344   - switch (smack_net_nltype) {
1345   - case NETLBL_NLTYPE_CIPSOV4:
1346   - nlsp->domain = smack;
1347   - nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
  1345 + nlsp->domain = smack;
  1346 + nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1348 1347  
1349   - rc = smack_to_cipso(smack, &cipso);
1350   - if (rc == 0) {
1351   - nlsp->attr.mls.lvl = cipso.smk_level;
1352   - smack_set_catset(cipso.smk_catset, nlsp);
1353   - } else {
1354   - nlsp->attr.mls.lvl = smack_cipso_direct;
1355   - smack_set_catset(smack, nlsp);
1356   - }
1357   - break;
1358   - default:
1359   - break;
  1348 + rc = smack_to_cipso(smack, &cipso);
  1349 + if (rc == 0) {
  1350 + nlsp->attr.mls.lvl = cipso.smk_level;
  1351 + smack_set_catset(cipso.smk_catset, nlsp);
  1352 + } else {
  1353 + nlsp->attr.mls.lvl = smack_cipso_direct;
  1354 + smack_set_catset(smack, nlsp);
1360 1355 }
1361 1356 }
1362 1357  
1363 1358 /**
1364 1359 * smack_netlabel - Set the secattr on a socket
1365 1360 * @sk: the socket
  1361 + * @labeled: socket label scheme
1366 1362 *
1367 1363 * Convert the outbound smack value (smk_out) to a
1368 1364 * secattr and attach it to the socket.
1369 1365 *
1370 1366 * Returns 0 on success or an error code
1371 1367 */
1372   -static int smack_netlabel(struct sock *sk)
  1368 +static int smack_netlabel(struct sock *sk, int labeled)
1373 1369 {
1374 1370 struct socket_smack *ssp;
1375 1371 struct netlbl_lsm_secattr secattr;
1376   - int rc;
  1372 + int rc = 0;
1377 1373  
1378 1374 ssp = sk->sk_security;
1379   - netlbl_secattr_init(&secattr);
1380   - smack_to_secattr(ssp->smk_out, &secattr);
1381   - rc = netlbl_sock_setattr(sk, &secattr);
1382   - netlbl_secattr_destroy(&secattr);
  1375 + /*
  1376 + * Usually the netlabel code will handle changing the
  1377 + * packet labeling based on the label.
  1378 + * The case of a single label host is different, because
  1379 + * a single label host should never get a labeled packet
  1380 + * even though the label is usually associated with a packet
  1381 + * label.
  1382 + */
  1383 + local_bh_disable();
  1384 + bh_lock_sock_nested(sk);
1383 1385  
  1386 + if (ssp->smk_out == smack_net_ambient ||
  1387 + labeled == SMACK_UNLABELED_SOCKET)
  1388 + netlbl_sock_delattr(sk);
  1389 + else {
  1390 + netlbl_secattr_init(&secattr);
  1391 + smack_to_secattr(ssp->smk_out, &secattr);
  1392 + rc = netlbl_sock_setattr(sk, &secattr);
  1393 + netlbl_secattr_destroy(&secattr);
  1394 + }
  1395 +
  1396 + bh_unlock_sock(sk);
  1397 + local_bh_enable();
  1398 + /*
  1399 + * Remember the label scheme used so that it is not
  1400 + * necessary to do the netlabel setting if it has not
  1401 + * changed the next time through.
  1402 + *
  1403 + * The -EDESTADDRREQ case is an indication that there's
  1404 + * a single level host involved.
  1405 + */
  1406 + if (rc == 0)
  1407 + ssp->smk_labeled = labeled;
  1408 +
1384 1409 return rc;
1385 1410 }
1386 1411  
... ... @@ -1432,7 +1457,7 @@
1432 1457 ssp->smk_in = sp;
1433 1458 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
1434 1459 ssp->smk_out = sp;
1435   - rc = smack_netlabel(sock->sk);
  1460 + rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1436 1461 if (rc != 0)
1437 1462 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
1438 1463 __func__, -rc);
1439 1464  
1440 1465  
... ... @@ -1462,10 +1487,111 @@
1462 1487 /*
1463 1488 * Set the outbound netlbl.
1464 1489 */
1465   - return smack_netlabel(sock->sk);
  1490 + return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1466 1491 }
1467 1492  
  1493 +
1468 1494 /**
  1495 + * smack_host_label - check host based restrictions
  1496 + * @sip: the object end
  1497 + *
  1498 + * looks for host based access restrictions
  1499 + *
  1500 + * This version will only be appropriate for really small
  1501 + * sets of single label hosts. Because of the masking
  1502 + * it cannot shortcut out on the first match. There are
  1503 + * numerious ways to address the problem, but none of them
  1504 + * have been applied here.
  1505 + *
  1506 + * Returns the label of the far end or NULL if it's not special.
  1507 + */
  1508 +static char *smack_host_label(struct sockaddr_in *sip)
  1509 +{
  1510 + struct smk_netlbladdr *snp;
  1511 + char *bestlabel = NULL;
  1512 + struct in_addr *siap = &sip->sin_addr;
  1513 + struct in_addr *liap;
  1514 + struct in_addr *miap;
  1515 + struct in_addr bestmask;
  1516 +
  1517 + if (siap->s_addr == 0)
  1518 + return NULL;
  1519 +
  1520 + bestmask.s_addr = 0;
  1521 +
  1522 + for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
  1523 + liap = &snp->smk_host.sin_addr;
  1524 + miap = &snp->smk_mask;
  1525 + /*
  1526 + * If the addresses match after applying the list entry mask
  1527 + * the entry matches the address. If it doesn't move along to
  1528 + * the next entry.
  1529 + */
  1530 + if ((liap->s_addr & miap->s_addr) !=
  1531 + (siap->s_addr & miap->s_addr))
  1532 + continue;
  1533 + /*
  1534 + * If the list entry mask identifies a single address
  1535 + * it can't get any more specific.
  1536 + */
  1537 + if (miap->s_addr == 0xffffffff)
  1538 + return snp->smk_label;
  1539 + /*
  1540 + * If the list entry mask is less specific than the best
  1541 + * already found this entry is uninteresting.
  1542 + */
  1543 + if ((miap->s_addr | bestmask.s_addr) == bestmask.s_addr)
  1544 + continue;
  1545 + /*
  1546 + * This is better than any entry found so far.
  1547 + */
  1548 + bestmask.s_addr = miap->s_addr;
  1549 + bestlabel = snp->smk_label;
  1550 + }
  1551 +
  1552 + return bestlabel;
  1553 +}
  1554 +
  1555 +/**
  1556 + * smack_socket_connect - connect access check
  1557 + * @sock: the socket
  1558 + * @sap: the other end
  1559 + * @addrlen: size of sap
  1560 + *
  1561 + * Verifies that a connection may be possible
  1562 + *
  1563 + * Returns 0 on success, and error code otherwise
  1564 + */
  1565 +static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
  1566 + int addrlen)
  1567 +{
  1568 + struct socket_smack *ssp = sock->sk->sk_security;
  1569 + char *hostsp;
  1570 + int rc;
  1571 +
  1572 + if (sock->sk == NULL || sock->sk->sk_family != PF_INET)
  1573 + return 0;
  1574 +
  1575 + if (addrlen < sizeof(struct sockaddr_in))
  1576 + return -EINVAL;
  1577 +
  1578 + hostsp = smack_host_label((struct sockaddr_in *)sap);
  1579 + if (hostsp == NULL) {
  1580 + if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
  1581 + return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
  1582 + return 0;
  1583 + }
  1584 +
  1585 + rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
  1586 + if (rc != 0)
  1587 + return rc;
  1588 +
  1589 + if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
  1590 + return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
  1591 + return 0;
  1592 +}
  1593 +
  1594 +/**
1469 1595 * smack_flags_to_may - convert S_ to MAY_ values
1470 1596 * @flags: the S_ value
1471 1597 *
1472 1598  
... ... @@ -2101,8 +2227,14 @@
2101 2227 if (newsmack == NULL)
2102 2228 return -EINVAL;
2103 2229  
  2230 + /*
  2231 + * No process is ever allowed the web ("@") label.
  2232 + */
  2233 + if (newsmack == smack_known_web.smk_known)
  2234 + return -EPERM;
  2235 +
2104 2236 new = prepare_creds();
2105   - if (!new)
  2237 + if (new == NULL)
2106 2238 return -ENOMEM;
2107 2239 new->security = newsmack;
2108 2240 commit_creds(new);
... ... @@ -2144,6 +2276,49 @@
2144 2276 }
2145 2277  
2146 2278 /**
  2279 + * smack_socket_sendmsg - Smack check based on destination host
  2280 + * @sock: the socket
  2281 + * @msghdr: the message
  2282 + * @size: the size of the message
  2283 + *
  2284 + * Return 0 if the current subject can write to the destination
  2285 + * host. This is only a question if the destination is a single
  2286 + * label host.
  2287 + */
  2288 +static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
  2289 + int size)
  2290 +{
  2291 + struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
  2292 + struct socket_smack *ssp = sock->sk->sk_security;
  2293 + char *hostsp;
  2294 + int rc;
  2295 +
  2296 + /*
  2297 + * Perfectly reasonable for this to be NULL
  2298 + */
  2299 + if (sip == NULL || sip->sin_family != PF_INET)
  2300 + return 0;
  2301 +
  2302 + hostsp = smack_host_label(sip);
  2303 + if (hostsp == NULL) {
  2304 + if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
  2305 + return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
  2306 + return 0;
  2307 + }
  2308 +
  2309 + rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
  2310 + if (rc != 0)
  2311 + return rc;
  2312 +
  2313 + if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
  2314 + return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
  2315 +
  2316 + return 0;
  2317 +
  2318 +}
  2319 +
  2320 +
  2321 +/**
2147 2322 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat
2148 2323 * pair to smack
2149 2324 * @sap: netlabel secattr
2150 2325  
2151 2326  
2152 2327  
2153 2328  
2154 2329  
2155 2330  
2156 2331  
... ... @@ -2154,44 +2329,66 @@
2154 2329 static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
2155 2330 {
2156 2331 char smack[SMK_LABELLEN];
  2332 + char *sp;
2157 2333 int pcat;
2158 2334  
2159   - if ((sap->flags & NETLBL_SECATTR_MLS_LVL) == 0) {
  2335 + if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
2160 2336 /*
  2337 + * Looks like a CIPSO packet.
2161 2338 * If there are flags but no level netlabel isn't
2162 2339 * behaving the way we expect it to.
2163 2340 *
  2341 + * Get the categories, if any
2164 2342 * Without guidance regarding the smack value
2165 2343 * for the packet fall back on the network
2166 2344 * ambient value.
2167 2345 */
2168   - strncpy(sip, smack_net_ambient, SMK_MAXLEN);
  2346 + memset(smack, '\0', SMK_LABELLEN);
  2347 + if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
  2348 + for (pcat = -1;;) {
  2349 + pcat = netlbl_secattr_catmap_walk(
  2350 + sap->attr.mls.cat, pcat + 1);
  2351 + if (pcat < 0)
  2352 + break;
  2353 + smack_catset_bit(pcat, smack);
  2354 + }
  2355 + /*
  2356 + * If it is CIPSO using smack direct mapping
  2357 + * we are already done. WeeHee.
  2358 + */
  2359 + if (sap->attr.mls.lvl == smack_cipso_direct) {
  2360 + memcpy(sip, smack, SMK_MAXLEN);
  2361 + return;
  2362 + }
  2363 + /*
  2364 + * Look it up in the supplied table if it is not
  2365 + * a direct mapping.
  2366 + */
  2367 + smack_from_cipso(sap->attr.mls.lvl, smack, sip);
2169 2368 return;
2170 2369 }
2171   - /*
2172   - * Get the categories, if any
2173   - */
2174   - memset(smack, '\0', SMK_LABELLEN);
2175   - if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
2176   - for (pcat = -1;;) {
2177   - pcat = netlbl_secattr_catmap_walk(sap->attr.mls.cat,
2178   - pcat + 1);
2179   - if (pcat < 0)
2180   - break;
2181   - smack_catset_bit(pcat, smack);
2182   - }
2183   - /*
2184   - * If it is CIPSO using smack direct mapping
2185   - * we are already done. WeeHee.
2186   - */
2187   - if (sap->attr.mls.lvl == smack_cipso_direct) {
2188   - memcpy(sip, smack, SMK_MAXLEN);
  2370 + if ((sap->flags & NETLBL_SECATTR_SECID) != 0) {
  2371 + /*
  2372 + * Looks like a fallback, which gives us a secid.
  2373 + */
  2374 + sp = smack_from_secid(sap->attr.secid);
  2375 + /*
  2376 + * This has got to be a bug because it is
  2377 + * impossible to specify a fallback without
  2378 + * specifying the label, which will ensure
  2379 + * it has a secid, and the only way to get a
  2380 + * secid is from a fallback.
  2381 + */
  2382 + BUG_ON(sp == NULL);
  2383 + strncpy(sip, sp, SMK_MAXLEN);
2189 2384 return;
2190 2385 }
2191 2386 /*
2192   - * Look it up in the supplied table if it is not a direct mapping.
  2387 + * Without guidance regarding the smack value
  2388 + * for the packet fall back on the network
  2389 + * ambient value.
2193 2390 */
2194   - smack_from_cipso(sap->attr.mls.lvl, smack, sip);
  2391 + strncpy(sip, smack_net_ambient, SMK_MAXLEN);
2195 2392 return;
2196 2393 }
2197 2394  
... ... @@ -2207,6 +2404,7 @@
2207 2404 struct netlbl_lsm_secattr secattr;
2208 2405 struct socket_smack *ssp = sk->sk_security;
2209 2406 char smack[SMK_LABELLEN];
  2407 + char *csp;
2210 2408 int rc;
2211 2409  
2212 2410 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
2213 2411  
2214 2412  
2215 2413  
2216 2414  
2217 2415  
... ... @@ -2215,21 +2413,24 @@
2215 2413 /*
2216 2414 * Translate what netlabel gave us.
2217 2415 */
2218   - memset(smack, '\0', SMK_LABELLEN);
2219 2416 netlbl_secattr_init(&secattr);
  2417 +
2220 2418 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
2221   - if (rc == 0)
  2419 + if (rc == 0) {
2222 2420 smack_from_secattr(&secattr, smack);
2223   - else
2224   - strncpy(smack, smack_net_ambient, SMK_MAXLEN);
  2421 + csp = smack;
  2422 + } else
  2423 + csp = smack_net_ambient;
  2424 +
2225 2425 netlbl_secattr_destroy(&secattr);
  2426 +
2226 2427 /*
2227 2428 * Receiving a packet requires that the other end
2228 2429 * be able to write here. Read access is not required.
2229 2430 * This is the simplist possible security model
2230 2431 * for networking.
2231 2432 */
2232   - rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
  2433 + rc = smk_access(csp, ssp->smk_in, MAY_WRITE);
2233 2434 if (rc != 0)
2234 2435 netlbl_skbuff_err(skb, rc, 0);
2235 2436 return rc;
... ... @@ -2298,7 +2499,6 @@
2298 2499 /*
2299 2500 * Translate what netlabel gave us.
2300 2501 */
2301   - memset(smack, '\0', SMK_LABELLEN);
2302 2502 netlbl_secattr_init(&secattr);
2303 2503 rc = netlbl_skbuff_getattr(skb, family, &secattr);
2304 2504 if (rc == 0)
... ... @@ -2341,7 +2541,7 @@
2341 2541 ssp->smk_in = ssp->smk_out = current_security();
2342 2542 ssp->smk_packet[0] = '\0';
2343 2543  
2344   - rc = smack_netlabel(sk);
  2544 + rc = smack_netlabel(sk, SMACK_CIPSO_SOCKET);
2345 2545 if (rc != 0)
2346 2546 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
2347 2547 __func__, -rc);
... ... @@ -2367,7 +2567,6 @@
2367 2567 if (skb == NULL)
2368 2568 return -EACCES;
2369 2569  
2370   - memset(smack, '\0', SMK_LABELLEN);
2371 2570 netlbl_secattr_init(&skb_secattr);
2372 2571 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr);
2373 2572 if (rc == 0)
... ... @@ -2732,6 +2931,8 @@
2732 2931 .unix_may_send = smack_unix_may_send,
2733 2932  
2734 2933 .socket_post_create = smack_socket_post_create,
  2934 + .socket_connect = smack_socket_connect,
  2935 + .socket_sendmsg = smack_socket_sendmsg,
2735 2936 .socket_sock_rcv_skb = smack_socket_sock_rcv_skb,
2736 2937 .socket_getpeersec_stream = smack_socket_getpeersec_stream,
2737 2938 .socket_getpeersec_dgram = smack_socket_getpeersec_dgram,
... ... @@ -2783,7 +2984,6 @@
2783 2984 /*
2784 2985 * Initialize locks
2785 2986 */
2786   - spin_lock_init(&smack_known_unset.smk_cipsolock);
2787 2987 spin_lock_init(&smack_known_huh.smk_cipsolock);
2788 2988 spin_lock_init(&smack_known_hat.smk_cipsolock);
2789 2989 spin_lock_init(&smack_known_star.smk_cipsolock);
security/smack/smackfs.c
... ... @@ -20,6 +20,7 @@
20 20 #include <linux/vmalloc.h>
21 21 #include <linux/security.h>
22 22 #include <linux/mutex.h>
  23 +#include <net/net_namespace.h>
23 24 #include <net/netlabel.h>
24 25 #include <net/cipso_ipv4.h>
25 26 #include <linux/seq_file.h>
... ... @@ -38,7 +39,7 @@
38 39 SMK_DOI = 5, /* CIPSO DOI */
39 40 SMK_DIRECT = 6, /* CIPSO level indicating direct label */
40 41 SMK_AMBIENT = 7, /* internet ambient label */
41   - SMK_NLTYPE = 8, /* label scheme to use by default */
  42 + SMK_NETLBLADDR = 8, /* single label hosts */
42 43 SMK_ONLYCAP = 9, /* the only "capable" label */
43 44 };
44 45  
... ... @@ -48,6 +49,7 @@
48 49 static DEFINE_MUTEX(smack_list_lock);
49 50 static DEFINE_MUTEX(smack_cipso_lock);
50 51 static DEFINE_MUTEX(smack_ambient_lock);
  52 +static DEFINE_MUTEX(smk_netlbladdr_lock);
51 53  
52 54 /*
53 55 * This is the "ambient" label for network traffic.
... ... @@ -57,12 +59,6 @@
57 59 char *smack_net_ambient = smack_known_floor.smk_known;
58 60  
59 61 /*
60   - * This is the default packet marking scheme for network traffic.
61   - * It can be reset via smackfs/nltype
62   - */
63   -int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;
64   -
65   -/*
66 62 * This is the level in a CIPSO header that indicates a
67 63 * smack label is contained directly in the category set.
68 64 * It can be reset via smackfs/direct
... ... @@ -79,6 +75,13 @@
79 75 */
80 76 char *smack_onlycap;
81 77  
  78 +/*
  79 + * Certain IP addresses may be designated as single label hosts.
  80 + * Packets are sent there unlabeled, but only from tasks that
  81 + * can write to the specified label.
  82 + */
  83 +struct smk_netlbladdr *smack_netlbladdrs;
  84 +
82 85 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
83 86 struct smk_list_entry *smack_list;
84 87  
85 88  
... ... @@ -104,8 +107,26 @@
104 107 #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
105 108 #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
106 109  
  110 +/**
  111 + * smk_netlabel_audit_set - fill a netlbl_audit struct
  112 + * @nap: structure to fill
  113 + */
  114 +static void smk_netlabel_audit_set(struct netlbl_audit *nap)
  115 +{
  116 + nap->loginuid = audit_get_loginuid(current);
  117 + nap->sessionid = audit_get_sessionid(current);
  118 + nap->secid = smack_to_secid(current_security());
  119 +}
107 120  
108 121 /*
  122 + * Values for parsing single label host rules
  123 + * "1.2.3.4 X"
  124 + * "192.168.138.129/32 abcdefghijklmnopqrstuvw"
  125 + */
  126 +#define SMK_NETLBLADDRMIN 9
  127 +#define SMK_NETLBLADDRMAX 42
  128 +
  129 +/*
109 130 * Seq_file read operations for /smack/load
110 131 */
111 132  
112 133  
113 134  
... ... @@ -344,13 +365,11 @@
344 365 {
345 366 int rc;
346 367 struct cipso_v4_doi *doip;
347   - struct netlbl_audit audit_info;
  368 + struct netlbl_audit nai;
348 369  
349   - audit_info.loginuid = audit_get_loginuid(current);
350   - audit_info.sessionid = audit_get_sessionid(current);
351   - audit_info.secid = smack_to_secid(current_security());
  370 + smk_netlabel_audit_set(&nai);
352 371  
353   - rc = netlbl_cfg_map_del(NULL, &audit_info);
  372 + rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
354 373 if (rc != 0)
355 374 printk(KERN_WARNING "%s:%d remove rc = %d\n",
356 375 __func__, __LINE__, rc);
357 376  
358 377  
359 378  
... ... @@ -365,12 +384,20 @@
365 384 for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
366 385 doip->tags[rc] = CIPSO_V4_TAG_INVALID;
367 386  
368   - rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info);
  387 + rc = netlbl_cfg_cipsov4_add(doip, &nai);
369 388 if (rc != 0) {
370   - printk(KERN_WARNING "%s:%d add rc = %d\n",
  389 + printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
371 390 __func__, __LINE__, rc);
372 391 kfree(doip);
  392 + return;
373 393 }
  394 + rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
  395 + if (rc != 0) {
  396 + printk(KERN_WARNING "%s:%d map add rc = %d\n",
  397 + __func__, __LINE__, rc);
  398 + kfree(doip);
  399 + return;
  400 + }
374 401 }
375 402  
376 403 /**
377 404  
378 405  
379 406  
... ... @@ -379,20 +406,19 @@
379 406 static void smk_unlbl_ambient(char *oldambient)
380 407 {
381 408 int rc;
382   - struct netlbl_audit audit_info;
  409 + struct netlbl_audit nai;
383 410  
384   - audit_info.loginuid = audit_get_loginuid(current);
385   - audit_info.sessionid = audit_get_sessionid(current);
386   - audit_info.secid = smack_to_secid(current_security());
  411 + smk_netlabel_audit_set(&nai);
387 412  
388 413 if (oldambient != NULL) {
389   - rc = netlbl_cfg_map_del(oldambient, &audit_info);
  414 + rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
390 415 if (rc != 0)
391 416 printk(KERN_WARNING "%s:%d remove rc = %d\n",
392 417 __func__, __LINE__, rc);
393 418 }
394 419  
395   - rc = netlbl_cfg_unlbl_add_map(smack_net_ambient, &audit_info);
  420 + rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
  421 + NULL, NULL, &nai);
396 422 if (rc != 0)
397 423 printk(KERN_WARNING "%s:%d add rc = %d\n",
398 424 __func__, __LINE__, rc);
399 425  
... ... @@ -603,7 +629,202 @@
603 629 .release = seq_release,
604 630 };
605 631  
  632 +/*
  633 + * Seq_file read operations for /smack/netlabel
  634 + */
  635 +
  636 +static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
  637 +{
  638 + if (*pos == SEQ_READ_FINISHED)
  639 + return NULL;
  640 +
  641 + return smack_netlbladdrs;
  642 +}
  643 +
  644 +static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
  645 +{
  646 + struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next;
  647 +
  648 + if (skp == NULL)
  649 + *pos = SEQ_READ_FINISHED;
  650 +
  651 + return skp;
  652 +}
  653 +/*
  654 +#define BEMASK 0x80000000
  655 +*/
  656 +#define BEMASK 0x00000001
  657 +#define BEBITS (sizeof(__be32) * 8)
  658 +
  659 +/*
  660 + * Print host/label pairs
  661 + */
  662 +static int netlbladdr_seq_show(struct seq_file *s, void *v)
  663 +{
  664 + struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v;
  665 + unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
  666 + __be32 bebits;
  667 + int maskn = 0;
  668 +
  669 + for (bebits = BEMASK; bebits != 0; maskn++, bebits <<= 1)
  670 + if ((skp->smk_mask.s_addr & bebits) == 0)
  671 + break;
  672 +
  673 + seq_printf(s, "%u.%u.%u.%u/%d %s\n",
  674 + hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
  675 +
  676 + return 0;
  677 +}
  678 +
  679 +static void netlbladdr_seq_stop(struct seq_file *s, void *v)
  680 +{
  681 + /* No-op */
  682 +}
  683 +
  684 +static struct seq_operations netlbladdr_seq_ops = {
  685 + .start = netlbladdr_seq_start,
  686 + .stop = netlbladdr_seq_stop,
  687 + .next = netlbladdr_seq_next,
  688 + .show = netlbladdr_seq_show,
  689 +};
  690 +
606 691 /**
  692 + * smk_open_netlbladdr - open() for /smack/netlabel
  693 + * @inode: inode structure representing file
  694 + * @file: "netlabel" file pointer
  695 + *
  696 + * Connect our netlbladdr_seq_* operations with /smack/netlabel
  697 + * file_operations
  698 + */
  699 +static int smk_open_netlbladdr(struct inode *inode, struct file *file)
  700 +{
  701 + return seq_open(file, &netlbladdr_seq_ops);
  702 +}
  703 +
  704 +/**
  705 + * smk_write_netlbladdr - write() for /smack/netlabel
  706 + * @filp: file pointer, not actually used
  707 + * @buf: where to get the data from
  708 + * @count: bytes sent
  709 + * @ppos: where to start
  710 + *
  711 + * Accepts only one netlbladdr per write call.
  712 + * Returns number of bytes written or error code, as appropriate
  713 + */
  714 +static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
  715 + size_t count, loff_t *ppos)
  716 +{
  717 + struct smk_netlbladdr *skp;
  718 + struct sockaddr_in newname;
  719 + char smack[SMK_LABELLEN];
  720 + char *sp;
  721 + char data[SMK_NETLBLADDRMAX];
  722 + char *host = (char *)&newname.sin_addr.s_addr;
  723 + int rc;
  724 + struct netlbl_audit audit_info;
  725 + struct in_addr mask;
  726 + unsigned int m;
  727 + __be32 bebits = BEMASK;
  728 + __be32 nsa;
  729 +
  730 + /*
  731 + * Must have privilege.
  732 + * No partial writes.
  733 + * Enough data must be present.
  734 + * "<addr/mask, as a.b.c.d/e><space><label>"
  735 + * "<addr, as a.b.c.d><space><label>"
  736 + */
  737 + if (!capable(CAP_MAC_ADMIN))
  738 + return -EPERM;
  739 + if (*ppos != 0)
  740 + return -EINVAL;
  741 + if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX)
  742 + return -EINVAL;
  743 + if (copy_from_user(data, buf, count) != 0)
  744 + return -EFAULT;
  745 +
  746 + data[count] = '\0';
  747 +
  748 + rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",
  749 + &host[0], &host[1], &host[2], &host[3], &m, smack);
  750 + if (rc != 6) {
  751 + rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
  752 + &host[0], &host[1], &host[2], &host[3], smack);
  753 + if (rc != 5)
  754 + return -EINVAL;
  755 + m = BEBITS;
  756 + }
  757 + if (m > BEBITS)
  758 + return -EINVAL;
  759 +
  760 + sp = smk_import(smack, 0);
  761 + if (sp == NULL)
  762 + return -EINVAL;
  763 +
  764 + for (mask.s_addr = 0; m > 0; m--) {
  765 + mask.s_addr |= bebits;
  766 + bebits <<= 1;
  767 + }
  768 + /*
  769 + * Only allow one writer at a time. Writes should be
  770 + * quite rare and small in any case.
  771 + */
  772 + mutex_lock(&smk_netlbladdr_lock);
  773 +
  774 + nsa = newname.sin_addr.s_addr;
  775 + for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next)
  776 + if (skp->smk_host.sin_addr.s_addr == nsa &&
  777 + skp->smk_mask.s_addr == mask.s_addr)
  778 + break;
  779 +
  780 + smk_netlabel_audit_set(&audit_info);
  781 +
  782 + if (skp == NULL) {
  783 + skp = kzalloc(sizeof(*skp), GFP_KERNEL);
  784 + if (skp == NULL)
  785 + rc = -ENOMEM;
  786 + else {
  787 + rc = 0;
  788 + skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
  789 + skp->smk_mask.s_addr = mask.s_addr;
  790 + skp->smk_next = smack_netlbladdrs;
  791 + skp->smk_label = sp;
  792 + smack_netlbladdrs = skp;
  793 + }
  794 + } else {
  795 + rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
  796 + &skp->smk_host.sin_addr, &skp->smk_mask,
  797 + PF_INET, &audit_info);
  798 + skp->smk_label = sp;
  799 + }
  800 +
  801 + /*
  802 + * Now tell netlabel about the single label nature of
  803 + * this host so that incoming packets get labeled.
  804 + */
  805 +
  806 + if (rc == 0)
  807 + rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
  808 + &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
  809 + smack_to_secid(skp->smk_label), &audit_info);
  810 +
  811 + if (rc == 0)
  812 + rc = count;
  813 +
  814 + mutex_unlock(&smk_netlbladdr_lock);
  815 +
  816 + return rc;
  817 +}
  818 +
  819 +static const struct file_operations smk_netlbladdr_ops = {
  820 + .open = smk_open_netlbladdr,
  821 + .read = seq_read,
  822 + .llseek = seq_lseek,
  823 + .write = smk_write_netlbladdr,
  824 + .release = seq_release,
  825 +};
  826 +
  827 +/**
607 828 * smk_read_doi - read() for /smack/doi
608 829 * @filp: file pointer, not actually used
609 830 * @buf: where to put the result
610 831  
... ... @@ -891,111 +1112,7 @@
891 1112 .write = smk_write_onlycap,
892 1113 };
893 1114  
894   -struct option_names {
895   - int o_number;
896   - char *o_name;
897   - char *o_alias;
898   -};
899   -
900   -static struct option_names netlbl_choices[] = {
901   - { NETLBL_NLTYPE_RIPSO,
902   - NETLBL_NLTYPE_RIPSO_NAME, "ripso" },
903   - { NETLBL_NLTYPE_CIPSOV4,
904   - NETLBL_NLTYPE_CIPSOV4_NAME, "cipsov4" },
905   - { NETLBL_NLTYPE_CIPSOV4,
906   - NETLBL_NLTYPE_CIPSOV4_NAME, "cipso" },
907   - { NETLBL_NLTYPE_CIPSOV6,
908   - NETLBL_NLTYPE_CIPSOV6_NAME, "cipsov6" },
909   - { NETLBL_NLTYPE_UNLABELED,
910   - NETLBL_NLTYPE_UNLABELED_NAME, "unlabeled" },
911   -};
912   -
913 1115 /**
914   - * smk_read_nltype - read() for /smack/nltype
915   - * @filp: file pointer, not actually used
916   - * @buf: where to put the result
917   - * @count: maximum to send along
918   - * @ppos: where to start
919   - *
920   - * Returns number of bytes read or error code, as appropriate
921   - */
922   -static ssize_t smk_read_nltype(struct file *filp, char __user *buf,
923   - size_t count, loff_t *ppos)
924   -{
925   - char bound[40];
926   - ssize_t rc;
927   - int i;
928   -
929   - if (count < SMK_LABELLEN)
930   - return -EINVAL;
931   -
932   - if (*ppos != 0)
933   - return 0;
934   -
935   - sprintf(bound, "unknown");
936   -
937   - for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
938   - if (smack_net_nltype == netlbl_choices[i].o_number) {
939   - sprintf(bound, "%s", netlbl_choices[i].o_name);
940   - break;
941   - }
942   -
943   - rc = simple_read_from_buffer(buf, count, ppos, bound, strlen(bound));
944   -
945   - return rc;
946   -}
947   -
948   -/**
949   - * smk_write_nltype - write() for /smack/nltype
950   - * @filp: file pointer, not actually used
951   - * @buf: where to get the data from
952   - * @count: bytes sent
953   - * @ppos: where to start
954   - *
955   - * Returns number of bytes written or error code, as appropriate
956   - */
957   -static ssize_t smk_write_nltype(struct file *file, const char __user *buf,
958   - size_t count, loff_t *ppos)
959   -{
960   - char bound[40];
961   - char *cp;
962   - int i;
963   -
964   - if (!capable(CAP_MAC_ADMIN))
965   - return -EPERM;
966   -
967   - if (count >= 40)
968   - return -EINVAL;
969   -
970   - if (copy_from_user(bound, buf, count) != 0)
971   - return -EFAULT;
972   -
973   - bound[count] = '\0';
974   - cp = strchr(bound, ' ');
975   - if (cp != NULL)
976   - *cp = '\0';
977   - cp = strchr(bound, '\n');
978   - if (cp != NULL)
979   - *cp = '\0';
980   -
981   - for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
982   - if (strcmp(bound, netlbl_choices[i].o_name) == 0 ||
983   - strcmp(bound, netlbl_choices[i].o_alias) == 0) {
984   - smack_net_nltype = netlbl_choices[i].o_number;
985   - return count;
986   - }
987   - /*
988   - * Not a valid choice.
989   - */
990   - return -EINVAL;
991   -}
992   -
993   -static const struct file_operations smk_nltype_ops = {
994   - .read = smk_read_nltype,
995   - .write = smk_write_nltype,
996   -};
997   -
998   -/**
999 1116 * smk_fill_super - fill the /smackfs superblock
1000 1117 * @sb: the empty superblock
1001 1118 * @data: unused
... ... @@ -1021,8 +1138,8 @@
1021 1138 {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
1022 1139 [SMK_AMBIENT] =
1023 1140 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
1024   - [SMK_NLTYPE] =
1025   - {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR},
  1141 + [SMK_NETLBLADDR] =
  1142 + {"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
1026 1143 [SMK_ONLYCAP] =
1027 1144 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
1028 1145 /* last one */ {""}