Commit ac8cc0fa5395fe2278e305a4cbed48e90d88d878
Exists in
master
and in
39 other branches
Merge branch 'next' into for-linus
Showing 26 changed files Side-by-side Diff
- Documentation/feature-removal-schedule.txt
- include/linux/capability.h
- include/linux/security.h
- include/net/cipso_ipv4.h
- include/net/netlabel.h
- kernel/capability.c
- net/ipv4/cipso_ipv4.c
- net/netlabel/netlabel_cipso_v4.c
- net/netlabel/netlabel_domainhash.c
- net/netlabel/netlabel_domainhash.h
- net/netlabel/netlabel_kapi.c
- net/netlabel/netlabel_unlabeled.c
- net/netlabel/netlabel_unlabeled.h
- security/commoncap.c
- security/keys/keyctl.c
- security/security.c
- security/selinux/Kconfig
- security/selinux/avc.c
- security/selinux/hooks.c
- security/selinux/include/avc_ss.h
- security/selinux/selinuxfs.c
- security/selinux/ss/context.h
- security/smack/smack.h
- security/smack/smack_access.c
- security/smack/smack_lsm.c
- security/smack/smackfs.c
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 |
kernel/capability.c
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
security/security.c
... | ... | @@ -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 */ {""} |