diff options
Diffstat (limited to 'security')
36 files changed, 1307 insertions, 572 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 452567d3a08e..d97cba3e3849 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c | |||
@@ -621,7 +621,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) | |||
621 | * There is no exception for unconfined as change_hat is not | 621 | * There is no exception for unconfined as change_hat is not |
622 | * available. | 622 | * available. |
623 | */ | 623 | */ |
624 | if (current->no_new_privs) | 624 | if (task_no_new_privs(current)) |
625 | return -EPERM; | 625 | return -EPERM; |
626 | 626 | ||
627 | /* released below */ | 627 | /* released below */ |
@@ -776,7 +776,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, | |||
776 | * no_new_privs is set because this aways results in a reduction | 776 | * no_new_privs is set because this aways results in a reduction |
777 | * of permissions. | 777 | * of permissions. |
778 | */ | 778 | */ |
779 | if (current->no_new_privs && !unconfined(profile)) { | 779 | if (task_no_new_privs(current) && !unconfined(profile)) { |
780 | put_cred(cred); | 780 | put_cred(cred); |
781 | return -EPERM; | 781 | return -EPERM; |
782 | } | 782 | } |
diff --git a/security/capability.c b/security/capability.c index e76373de3129..a74fde6a7468 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -401,6 +401,11 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
401 | return 0; | 401 | return 0; |
402 | } | 402 | } |
403 | 403 | ||
404 | static int cap_kernel_fw_from_file(struct file *file, char *buf, size_t size) | ||
405 | { | ||
406 | return 0; | ||
407 | } | ||
408 | |||
404 | static int cap_kernel_module_request(char *kmod_name) | 409 | static int cap_kernel_module_request(char *kmod_name) |
405 | { | 410 | { |
406 | return 0; | 411 | return 0; |
@@ -1015,6 +1020,7 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
1015 | set_to_cap_if_null(ops, cred_transfer); | 1020 | set_to_cap_if_null(ops, cred_transfer); |
1016 | set_to_cap_if_null(ops, kernel_act_as); | 1021 | set_to_cap_if_null(ops, kernel_act_as); |
1017 | set_to_cap_if_null(ops, kernel_create_files_as); | 1022 | set_to_cap_if_null(ops, kernel_create_files_as); |
1023 | set_to_cap_if_null(ops, kernel_fw_from_file); | ||
1018 | set_to_cap_if_null(ops, kernel_module_request); | 1024 | set_to_cap_if_null(ops, kernel_module_request); |
1019 | set_to_cap_if_null(ops, kernel_module_from_file); | 1025 | set_to_cap_if_null(ops, kernel_module_from_file); |
1020 | set_to_cap_if_null(ops, task_fix_setuid); | 1026 | set_to_cap_if_null(ops, task_fix_setuid); |
diff --git a/security/commoncap.c b/security/commoncap.c index b9d613e0ef14..bab0611afc1e 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -421,6 +421,9 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data | |||
421 | cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); | 421 | cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); |
422 | } | 422 | } |
423 | 423 | ||
424 | cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; | ||
425 | cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; | ||
426 | |||
424 | return 0; | 427 | return 0; |
425 | } | 428 | } |
426 | 429 | ||
@@ -822,15 +825,20 @@ int cap_task_setnice(struct task_struct *p, int nice) | |||
822 | * Implement PR_CAPBSET_DROP. Attempt to remove the specified capability from | 825 | * Implement PR_CAPBSET_DROP. Attempt to remove the specified capability from |
823 | * the current task's bounding set. Returns 0 on success, -ve on error. | 826 | * the current task's bounding set. Returns 0 on success, -ve on error. |
824 | */ | 827 | */ |
825 | static long cap_prctl_drop(struct cred *new, unsigned long cap) | 828 | static int cap_prctl_drop(unsigned long cap) |
826 | { | 829 | { |
830 | struct cred *new; | ||
831 | |||
827 | if (!ns_capable(current_user_ns(), CAP_SETPCAP)) | 832 | if (!ns_capable(current_user_ns(), CAP_SETPCAP)) |
828 | return -EPERM; | 833 | return -EPERM; |
829 | if (!cap_valid(cap)) | 834 | if (!cap_valid(cap)) |
830 | return -EINVAL; | 835 | return -EINVAL; |
831 | 836 | ||
837 | new = prepare_creds(); | ||
838 | if (!new) | ||
839 | return -ENOMEM; | ||
832 | cap_lower(new->cap_bset, cap); | 840 | cap_lower(new->cap_bset, cap); |
833 | return 0; | 841 | return commit_creds(new); |
834 | } | 842 | } |
835 | 843 | ||
836 | /** | 844 | /** |
@@ -848,26 +856,17 @@ static long cap_prctl_drop(struct cred *new, unsigned long cap) | |||
848 | int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 856 | int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
849 | unsigned long arg4, unsigned long arg5) | 857 | unsigned long arg4, unsigned long arg5) |
850 | { | 858 | { |
859 | const struct cred *old = current_cred(); | ||
851 | struct cred *new; | 860 | struct cred *new; |
852 | long error = 0; | ||
853 | |||
854 | new = prepare_creds(); | ||
855 | if (!new) | ||
856 | return -ENOMEM; | ||
857 | 861 | ||
858 | switch (option) { | 862 | switch (option) { |
859 | case PR_CAPBSET_READ: | 863 | case PR_CAPBSET_READ: |
860 | error = -EINVAL; | ||
861 | if (!cap_valid(arg2)) | 864 | if (!cap_valid(arg2)) |
862 | goto error; | 865 | return -EINVAL; |
863 | error = !!cap_raised(new->cap_bset, arg2); | 866 | return !!cap_raised(old->cap_bset, arg2); |
864 | goto no_change; | ||
865 | 867 | ||
866 | case PR_CAPBSET_DROP: | 868 | case PR_CAPBSET_DROP: |
867 | error = cap_prctl_drop(new, arg2); | 869 | return cap_prctl_drop(arg2); |
868 | if (error < 0) | ||
869 | goto error; | ||
870 | goto changed; | ||
871 | 870 | ||
872 | /* | 871 | /* |
873 | * The next four prctl's remain to assist with transitioning a | 872 | * The next four prctl's remain to assist with transitioning a |
@@ -889,10 +888,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
889 | * capability-based-privilege environment. | 888 | * capability-based-privilege environment. |
890 | */ | 889 | */ |
891 | case PR_SET_SECUREBITS: | 890 | case PR_SET_SECUREBITS: |
892 | error = -EPERM; | 891 | if ((((old->securebits & SECURE_ALL_LOCKS) >> 1) |
893 | if ((((new->securebits & SECURE_ALL_LOCKS) >> 1) | 892 | & (old->securebits ^ arg2)) /*[1]*/ |
894 | & (new->securebits ^ arg2)) /*[1]*/ | 893 | || ((old->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ |
895 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ | ||
896 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ | 894 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ |
897 | || (cap_capable(current_cred(), | 895 | || (cap_capable(current_cred(), |
898 | current_cred()->user_ns, CAP_SETPCAP, | 896 | current_cred()->user_ns, CAP_SETPCAP, |
@@ -906,46 +904,39 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
906 | */ | 904 | */ |
907 | ) | 905 | ) |
908 | /* cannot change a locked bit */ | 906 | /* cannot change a locked bit */ |
909 | goto error; | 907 | return -EPERM; |
908 | |||
909 | new = prepare_creds(); | ||
910 | if (!new) | ||
911 | return -ENOMEM; | ||
910 | new->securebits = arg2; | 912 | new->securebits = arg2; |
911 | goto changed; | 913 | return commit_creds(new); |
912 | 914 | ||
913 | case PR_GET_SECUREBITS: | 915 | case PR_GET_SECUREBITS: |
914 | error = new->securebits; | 916 | return old->securebits; |
915 | goto no_change; | ||
916 | 917 | ||
917 | case PR_GET_KEEPCAPS: | 918 | case PR_GET_KEEPCAPS: |
918 | if (issecure(SECURE_KEEP_CAPS)) | 919 | return !!issecure(SECURE_KEEP_CAPS); |
919 | error = 1; | ||
920 | goto no_change; | ||
921 | 920 | ||
922 | case PR_SET_KEEPCAPS: | 921 | case PR_SET_KEEPCAPS: |
923 | error = -EINVAL; | ||
924 | if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ | 922 | if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ |
925 | goto error; | 923 | return -EINVAL; |
926 | error = -EPERM; | ||
927 | if (issecure(SECURE_KEEP_CAPS_LOCKED)) | 924 | if (issecure(SECURE_KEEP_CAPS_LOCKED)) |
928 | goto error; | 925 | return -EPERM; |
926 | |||
927 | new = prepare_creds(); | ||
928 | if (!new) | ||
929 | return -ENOMEM; | ||
929 | if (arg2) | 930 | if (arg2) |
930 | new->securebits |= issecure_mask(SECURE_KEEP_CAPS); | 931 | new->securebits |= issecure_mask(SECURE_KEEP_CAPS); |
931 | else | 932 | else |
932 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); | 933 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
933 | goto changed; | 934 | return commit_creds(new); |
934 | 935 | ||
935 | default: | 936 | default: |
936 | /* No functionality available - continue with default */ | 937 | /* No functionality available - continue with default */ |
937 | error = -ENOSYS; | 938 | return -ENOSYS; |
938 | goto error; | ||
939 | } | 939 | } |
940 | |||
941 | /* Functionality provided */ | ||
942 | changed: | ||
943 | return commit_creds(new); | ||
944 | |||
945 | no_change: | ||
946 | error: | ||
947 | abort_creds(new); | ||
948 | return error; | ||
949 | } | 940 | } |
950 | 941 | ||
951 | /** | 942 | /** |
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig index 245c6d92065b..b76235ae4786 100644 --- a/security/integrity/Kconfig +++ b/security/integrity/Kconfig | |||
@@ -1,11 +1,23 @@ | |||
1 | # | 1 | # |
2 | config INTEGRITY | 2 | config INTEGRITY |
3 | def_bool y | 3 | bool "Integrity subsystem" |
4 | depends on IMA || EVM | 4 | depends on SECURITY |
5 | default y | ||
6 | help | ||
7 | This option enables the integrity subsystem, which is comprised | ||
8 | of a number of different components including the Integrity | ||
9 | Measurement Architecture (IMA), Extended Verification Module | ||
10 | (EVM), IMA-appraisal extension, digital signature verification | ||
11 | extension and audit measurement log support. | ||
12 | |||
13 | Each of these components can be enabled/disabled separately. | ||
14 | Refer to the individual components for additional details. | ||
15 | |||
16 | if INTEGRITY | ||
5 | 17 | ||
6 | config INTEGRITY_SIGNATURE | 18 | config INTEGRITY_SIGNATURE |
7 | boolean "Digital signature verification using multiple keyrings" | 19 | boolean "Digital signature verification using multiple keyrings" |
8 | depends on INTEGRITY && KEYS | 20 | depends on KEYS |
9 | default n | 21 | default n |
10 | select SIGNATURE | 22 | select SIGNATURE |
11 | help | 23 | help |
@@ -17,9 +29,21 @@ config INTEGRITY_SIGNATURE | |||
17 | This is useful for evm and module keyrings, when keys are | 29 | This is useful for evm and module keyrings, when keys are |
18 | usually only added from initramfs. | 30 | usually only added from initramfs. |
19 | 31 | ||
32 | config INTEGRITY_ASYMMETRIC_KEYS | ||
33 | boolean "Enable asymmetric keys support" | ||
34 | depends on INTEGRITY_SIGNATURE | ||
35 | default n | ||
36 | select ASYMMETRIC_KEY_TYPE | ||
37 | select ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
38 | select PUBLIC_KEY_ALGO_RSA | ||
39 | select X509_CERTIFICATE_PARSER | ||
40 | help | ||
41 | This option enables digital signature verification using | ||
42 | asymmetric keys. | ||
43 | |||
20 | config INTEGRITY_AUDIT | 44 | config INTEGRITY_AUDIT |
21 | bool "Enables integrity auditing support " | 45 | bool "Enables integrity auditing support " |
22 | depends on INTEGRITY && AUDIT | 46 | depends on AUDIT |
23 | default y | 47 | default y |
24 | help | 48 | help |
25 | In addition to enabling integrity auditing support, this | 49 | In addition to enabling integrity auditing support, this |
@@ -32,17 +56,7 @@ config INTEGRITY_AUDIT | |||
32 | be enabled by specifying 'integrity_audit=1' on the kernel | 56 | be enabled by specifying 'integrity_audit=1' on the kernel |
33 | command line. | 57 | command line. |
34 | 58 | ||
35 | config INTEGRITY_ASYMMETRIC_KEYS | ||
36 | boolean "Enable asymmetric keys support" | ||
37 | depends on INTEGRITY_SIGNATURE | ||
38 | default n | ||
39 | select ASYMMETRIC_KEY_TYPE | ||
40 | select ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
41 | select PUBLIC_KEY_ALGO_RSA | ||
42 | select X509_CERTIFICATE_PARSER | ||
43 | help | ||
44 | This option enables digital signature verification using | ||
45 | asymmetric keys. | ||
46 | |||
47 | source security/integrity/ima/Kconfig | 59 | source security/integrity/ima/Kconfig |
48 | source security/integrity/evm/Kconfig | 60 | source security/integrity/evm/Kconfig |
61 | |||
62 | endif # if INTEGRITY | ||
diff --git a/security/integrity/Makefile b/security/integrity/Makefile index 0793f4811cb7..8d1f4bf51087 100644 --- a/security/integrity/Makefile +++ b/security/integrity/Makefile | |||
@@ -3,11 +3,11 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_INTEGRITY) += integrity.o | 5 | obj-$(CONFIG_INTEGRITY) += integrity.o |
6 | obj-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o | ||
7 | obj-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o | ||
8 | obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o | ||
9 | 6 | ||
10 | integrity-y := iint.o | 7 | integrity-y := iint.o |
8 | integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o | ||
9 | integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o | ||
10 | integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o | ||
11 | 11 | ||
12 | subdir-$(CONFIG_IMA) += ima | 12 | subdir-$(CONFIG_IMA) += ima |
13 | obj-$(CONFIG_IMA) += ima/ | 13 | obj-$(CONFIG_IMA) += ima/ |
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index b4af4ebc5be2..8d4fbff8b87c 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c | |||
@@ -13,7 +13,9 @@ | |||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | 14 | ||
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/sched.h> | ||
16 | #include <linux/rbtree.h> | 17 | #include <linux/rbtree.h> |
18 | #include <linux/cred.h> | ||
17 | #include <linux/key-type.h> | 19 | #include <linux/key-type.h> |
18 | #include <linux/digsig.h> | 20 | #include <linux/digsig.h> |
19 | 21 | ||
@@ -24,7 +26,11 @@ static struct key *keyring[INTEGRITY_KEYRING_MAX]; | |||
24 | static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { | 26 | static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { |
25 | "_evm", | 27 | "_evm", |
26 | "_module", | 28 | "_module", |
29 | #ifndef CONFIG_IMA_TRUSTED_KEYRING | ||
27 | "_ima", | 30 | "_ima", |
31 | #else | ||
32 | ".ima", | ||
33 | #endif | ||
28 | }; | 34 | }; |
29 | 35 | ||
30 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | 36 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, |
@@ -56,3 +62,25 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | |||
56 | 62 | ||
57 | return -EOPNOTSUPP; | 63 | return -EOPNOTSUPP; |
58 | } | 64 | } |
65 | |||
66 | int integrity_init_keyring(const unsigned int id) | ||
67 | { | ||
68 | const struct cred *cred = current_cred(); | ||
69 | int err = 0; | ||
70 | |||
71 | keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), | ||
72 | KGIDT_INIT(0), cred, | ||
73 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
74 | KEY_USR_VIEW | KEY_USR_READ | | ||
75 | KEY_USR_WRITE | KEY_USR_SEARCH), | ||
76 | KEY_ALLOC_NOT_IN_QUOTA, NULL); | ||
77 | if (!IS_ERR(keyring[id])) | ||
78 | set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); | ||
79 | else { | ||
80 | err = PTR_ERR(keyring[id]); | ||
81 | pr_info("Can't allocate %s keyring (%d)\n", | ||
82 | keyring_name[id], err); | ||
83 | keyring[id] = NULL; | ||
84 | } | ||
85 | return err; | ||
86 | } | ||
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 9eae4809006b..37e0d98517a8 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | 14 | ||
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/ratelimit.h> | ||
16 | #include <linux/key-type.h> | 17 | #include <linux/key-type.h> |
17 | #include <crypto/public_key.h> | 18 | #include <crypto/public_key.h> |
18 | #include <keys/asymmetric-type.h> | 19 | #include <keys/asymmetric-type.h> |
@@ -45,8 +46,8 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) | |||
45 | } | 46 | } |
46 | 47 | ||
47 | if (IS_ERR(key)) { | 48 | if (IS_ERR(key)) { |
48 | pr_warn("Request for unknown key '%s' err %ld\n", | 49 | pr_err_ratelimited("Request for unknown key '%s' err %ld\n", |
49 | name, PTR_ERR(key)); | 50 | name, PTR_ERR(key)); |
50 | switch (PTR_ERR(key)) { | 51 | switch (PTR_ERR(key)) { |
51 | /* Hide some search errors */ | 52 | /* Hide some search errors */ |
52 | case -EACCES: | 53 | case -EACCES: |
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig index d606f3d12d6b..df586fa00ef1 100644 --- a/security/integrity/evm/Kconfig +++ b/security/integrity/evm/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | config EVM | 1 | config EVM |
2 | boolean "EVM support" | 2 | boolean "EVM support" |
3 | depends on SECURITY | ||
4 | select KEYS | 3 | select KEYS |
5 | select ENCRYPTED_KEYS | 4 | select ENCRYPTED_KEYS |
6 | select CRYPTO_HMAC | 5 | select CRYPTO_HMAC |
@@ -12,10 +11,6 @@ config EVM | |||
12 | 11 | ||
13 | If you are unsure how to answer this question, answer N. | 12 | If you are unsure how to answer this question, answer N. |
14 | 13 | ||
15 | if EVM | ||
16 | |||
17 | menu "EVM options" | ||
18 | |||
19 | config EVM_ATTR_FSUUID | 14 | config EVM_ATTR_FSUUID |
20 | bool "FSUUID (version 2)" | 15 | bool "FSUUID (version 2)" |
21 | default y | 16 | default y |
@@ -47,6 +42,3 @@ config EVM_EXTRA_SMACK_XATTRS | |||
47 | additional info to the calculation, requires existing EVM | 42 | additional info to the calculation, requires existing EVM |
48 | labeled file systems to be relabeled. | 43 | labeled file systems to be relabeled. |
49 | 44 | ||
50 | endmenu | ||
51 | |||
52 | endif | ||
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 3bcb80df4d01..9685af330de5 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c | |||
@@ -126,14 +126,15 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, | |||
126 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, | 126 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, |
127 | GFP_NOFS); | 127 | GFP_NOFS); |
128 | if (rc <= 0) { | 128 | if (rc <= 0) { |
129 | if (rc == 0) | 129 | evm_status = INTEGRITY_FAIL; |
130 | evm_status = INTEGRITY_FAIL; /* empty */ | 130 | if (rc == -ENODATA) { |
131 | else if (rc == -ENODATA) { | ||
132 | rc = evm_find_protected_xattrs(dentry); | 131 | rc = evm_find_protected_xattrs(dentry); |
133 | if (rc > 0) | 132 | if (rc > 0) |
134 | evm_status = INTEGRITY_NOLABEL; | 133 | evm_status = INTEGRITY_NOLABEL; |
135 | else if (rc == 0) | 134 | else if (rc == 0) |
136 | evm_status = INTEGRITY_NOXATTRS; /* new file */ | 135 | evm_status = INTEGRITY_NOXATTRS; /* new file */ |
136 | } else if (rc == -EOPNOTSUPP) { | ||
137 | evm_status = INTEGRITY_UNKNOWN; | ||
137 | } | 138 | } |
138 | goto out; | 139 | goto out; |
139 | } | 140 | } |
@@ -284,6 +285,13 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, | |||
284 | goto out; | 285 | goto out; |
285 | } | 286 | } |
286 | evm_status = evm_verify_current_integrity(dentry); | 287 | evm_status = evm_verify_current_integrity(dentry); |
288 | if (evm_status == INTEGRITY_NOXATTRS) { | ||
289 | struct integrity_iint_cache *iint; | ||
290 | |||
291 | iint = integrity_iint_find(dentry->d_inode); | ||
292 | if (iint && (iint->flags & IMA_NEW_FILE)) | ||
293 | return 0; | ||
294 | } | ||
287 | out: | 295 | out: |
288 | if (evm_status != INTEGRITY_PASS) | 296 | if (evm_status != INTEGRITY_PASS) |
289 | integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, | 297 | integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode, |
@@ -352,7 +360,6 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, | |||
352 | return; | 360 | return; |
353 | 361 | ||
354 | evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); | 362 | evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); |
355 | return; | ||
356 | } | 363 | } |
357 | 364 | ||
358 | /** | 365 | /** |
@@ -372,7 +379,6 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) | |||
372 | mutex_lock(&inode->i_mutex); | 379 | mutex_lock(&inode->i_mutex); |
373 | evm_update_evmxattr(dentry, xattr_name, NULL, 0); | 380 | evm_update_evmxattr(dentry, xattr_name, NULL, 0); |
374 | mutex_unlock(&inode->i_mutex); | 381 | mutex_unlock(&inode->i_mutex); |
375 | return; | ||
376 | } | 382 | } |
377 | 383 | ||
378 | /** | 384 | /** |
@@ -414,7 +420,6 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) | |||
414 | 420 | ||
415 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) | 421 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) |
416 | evm_update_evmxattr(dentry, NULL, NULL, 0); | 422 | evm_update_evmxattr(dentry, NULL, NULL, 0); |
417 | return; | ||
418 | } | 423 | } |
419 | 424 | ||
420 | /* | 425 | /* |
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 81a27971d884..e099875643c5 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig | |||
@@ -2,8 +2,6 @@ | |||
2 | # | 2 | # |
3 | config IMA | 3 | config IMA |
4 | bool "Integrity Measurement Architecture(IMA)" | 4 | bool "Integrity Measurement Architecture(IMA)" |
5 | depends on SECURITY | ||
6 | select INTEGRITY | ||
7 | select SECURITYFS | 5 | select SECURITYFS |
8 | select CRYPTO | 6 | select CRYPTO |
9 | select CRYPTO_HMAC | 7 | select CRYPTO_HMAC |
@@ -123,3 +121,13 @@ config IMA_APPRAISE | |||
123 | For more information on integrity appraisal refer to: | 121 | For more information on integrity appraisal refer to: |
124 | <http://linux-ima.sourceforge.net> | 122 | <http://linux-ima.sourceforge.net> |
125 | If unsure, say N. | 123 | If unsure, say N. |
124 | |||
125 | config IMA_TRUSTED_KEYRING | ||
126 | bool "Require all keys on the .ima keyring be signed" | ||
127 | depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING | ||
128 | depends on INTEGRITY_ASYMMETRIC_KEYS | ||
129 | select KEYS_DEBUG_PROC_KEYS | ||
130 | default y | ||
131 | help | ||
132 | This option requires that all keys added to the .ima | ||
133 | keyring be signed by a key on the system trusted keyring. | ||
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index f79fa8be203c..8e4bb883fc13 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -90,10 +90,7 @@ extern struct list_head ima_measurements; /* list of all measurements */ | |||
90 | 90 | ||
91 | /* Internal IMA function definitions */ | 91 | /* Internal IMA function definitions */ |
92 | int ima_init(void); | 92 | int ima_init(void); |
93 | void ima_cleanup(void); | ||
94 | int ima_fs_init(void); | 93 | int ima_fs_init(void); |
95 | void ima_fs_cleanup(void); | ||
96 | int ima_inode_alloc(struct inode *inode); | ||
97 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, | 94 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, |
98 | const char *op, struct inode *inode, | 95 | const char *op, struct inode *inode, |
99 | const unsigned char *filename); | 96 | const unsigned char *filename); |
@@ -110,8 +107,6 @@ void ima_print_digest(struct seq_file *m, u8 *digest, int size); | |||
110 | struct ima_template_desc *ima_template_desc_current(void); | 107 | struct ima_template_desc *ima_template_desc_current(void); |
111 | int ima_init_template(void); | 108 | int ima_init_template(void); |
112 | 109 | ||
113 | int ima_init_template(void); | ||
114 | |||
115 | /* | 110 | /* |
116 | * used to protect h_table and sha_table | 111 | * used to protect h_table and sha_table |
117 | */ | 112 | */ |
@@ -151,14 +146,8 @@ int ima_store_template(struct ima_template_entry *entry, int violation, | |||
151 | void ima_free_template_entry(struct ima_template_entry *entry); | 146 | void ima_free_template_entry(struct ima_template_entry *entry); |
152 | const char *ima_d_path(struct path *path, char **pathbuf); | 147 | const char *ima_d_path(struct path *path, char **pathbuf); |
153 | 148 | ||
154 | /* rbtree tree calls to lookup, insert, delete | ||
155 | * integrity data associated with an inode. | ||
156 | */ | ||
157 | struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | ||
158 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | ||
159 | |||
160 | /* IMA policy related functions */ | 149 | /* IMA policy related functions */ |
161 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, POST_SETATTR }; | 150 | enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR }; |
162 | 151 | ||
163 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, | 152 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, |
164 | int flags); | 153 | int flags); |
@@ -171,12 +160,13 @@ void ima_delete_rules(void); | |||
171 | #define IMA_APPRAISE_ENFORCE 0x01 | 160 | #define IMA_APPRAISE_ENFORCE 0x01 |
172 | #define IMA_APPRAISE_FIX 0x02 | 161 | #define IMA_APPRAISE_FIX 0x02 |
173 | #define IMA_APPRAISE_MODULES 0x04 | 162 | #define IMA_APPRAISE_MODULES 0x04 |
163 | #define IMA_APPRAISE_FIRMWARE 0x08 | ||
174 | 164 | ||
175 | #ifdef CONFIG_IMA_APPRAISE | 165 | #ifdef CONFIG_IMA_APPRAISE |
176 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | 166 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
177 | struct file *file, const unsigned char *filename, | 167 | struct file *file, const unsigned char *filename, |
178 | struct evm_ima_xattr_data *xattr_value, | 168 | struct evm_ima_xattr_data *xattr_value, |
179 | int xattr_len); | 169 | int xattr_len, int opened); |
180 | int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); | 170 | int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); |
181 | void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); | 171 | void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); |
182 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, | 172 | enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, |
@@ -192,7 +182,7 @@ static inline int ima_appraise_measurement(int func, | |||
192 | struct file *file, | 182 | struct file *file, |
193 | const unsigned char *filename, | 183 | const unsigned char *filename, |
194 | struct evm_ima_xattr_data *xattr_value, | 184 | struct evm_ima_xattr_data *xattr_value, |
195 | int xattr_len) | 185 | int xattr_len, int opened) |
196 | { | 186 | { |
197 | return INTEGRITY_UNKNOWN; | 187 | return INTEGRITY_UNKNOWN; |
198 | } | 188 | } |
@@ -249,4 +239,16 @@ static inline int security_filter_rule_match(u32 secid, u32 field, u32 op, | |||
249 | return -EINVAL; | 239 | return -EINVAL; |
250 | } | 240 | } |
251 | #endif /* CONFIG_IMA_LSM_RULES */ | 241 | #endif /* CONFIG_IMA_LSM_RULES */ |
242 | |||
243 | #ifdef CONFIG_IMA_TRUSTED_KEYRING | ||
244 | static inline int ima_init_keyring(const unsigned int id) | ||
245 | { | ||
246 | return integrity_init_keyring(id); | ||
247 | } | ||
248 | #else | ||
249 | static inline int ima_init_keyring(const unsigned int id) | ||
250 | { | ||
251 | return 0; | ||
252 | } | ||
253 | #endif /* CONFIG_IMA_TRUSTED_KEYRING */ | ||
252 | #endif | 254 | #endif |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index d9cd5ce14d2b..65c41a968cc1 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -330,10 +330,9 @@ const char *ima_d_path(struct path *path, char **pathbuf) | |||
330 | { | 330 | { |
331 | char *pathname = NULL; | 331 | char *pathname = NULL; |
332 | 332 | ||
333 | /* We will allow 11 spaces for ' (deleted)' to be appended */ | 333 | *pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); |
334 | *pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); | ||
335 | if (*pathbuf) { | 334 | if (*pathbuf) { |
336 | pathname = d_path(path, *pathbuf, PATH_MAX + 11); | 335 | pathname = d_absolute_path(path, *pathbuf, PATH_MAX); |
337 | if (IS_ERR(pathname)) { | 336 | if (IS_ERR(pathname)) { |
338 | kfree(*pathbuf); | 337 | kfree(*pathbuf); |
339 | *pathbuf = NULL; | 338 | *pathbuf = NULL; |
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index d3113d4aaa3c..013ec3f0e42d 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
@@ -75,6 +75,8 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, | |||
75 | return iint->ima_bprm_status; | 75 | return iint->ima_bprm_status; |
76 | case MODULE_CHECK: | 76 | case MODULE_CHECK: |
77 | return iint->ima_module_status; | 77 | return iint->ima_module_status; |
78 | case FIRMWARE_CHECK: | ||
79 | return iint->ima_firmware_status; | ||
78 | case FILE_CHECK: | 80 | case FILE_CHECK: |
79 | default: | 81 | default: |
80 | return iint->ima_file_status; | 82 | return iint->ima_file_status; |
@@ -94,6 +96,9 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, | |||
94 | case MODULE_CHECK: | 96 | case MODULE_CHECK: |
95 | iint->ima_module_status = status; | 97 | iint->ima_module_status = status; |
96 | break; | 98 | break; |
99 | case FIRMWARE_CHECK: | ||
100 | iint->ima_firmware_status = status; | ||
101 | break; | ||
97 | case FILE_CHECK: | 102 | case FILE_CHECK: |
98 | default: | 103 | default: |
99 | iint->ima_file_status = status; | 104 | iint->ima_file_status = status; |
@@ -113,6 +118,9 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func) | |||
113 | case MODULE_CHECK: | 118 | case MODULE_CHECK: |
114 | iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED); | 119 | iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED); |
115 | break; | 120 | break; |
121 | case FIRMWARE_CHECK: | ||
122 | iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED); | ||
123 | break; | ||
116 | case FILE_CHECK: | 124 | case FILE_CHECK: |
117 | default: | 125 | default: |
118 | iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); | 126 | iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); |
@@ -175,7 +183,7 @@ int ima_read_xattr(struct dentry *dentry, | |||
175 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | 183 | int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, |
176 | struct file *file, const unsigned char *filename, | 184 | struct file *file, const unsigned char *filename, |
177 | struct evm_ima_xattr_data *xattr_value, | 185 | struct evm_ima_xattr_data *xattr_value, |
178 | int xattr_len) | 186 | int xattr_len, int opened) |
179 | { | 187 | { |
180 | static const char op[] = "appraise_data"; | 188 | static const char op[] = "appraise_data"; |
181 | char *cause = "unknown"; | 189 | char *cause = "unknown"; |
@@ -184,8 +192,6 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | |||
184 | enum integrity_status status = INTEGRITY_UNKNOWN; | 192 | enum integrity_status status = INTEGRITY_UNKNOWN; |
185 | int rc = xattr_len, hash_start = 0; | 193 | int rc = xattr_len, hash_start = 0; |
186 | 194 | ||
187 | if (!ima_appraise) | ||
188 | return 0; | ||
189 | if (!inode->i_op->getxattr) | 195 | if (!inode->i_op->getxattr) |
190 | return INTEGRITY_UNKNOWN; | 196 | return INTEGRITY_UNKNOWN; |
191 | 197 | ||
@@ -194,8 +200,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | |||
194 | goto out; | 200 | goto out; |
195 | 201 | ||
196 | cause = "missing-hash"; | 202 | cause = "missing-hash"; |
197 | status = | 203 | status = INTEGRITY_NOLABEL; |
198 | (inode->i_size == 0) ? INTEGRITY_PASS : INTEGRITY_NOLABEL; | 204 | if (opened & FILE_CREATED) { |
205 | iint->flags |= IMA_NEW_FILE; | ||
206 | status = INTEGRITY_PASS; | ||
207 | } | ||
199 | goto out; | 208 | goto out; |
200 | } | 209 | } |
201 | 210 | ||
@@ -214,7 +223,7 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, | |||
214 | hash_start = 1; | 223 | hash_start = 1; |
215 | case IMA_XATTR_DIGEST: | 224 | case IMA_XATTR_DIGEST: |
216 | if (iint->flags & IMA_DIGSIG_REQUIRED) { | 225 | if (iint->flags & IMA_DIGSIG_REQUIRED) { |
217 | cause = "IMA signature required"; | 226 | cause = "IMA-signature-required"; |
218 | status = INTEGRITY_FAIL; | 227 | status = INTEGRITY_FAIL; |
219 | break; | 228 | break; |
220 | } | 229 | } |
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index ccd0ac8fa9a0..d34e7dfc1118 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 16 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
17 | 17 | ||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/ratelimit.h> | ||
19 | #include <linux/file.h> | 21 | #include <linux/file.h> |
20 | #include <linux/crypto.h> | 22 | #include <linux/crypto.h> |
21 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
@@ -25,7 +27,45 @@ | |||
25 | #include <crypto/hash_info.h> | 27 | #include <crypto/hash_info.h> |
26 | #include "ima.h" | 28 | #include "ima.h" |
27 | 29 | ||
30 | struct ahash_completion { | ||
31 | struct completion completion; | ||
32 | int err; | ||
33 | }; | ||
34 | |||
35 | /* minimum file size for ahash use */ | ||
36 | static unsigned long ima_ahash_minsize; | ||
37 | module_param_named(ahash_minsize, ima_ahash_minsize, ulong, 0644); | ||
38 | MODULE_PARM_DESC(ahash_minsize, "Minimum file size for ahash use"); | ||
39 | |||
40 | /* default is 0 - 1 page. */ | ||
41 | static int ima_maxorder; | ||
42 | static unsigned int ima_bufsize = PAGE_SIZE; | ||
43 | |||
44 | static int param_set_bufsize(const char *val, const struct kernel_param *kp) | ||
45 | { | ||
46 | unsigned long long size; | ||
47 | int order; | ||
48 | |||
49 | size = memparse(val, NULL); | ||
50 | order = get_order(size); | ||
51 | if (order >= MAX_ORDER) | ||
52 | return -EINVAL; | ||
53 | ima_maxorder = order; | ||
54 | ima_bufsize = PAGE_SIZE << order; | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static struct kernel_param_ops param_ops_bufsize = { | ||
59 | .set = param_set_bufsize, | ||
60 | .get = param_get_uint, | ||
61 | }; | ||
62 | #define param_check_bufsize(name, p) __param_check(name, p, unsigned int) | ||
63 | |||
64 | module_param_named(ahash_bufsize, ima_bufsize, bufsize, 0644); | ||
65 | MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size"); | ||
66 | |||
28 | static struct crypto_shash *ima_shash_tfm; | 67 | static struct crypto_shash *ima_shash_tfm; |
68 | static struct crypto_ahash *ima_ahash_tfm; | ||
29 | 69 | ||
30 | /** | 70 | /** |
31 | * ima_kernel_read - read file content | 71 | * ima_kernel_read - read file content |
@@ -40,24 +80,24 @@ static int ima_kernel_read(struct file *file, loff_t offset, | |||
40 | { | 80 | { |
41 | mm_segment_t old_fs; | 81 | mm_segment_t old_fs; |
42 | char __user *buf = addr; | 82 | char __user *buf = addr; |
43 | ssize_t ret; | 83 | ssize_t ret = -EINVAL; |
44 | 84 | ||
45 | if (!(file->f_mode & FMODE_READ)) | 85 | if (!(file->f_mode & FMODE_READ)) |
46 | return -EBADF; | 86 | return -EBADF; |
47 | if (!file->f_op->read && !file->f_op->aio_read) | ||
48 | return -EINVAL; | ||
49 | 87 | ||
50 | old_fs = get_fs(); | 88 | old_fs = get_fs(); |
51 | set_fs(get_ds()); | 89 | set_fs(get_ds()); |
52 | if (file->f_op->read) | 90 | if (file->f_op->read) |
53 | ret = file->f_op->read(file, buf, count, &offset); | 91 | ret = file->f_op->read(file, buf, count, &offset); |
54 | else | 92 | else if (file->f_op->aio_read) |
55 | ret = do_sync_read(file, buf, count, &offset); | 93 | ret = do_sync_read(file, buf, count, &offset); |
94 | else if (file->f_op->read_iter) | ||
95 | ret = new_sync_read(file, buf, count, &offset); | ||
56 | set_fs(old_fs); | 96 | set_fs(old_fs); |
57 | return ret; | 97 | return ret; |
58 | } | 98 | } |
59 | 99 | ||
60 | int ima_init_crypto(void) | 100 | int __init ima_init_crypto(void) |
61 | { | 101 | { |
62 | long rc; | 102 | long rc; |
63 | 103 | ||
@@ -76,7 +116,10 @@ static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo) | |||
76 | struct crypto_shash *tfm = ima_shash_tfm; | 116 | struct crypto_shash *tfm = ima_shash_tfm; |
77 | int rc; | 117 | int rc; |
78 | 118 | ||
79 | if (algo != ima_hash_algo && algo < HASH_ALGO__LAST) { | 119 | if (algo < 0 || algo >= HASH_ALGO__LAST) |
120 | algo = ima_hash_algo; | ||
121 | |||
122 | if (algo != ima_hash_algo) { | ||
80 | tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); | 123 | tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0); |
81 | if (IS_ERR(tfm)) { | 124 | if (IS_ERR(tfm)) { |
82 | rc = PTR_ERR(tfm); | 125 | rc = PTR_ERR(tfm); |
@@ -93,9 +136,249 @@ static void ima_free_tfm(struct crypto_shash *tfm) | |||
93 | crypto_free_shash(tfm); | 136 | crypto_free_shash(tfm); |
94 | } | 137 | } |
95 | 138 | ||
96 | /* | 139 | /** |
97 | * Calculate the MD5/SHA1 file digest | 140 | * ima_alloc_pages() - Allocate contiguous pages. |
141 | * @max_size: Maximum amount of memory to allocate. | ||
142 | * @allocated_size: Returned size of actual allocation. | ||
143 | * @last_warn: Should the min_size allocation warn or not. | ||
144 | * | ||
145 | * Tries to do opportunistic allocation for memory first trying to allocate | ||
146 | * max_size amount of memory and then splitting that until zero order is | ||
147 | * reached. Allocation is tried without generating allocation warnings unless | ||
148 | * last_warn is set. Last_warn set affects only last allocation of zero order. | ||
149 | * | ||
150 | * By default, ima_maxorder is 0 and it is equivalent to kmalloc(GFP_KERNEL) | ||
151 | * | ||
152 | * Return pointer to allocated memory, or NULL on failure. | ||
98 | */ | 153 | */ |
154 | static void *ima_alloc_pages(loff_t max_size, size_t *allocated_size, | ||
155 | int last_warn) | ||
156 | { | ||
157 | void *ptr; | ||
158 | int order = ima_maxorder; | ||
159 | gfp_t gfp_mask = __GFP_WAIT | __GFP_NOWARN | __GFP_NORETRY; | ||
160 | |||
161 | if (order) | ||
162 | order = min(get_order(max_size), order); | ||
163 | |||
164 | for (; order; order--) { | ||
165 | ptr = (void *)__get_free_pages(gfp_mask, order); | ||
166 | if (ptr) { | ||
167 | *allocated_size = PAGE_SIZE << order; | ||
168 | return ptr; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | /* order is zero - one page */ | ||
173 | |||
174 | gfp_mask = GFP_KERNEL; | ||
175 | |||
176 | if (!last_warn) | ||
177 | gfp_mask |= __GFP_NOWARN; | ||
178 | |||
179 | ptr = (void *)__get_free_pages(gfp_mask, 0); | ||
180 | if (ptr) { | ||
181 | *allocated_size = PAGE_SIZE; | ||
182 | return ptr; | ||
183 | } | ||
184 | |||
185 | *allocated_size = 0; | ||
186 | return NULL; | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * ima_free_pages() - Free pages allocated by ima_alloc_pages(). | ||
191 | * @ptr: Pointer to allocated pages. | ||
192 | * @size: Size of allocated buffer. | ||
193 | */ | ||
194 | static void ima_free_pages(void *ptr, size_t size) | ||
195 | { | ||
196 | if (!ptr) | ||
197 | return; | ||
198 | free_pages((unsigned long)ptr, get_order(size)); | ||
199 | } | ||
200 | |||
201 | static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo) | ||
202 | { | ||
203 | struct crypto_ahash *tfm = ima_ahash_tfm; | ||
204 | int rc; | ||
205 | |||
206 | if (algo < 0 || algo >= HASH_ALGO__LAST) | ||
207 | algo = ima_hash_algo; | ||
208 | |||
209 | if (algo != ima_hash_algo || !tfm) { | ||
210 | tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0); | ||
211 | if (!IS_ERR(tfm)) { | ||
212 | if (algo == ima_hash_algo) | ||
213 | ima_ahash_tfm = tfm; | ||
214 | } else { | ||
215 | rc = PTR_ERR(tfm); | ||
216 | pr_err("Can not allocate %s (reason: %d)\n", | ||
217 | hash_algo_name[algo], rc); | ||
218 | } | ||
219 | } | ||
220 | return tfm; | ||
221 | } | ||
222 | |||
223 | static void ima_free_atfm(struct crypto_ahash *tfm) | ||
224 | { | ||
225 | if (tfm != ima_ahash_tfm) | ||
226 | crypto_free_ahash(tfm); | ||
227 | } | ||
228 | |||
229 | static void ahash_complete(struct crypto_async_request *req, int err) | ||
230 | { | ||
231 | struct ahash_completion *res = req->data; | ||
232 | |||
233 | if (err == -EINPROGRESS) | ||
234 | return; | ||
235 | res->err = err; | ||
236 | complete(&res->completion); | ||
237 | } | ||
238 | |||
239 | static int ahash_wait(int err, struct ahash_completion *res) | ||
240 | { | ||
241 | switch (err) { | ||
242 | case 0: | ||
243 | break; | ||
244 | case -EINPROGRESS: | ||
245 | case -EBUSY: | ||
246 | wait_for_completion(&res->completion); | ||
247 | reinit_completion(&res->completion); | ||
248 | err = res->err; | ||
249 | /* fall through */ | ||
250 | default: | ||
251 | pr_crit_ratelimited("ahash calculation failed: err: %d\n", err); | ||
252 | } | ||
253 | |||
254 | return err; | ||
255 | } | ||
256 | |||
257 | static int ima_calc_file_hash_atfm(struct file *file, | ||
258 | struct ima_digest_data *hash, | ||
259 | struct crypto_ahash *tfm) | ||
260 | { | ||
261 | loff_t i_size, offset; | ||
262 | char *rbuf[2] = { NULL, }; | ||
263 | int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0; | ||
264 | struct ahash_request *req; | ||
265 | struct scatterlist sg[1]; | ||
266 | struct ahash_completion res; | ||
267 | size_t rbuf_size[2]; | ||
268 | |||
269 | hash->length = crypto_ahash_digestsize(tfm); | ||
270 | |||
271 | req = ahash_request_alloc(tfm, GFP_KERNEL); | ||
272 | if (!req) | ||
273 | return -ENOMEM; | ||
274 | |||
275 | init_completion(&res.completion); | ||
276 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | | ||
277 | CRYPTO_TFM_REQ_MAY_SLEEP, | ||
278 | ahash_complete, &res); | ||
279 | |||
280 | rc = ahash_wait(crypto_ahash_init(req), &res); | ||
281 | if (rc) | ||
282 | goto out1; | ||
283 | |||
284 | i_size = i_size_read(file_inode(file)); | ||
285 | |||
286 | if (i_size == 0) | ||
287 | goto out2; | ||
288 | |||
289 | /* | ||
290 | * Try to allocate maximum size of memory. | ||
291 | * Fail if even a single page cannot be allocated. | ||
292 | */ | ||
293 | rbuf[0] = ima_alloc_pages(i_size, &rbuf_size[0], 1); | ||
294 | if (!rbuf[0]) { | ||
295 | rc = -ENOMEM; | ||
296 | goto out1; | ||
297 | } | ||
298 | |||
299 | /* Only allocate one buffer if that is enough. */ | ||
300 | if (i_size > rbuf_size[0]) { | ||
301 | /* | ||
302 | * Try to allocate secondary buffer. If that fails fallback to | ||
303 | * using single buffering. Use previous memory allocation size | ||
304 | * as baseline for possible allocation size. | ||
305 | */ | ||
306 | rbuf[1] = ima_alloc_pages(i_size - rbuf_size[0], | ||
307 | &rbuf_size[1], 0); | ||
308 | } | ||
309 | |||
310 | if (!(file->f_mode & FMODE_READ)) { | ||
311 | file->f_mode |= FMODE_READ; | ||
312 | read = 1; | ||
313 | } | ||
314 | |||
315 | for (offset = 0; offset < i_size; offset += rbuf_len) { | ||
316 | if (!rbuf[1] && offset) { | ||
317 | /* Not using two buffers, and it is not the first | ||
318 | * read/request, wait for the completion of the | ||
319 | * previous ahash_update() request. | ||
320 | */ | ||
321 | rc = ahash_wait(ahash_rc, &res); | ||
322 | if (rc) | ||
323 | goto out3; | ||
324 | } | ||
325 | /* read buffer */ | ||
326 | rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]); | ||
327 | rc = ima_kernel_read(file, offset, rbuf[active], rbuf_len); | ||
328 | if (rc != rbuf_len) | ||
329 | goto out3; | ||
330 | |||
331 | if (rbuf[1] && offset) { | ||
332 | /* Using two buffers, and it is not the first | ||
333 | * read/request, wait for the completion of the | ||
334 | * previous ahash_update() request. | ||
335 | */ | ||
336 | rc = ahash_wait(ahash_rc, &res); | ||
337 | if (rc) | ||
338 | goto out3; | ||
339 | } | ||
340 | |||
341 | sg_init_one(&sg[0], rbuf[active], rbuf_len); | ||
342 | ahash_request_set_crypt(req, sg, NULL, rbuf_len); | ||
343 | |||
344 | ahash_rc = crypto_ahash_update(req); | ||
345 | |||
346 | if (rbuf[1]) | ||
347 | active = !active; /* swap buffers, if we use two */ | ||
348 | } | ||
349 | /* wait for the last update request to complete */ | ||
350 | rc = ahash_wait(ahash_rc, &res); | ||
351 | out3: | ||
352 | if (read) | ||
353 | file->f_mode &= ~FMODE_READ; | ||
354 | ima_free_pages(rbuf[0], rbuf_size[0]); | ||
355 | ima_free_pages(rbuf[1], rbuf_size[1]); | ||
356 | out2: | ||
357 | if (!rc) { | ||
358 | ahash_request_set_crypt(req, NULL, hash->digest, 0); | ||
359 | rc = ahash_wait(crypto_ahash_final(req), &res); | ||
360 | } | ||
361 | out1: | ||
362 | ahash_request_free(req); | ||
363 | return rc; | ||
364 | } | ||
365 | |||
366 | static int ima_calc_file_ahash(struct file *file, struct ima_digest_data *hash) | ||
367 | { | ||
368 | struct crypto_ahash *tfm; | ||
369 | int rc; | ||
370 | |||
371 | tfm = ima_alloc_atfm(hash->algo); | ||
372 | if (IS_ERR(tfm)) | ||
373 | return PTR_ERR(tfm); | ||
374 | |||
375 | rc = ima_calc_file_hash_atfm(file, hash, tfm); | ||
376 | |||
377 | ima_free_atfm(tfm); | ||
378 | |||
379 | return rc; | ||
380 | } | ||
381 | |||
99 | static int ima_calc_file_hash_tfm(struct file *file, | 382 | static int ima_calc_file_hash_tfm(struct file *file, |
100 | struct ima_digest_data *hash, | 383 | struct ima_digest_data *hash, |
101 | struct crypto_shash *tfm) | 384 | struct crypto_shash *tfm) |
@@ -156,7 +439,7 @@ out: | |||
156 | return rc; | 439 | return rc; |
157 | } | 440 | } |
158 | 441 | ||
159 | int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) | 442 | static int ima_calc_file_shash(struct file *file, struct ima_digest_data *hash) |
160 | { | 443 | { |
161 | struct crypto_shash *tfm; | 444 | struct crypto_shash *tfm; |
162 | int rc; | 445 | int rc; |
@@ -173,6 +456,35 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) | |||
173 | } | 456 | } |
174 | 457 | ||
175 | /* | 458 | /* |
459 | * ima_calc_file_hash - calculate file hash | ||
460 | * | ||
461 | * Asynchronous hash (ahash) allows using HW acceleration for calculating | ||
462 | * a hash. ahash performance varies for different data sizes on different | ||
463 | * crypto accelerators. shash performance might be better for smaller files. | ||
464 | * The 'ima.ahash_minsize' module parameter allows specifying the best | ||
465 | * minimum file size for using ahash on the system. | ||
466 | * | ||
467 | * If the ima.ahash_minsize parameter is not specified, this function uses | ||
468 | * shash for the hash calculation. If ahash fails, it falls back to using | ||
469 | * shash. | ||
470 | */ | ||
471 | int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) | ||
472 | { | ||
473 | loff_t i_size; | ||
474 | int rc; | ||
475 | |||
476 | i_size = i_size_read(file_inode(file)); | ||
477 | |||
478 | if (ima_ahash_minsize && i_size >= ima_ahash_minsize) { | ||
479 | rc = ima_calc_file_ahash(file, hash); | ||
480 | if (!rc) | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | return ima_calc_file_shash(file, hash); | ||
485 | } | ||
486 | |||
487 | /* | ||
176 | * Calculate the hash of template data | 488 | * Calculate the hash of template data |
177 | */ | 489 | */ |
178 | static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, | 490 | static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 09baa335ebc7..673a37e92ba3 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -88,8 +88,6 @@ static void ima_rdwr_violation_check(struct file *file) | |||
88 | if (!S_ISREG(inode->i_mode) || !ima_initialized) | 88 | if (!S_ISREG(inode->i_mode) || !ima_initialized) |
89 | return; | 89 | return; |
90 | 90 | ||
91 | mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ | ||
92 | |||
93 | if (mode & FMODE_WRITE) { | 91 | if (mode & FMODE_WRITE) { |
94 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { | 92 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { |
95 | struct integrity_iint_cache *iint; | 93 | struct integrity_iint_cache *iint; |
@@ -104,8 +102,6 @@ static void ima_rdwr_violation_check(struct file *file) | |||
104 | send_writers = true; | 102 | send_writers = true; |
105 | } | 103 | } |
106 | 104 | ||
107 | mutex_unlock(&inode->i_mutex); | ||
108 | |||
109 | if (!send_tomtou && !send_writers) | 105 | if (!send_tomtou && !send_writers) |
110 | return; | 106 | return; |
111 | 107 | ||
@@ -128,11 +124,13 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, | |||
128 | return; | 124 | return; |
129 | 125 | ||
130 | mutex_lock(&inode->i_mutex); | 126 | mutex_lock(&inode->i_mutex); |
131 | if (atomic_read(&inode->i_writecount) == 1 && | 127 | if (atomic_read(&inode->i_writecount) == 1) { |
132 | iint->version != inode->i_version) { | 128 | if ((iint->version != inode->i_version) || |
133 | iint->flags &= ~IMA_DONE_MASK; | 129 | (iint->flags & IMA_NEW_FILE)) { |
134 | if (iint->flags & IMA_APPRAISE) | 130 | iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); |
135 | ima_update_xattr(iint, file); | 131 | if (iint->flags & IMA_APPRAISE) |
132 | ima_update_xattr(iint, file); | ||
133 | } | ||
136 | } | 134 | } |
137 | mutex_unlock(&inode->i_mutex); | 135 | mutex_unlock(&inode->i_mutex); |
138 | } | 136 | } |
@@ -158,15 +156,15 @@ void ima_file_free(struct file *file) | |||
158 | ima_check_last_writer(iint, inode, file); | 156 | ima_check_last_writer(iint, inode, file); |
159 | } | 157 | } |
160 | 158 | ||
161 | static int process_measurement(struct file *file, const char *filename, | 159 | static int process_measurement(struct file *file, int mask, int function, |
162 | int mask, int function) | 160 | int opened) |
163 | { | 161 | { |
164 | struct inode *inode = file_inode(file); | 162 | struct inode *inode = file_inode(file); |
165 | struct integrity_iint_cache *iint; | 163 | struct integrity_iint_cache *iint; |
166 | struct ima_template_desc *template_desc = ima_template_desc_current(); | 164 | struct ima_template_desc *template_desc; |
167 | char *pathbuf = NULL; | 165 | char *pathbuf = NULL; |
168 | const char *pathname = NULL; | 166 | const char *pathname = NULL; |
169 | int rc = -ENOMEM, action, must_appraise, _func; | 167 | int rc = -ENOMEM, action, must_appraise; |
170 | struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; | 168 | struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; |
171 | int xattr_len = 0; | 169 | int xattr_len = 0; |
172 | 170 | ||
@@ -184,7 +182,8 @@ static int process_measurement(struct file *file, const char *filename, | |||
184 | must_appraise = action & IMA_APPRAISE; | 182 | must_appraise = action & IMA_APPRAISE; |
185 | 183 | ||
186 | /* Is the appraise rule hook specific? */ | 184 | /* Is the appraise rule hook specific? */ |
187 | _func = (action & IMA_FILE_APPRAISE) ? FILE_CHECK : function; | 185 | if (action & IMA_FILE_APPRAISE) |
186 | function = FILE_CHECK; | ||
188 | 187 | ||
189 | mutex_lock(&inode->i_mutex); | 188 | mutex_lock(&inode->i_mutex); |
190 | 189 | ||
@@ -203,14 +202,13 @@ static int process_measurement(struct file *file, const char *filename, | |||
203 | /* Nothing to do, just return existing appraised status */ | 202 | /* Nothing to do, just return existing appraised status */ |
204 | if (!action) { | 203 | if (!action) { |
205 | if (must_appraise) | 204 | if (must_appraise) |
206 | rc = ima_get_cache_status(iint, _func); | 205 | rc = ima_get_cache_status(iint, function); |
207 | goto out_digsig; | 206 | goto out_digsig; |
208 | } | 207 | } |
209 | 208 | ||
210 | if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) { | 209 | template_desc = ima_template_desc_current(); |
211 | if (action & IMA_APPRAISE_SUBMASK) | 210 | if ((action & IMA_APPRAISE_SUBMASK) || |
212 | xattr_ptr = &xattr_value; | 211 | strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) |
213 | } else | ||
214 | xattr_ptr = &xattr_value; | 212 | xattr_ptr = &xattr_value; |
215 | 213 | ||
216 | rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); | 214 | rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); |
@@ -220,14 +218,14 @@ static int process_measurement(struct file *file, const char *filename, | |||
220 | goto out_digsig; | 218 | goto out_digsig; |
221 | } | 219 | } |
222 | 220 | ||
223 | pathname = filename ?: ima_d_path(&file->f_path, &pathbuf); | 221 | pathname = ima_d_path(&file->f_path, &pathbuf); |
224 | 222 | ||
225 | if (action & IMA_MEASURE) | 223 | if (action & IMA_MEASURE) |
226 | ima_store_measurement(iint, file, pathname, | 224 | ima_store_measurement(iint, file, pathname, |
227 | xattr_value, xattr_len); | 225 | xattr_value, xattr_len); |
228 | if (action & IMA_APPRAISE_SUBMASK) | 226 | if (action & IMA_APPRAISE_SUBMASK) |
229 | rc = ima_appraise_measurement(_func, iint, file, pathname, | 227 | rc = ima_appraise_measurement(function, iint, file, pathname, |
230 | xattr_value, xattr_len); | 228 | xattr_value, xattr_len, opened); |
231 | if (action & IMA_AUDIT) | 229 | if (action & IMA_AUDIT) |
232 | ima_audit_measurement(iint, pathname); | 230 | ima_audit_measurement(iint, pathname); |
233 | kfree(pathbuf); | 231 | kfree(pathbuf); |
@@ -256,7 +254,7 @@ out: | |||
256 | int ima_file_mmap(struct file *file, unsigned long prot) | 254 | int ima_file_mmap(struct file *file, unsigned long prot) |
257 | { | 255 | { |
258 | if (file && (prot & PROT_EXEC)) | 256 | if (file && (prot & PROT_EXEC)) |
259 | return process_measurement(file, NULL, MAY_EXEC, MMAP_CHECK); | 257 | return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0); |
260 | return 0; | 258 | return 0; |
261 | } | 259 | } |
262 | 260 | ||
@@ -275,10 +273,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) | |||
275 | */ | 273 | */ |
276 | int ima_bprm_check(struct linux_binprm *bprm) | 274 | int ima_bprm_check(struct linux_binprm *bprm) |
277 | { | 275 | { |
278 | return process_measurement(bprm->file, | 276 | return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0); |
279 | (strcmp(bprm->filename, bprm->interp) == 0) ? | ||
280 | bprm->filename : bprm->interp, | ||
281 | MAY_EXEC, BPRM_CHECK); | ||
282 | } | 277 | } |
283 | 278 | ||
284 | /** | 279 | /** |
@@ -291,12 +286,12 @@ int ima_bprm_check(struct linux_binprm *bprm) | |||
291 | * On success return 0. On integrity appraisal error, assuming the file | 286 | * On success return 0. On integrity appraisal error, assuming the file |
292 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. | 287 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. |
293 | */ | 288 | */ |
294 | int ima_file_check(struct file *file, int mask) | 289 | int ima_file_check(struct file *file, int mask, int opened) |
295 | { | 290 | { |
296 | ima_rdwr_violation_check(file); | 291 | ima_rdwr_violation_check(file); |
297 | return process_measurement(file, NULL, | 292 | return process_measurement(file, |
298 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | 293 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
299 | FILE_CHECK); | 294 | FILE_CHECK, opened); |
300 | } | 295 | } |
301 | EXPORT_SYMBOL_GPL(ima_file_check); | 296 | EXPORT_SYMBOL_GPL(ima_file_check); |
302 | 297 | ||
@@ -319,7 +314,18 @@ int ima_module_check(struct file *file) | |||
319 | #endif | 314 | #endif |
320 | return 0; /* We rely on module signature checking */ | 315 | return 0; /* We rely on module signature checking */ |
321 | } | 316 | } |
322 | return process_measurement(file, NULL, MAY_EXEC, MODULE_CHECK); | 317 | return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0); |
318 | } | ||
319 | |||
320 | int ima_fw_from_file(struct file *file, char *buf, size_t size) | ||
321 | { | ||
322 | if (!file) { | ||
323 | if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && | ||
324 | (ima_appraise & IMA_APPRAISE_ENFORCE)) | ||
325 | return -EACCES; /* INTEGRITY_UNKNOWN */ | ||
326 | return 0; | ||
327 | } | ||
328 | return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0); | ||
323 | } | 329 | } |
324 | 330 | ||
325 | static int __init init_ima(void) | 331 | static int __init init_ima(void) |
@@ -328,8 +334,14 @@ static int __init init_ima(void) | |||
328 | 334 | ||
329 | hash_setup(CONFIG_IMA_DEFAULT_HASH); | 335 | hash_setup(CONFIG_IMA_DEFAULT_HASH); |
330 | error = ima_init(); | 336 | error = ima_init(); |
331 | if (!error) | 337 | if (error) |
332 | ima_initialized = 1; | 338 | goto out; |
339 | |||
340 | error = ima_init_keyring(INTEGRITY_KEYRING_IMA); | ||
341 | if (error) | ||
342 | goto out; | ||
343 | ima_initialized = 1; | ||
344 | out: | ||
333 | return error; | 345 | return error; |
334 | } | 346 | } |
335 | 347 | ||
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 40a7488f6721..07099a8bc283 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
@@ -84,6 +84,7 @@ static struct ima_rule_entry default_rules[] = { | |||
84 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID, | 84 | {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID, |
85 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, | 85 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, |
86 | {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, | 86 | {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, |
87 | {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, | ||
87 | }; | 88 | }; |
88 | 89 | ||
89 | static struct ima_rule_entry default_appraise_rules[] = { | 90 | static struct ima_rule_entry default_appraise_rules[] = { |
@@ -241,6 +242,8 @@ static int get_subaction(struct ima_rule_entry *rule, int func) | |||
241 | return IMA_BPRM_APPRAISE; | 242 | return IMA_BPRM_APPRAISE; |
242 | case MODULE_CHECK: | 243 | case MODULE_CHECK: |
243 | return IMA_MODULE_APPRAISE; | 244 | return IMA_MODULE_APPRAISE; |
245 | case FIRMWARE_CHECK: | ||
246 | return IMA_FIRMWARE_APPRAISE; | ||
244 | case FILE_CHECK: | 247 | case FILE_CHECK: |
245 | default: | 248 | default: |
246 | return IMA_FILE_APPRAISE; | 249 | return IMA_FILE_APPRAISE; |
@@ -332,7 +335,7 @@ void __init ima_init_policy(void) | |||
332 | void ima_update_policy(void) | 335 | void ima_update_policy(void) |
333 | { | 336 | { |
334 | static const char op[] = "policy_update"; | 337 | static const char op[] = "policy_update"; |
335 | const char *cause = "already exists"; | 338 | const char *cause = "already-exists"; |
336 | int result = 1; | 339 | int result = 1; |
337 | int audit_info = 0; | 340 | int audit_info = 0; |
338 | 341 | ||
@@ -486,6 +489,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
486 | entry->func = FILE_CHECK; | 489 | entry->func = FILE_CHECK; |
487 | else if (strcmp(args[0].from, "MODULE_CHECK") == 0) | 490 | else if (strcmp(args[0].from, "MODULE_CHECK") == 0) |
488 | entry->func = MODULE_CHECK; | 491 | entry->func = MODULE_CHECK; |
492 | else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0) | ||
493 | entry->func = FIRMWARE_CHECK; | ||
489 | else if ((strcmp(args[0].from, "FILE_MMAP") == 0) | 494 | else if ((strcmp(args[0].from, "FILE_MMAP") == 0) |
490 | || (strcmp(args[0].from, "MMAP_CHECK") == 0)) | 495 | || (strcmp(args[0].from, "MMAP_CHECK") == 0)) |
491 | entry->func = MMAP_CHECK; | 496 | entry->func = MMAP_CHECK; |
@@ -636,6 +641,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
636 | result = -EINVAL; | 641 | result = -EINVAL; |
637 | else if (entry->func == MODULE_CHECK) | 642 | else if (entry->func == MODULE_CHECK) |
638 | ima_appraise |= IMA_APPRAISE_MODULES; | 643 | ima_appraise |= IMA_APPRAISE_MODULES; |
644 | else if (entry->func == FIRMWARE_CHECK) | ||
645 | ima_appraise |= IMA_APPRAISE_FIRMWARE; | ||
639 | audit_log_format(ab, "res=%d", !result); | 646 | audit_log_format(ab, "res=%d", !result); |
640 | audit_log_end(ab); | 647 | audit_log_end(ab); |
641 | return result; | 648 | return result; |
@@ -659,7 +666,7 @@ ssize_t ima_parse_add_rule(char *rule) | |||
659 | /* Prevent installed policy from changing */ | 666 | /* Prevent installed policy from changing */ |
660 | if (ima_rules != &ima_default_rules) { | 667 | if (ima_rules != &ima_default_rules) { |
661 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, | 668 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, |
662 | NULL, op, "already exists", | 669 | NULL, op, "already-exists", |
663 | -EACCES, audit_info); | 670 | -EACCES, audit_info); |
664 | return -EACCES; | 671 | return -EACCES; |
665 | } | 672 | } |
@@ -685,7 +692,7 @@ ssize_t ima_parse_add_rule(char *rule) | |||
685 | if (result) { | 692 | if (result) { |
686 | kfree(entry); | 693 | kfree(entry); |
687 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, | 694 | integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, |
688 | NULL, op, "invalid policy", result, | 695 | NULL, op, "invalid-policy", result, |
689 | audit_info); | 696 | audit_info); |
690 | return result; | 697 | return result; |
691 | } | 698 | } |
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index a076a967ec47..e854862c9337 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c | |||
@@ -152,24 +152,6 @@ out: | |||
152 | return result; | 152 | return result; |
153 | } | 153 | } |
154 | 154 | ||
155 | static int init_defined_templates(void) | ||
156 | { | ||
157 | int i = 0; | ||
158 | int result = 0; | ||
159 | |||
160 | /* Init defined templates. */ | ||
161 | for (i = 0; i < ARRAY_SIZE(defined_templates); i++) { | ||
162 | struct ima_template_desc *template = &defined_templates[i]; | ||
163 | |||
164 | result = template_desc_init_fields(template->fmt, | ||
165 | &(template->fields), | ||
166 | &(template->num_fields)); | ||
167 | if (result < 0) | ||
168 | return result; | ||
169 | } | ||
170 | return result; | ||
171 | } | ||
172 | |||
173 | struct ima_template_desc *ima_template_desc_current(void) | 155 | struct ima_template_desc *ima_template_desc_current(void) |
174 | { | 156 | { |
175 | if (!ima_template) | 157 | if (!ima_template) |
@@ -178,13 +160,11 @@ struct ima_template_desc *ima_template_desc_current(void) | |||
178 | return ima_template; | 160 | return ima_template; |
179 | } | 161 | } |
180 | 162 | ||
181 | int ima_init_template(void) | 163 | int __init ima_init_template(void) |
182 | { | 164 | { |
183 | int result; | 165 | struct ima_template_desc *template = ima_template_desc_current(); |
184 | |||
185 | result = init_defined_templates(); | ||
186 | if (result < 0) | ||
187 | return result; | ||
188 | 166 | ||
189 | return 0; | 167 | return template_desc_init_fields(template->fmt, |
168 | &(template->fields), | ||
169 | &(template->num_fields)); | ||
190 | } | 170 | } |
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 33c0a70f6b15..c0379d13dbe1 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #define IMA_DIGSIG 0x01000000 | 31 | #define IMA_DIGSIG 0x01000000 |
32 | #define IMA_DIGSIG_REQUIRED 0x02000000 | 32 | #define IMA_DIGSIG_REQUIRED 0x02000000 |
33 | #define IMA_PERMIT_DIRECTIO 0x04000000 | 33 | #define IMA_PERMIT_DIRECTIO 0x04000000 |
34 | #define IMA_NEW_FILE 0x08000000 | ||
34 | 35 | ||
35 | #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ | 36 | #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ |
36 | IMA_APPRAISE_SUBMASK) | 37 | IMA_APPRAISE_SUBMASK) |
@@ -46,10 +47,14 @@ | |||
46 | #define IMA_BPRM_APPRAISED 0x00002000 | 47 | #define IMA_BPRM_APPRAISED 0x00002000 |
47 | #define IMA_MODULE_APPRAISE 0x00004000 | 48 | #define IMA_MODULE_APPRAISE 0x00004000 |
48 | #define IMA_MODULE_APPRAISED 0x00008000 | 49 | #define IMA_MODULE_APPRAISED 0x00008000 |
50 | #define IMA_FIRMWARE_APPRAISE 0x00010000 | ||
51 | #define IMA_FIRMWARE_APPRAISED 0x00020000 | ||
49 | #define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ | 52 | #define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ |
50 | IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE) | 53 | IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \ |
54 | IMA_FIRMWARE_APPRAISE) | ||
51 | #define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ | 55 | #define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ |
52 | IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED) | 56 | IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \ |
57 | IMA_FIRMWARE_APPRAISED) | ||
53 | 58 | ||
54 | enum evm_ima_xattr_type { | 59 | enum evm_ima_xattr_type { |
55 | IMA_XATTR_DIGEST = 0x01, | 60 | IMA_XATTR_DIGEST = 0x01, |
@@ -104,6 +109,7 @@ struct integrity_iint_cache { | |||
104 | enum integrity_status ima_mmap_status:4; | 109 | enum integrity_status ima_mmap_status:4; |
105 | enum integrity_status ima_bprm_status:4; | 110 | enum integrity_status ima_bprm_status:4; |
106 | enum integrity_status ima_module_status:4; | 111 | enum integrity_status ima_module_status:4; |
112 | enum integrity_status ima_firmware_status:4; | ||
107 | enum integrity_status evm_status:4; | 113 | enum integrity_status evm_status:4; |
108 | struct ima_digest_data *ima_hash; | 114 | struct ima_digest_data *ima_hash; |
109 | }; | 115 | }; |
@@ -111,7 +117,6 @@ struct integrity_iint_cache { | |||
111 | /* rbtree tree calls to lookup, insert, delete | 117 | /* rbtree tree calls to lookup, insert, delete |
112 | * integrity data associated with an inode. | 118 | * integrity data associated with an inode. |
113 | */ | 119 | */ |
114 | struct integrity_iint_cache *integrity_iint_insert(struct inode *inode); | ||
115 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | 120 | struct integrity_iint_cache *integrity_iint_find(struct inode *inode); |
116 | 121 | ||
117 | #define INTEGRITY_KEYRING_EVM 0 | 122 | #define INTEGRITY_KEYRING_EVM 0 |
@@ -124,6 +129,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode); | |||
124 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | 129 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, |
125 | const char *digest, int digestlen); | 130 | const char *digest, int digestlen); |
126 | 131 | ||
132 | int integrity_init_keyring(const unsigned int id); | ||
127 | #else | 133 | #else |
128 | 134 | ||
129 | static inline int integrity_digsig_verify(const unsigned int id, | 135 | static inline int integrity_digsig_verify(const unsigned int id, |
@@ -133,6 +139,10 @@ static inline int integrity_digsig_verify(const unsigned int id, | |||
133 | return -EOPNOTSUPP; | 139 | return -EOPNOTSUPP; |
134 | } | 140 | } |
135 | 141 | ||
142 | static inline int integrity_init_keyring(const unsigned int id) | ||
143 | { | ||
144 | return 0; | ||
145 | } | ||
136 | #endif /* CONFIG_INTEGRITY_SIGNATURE */ | 146 | #endif /* CONFIG_INTEGRITY_SIGNATURE */ |
137 | 147 | ||
138 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS | 148 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS |
diff --git a/security/keys/big_key.c b/security/keys/big_key.c index 8137b27d641d..b6adb94f6d52 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c | |||
@@ -33,9 +33,9 @@ MODULE_LICENSE("GPL"); | |||
33 | */ | 33 | */ |
34 | struct key_type key_type_big_key = { | 34 | struct key_type key_type_big_key = { |
35 | .name = "big_key", | 35 | .name = "big_key", |
36 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 36 | .preparse = big_key_preparse, |
37 | .instantiate = big_key_instantiate, | 37 | .free_preparse = big_key_free_preparse, |
38 | .match = user_match, | 38 | .instantiate = generic_key_instantiate, |
39 | .revoke = big_key_revoke, | 39 | .revoke = big_key_revoke, |
40 | .destroy = big_key_destroy, | 40 | .destroy = big_key_destroy, |
41 | .describe = big_key_describe, | 41 | .describe = big_key_describe, |
@@ -43,11 +43,11 @@ struct key_type key_type_big_key = { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Instantiate a big key | 46 | * Preparse a big key |
47 | */ | 47 | */ |
48 | int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | 48 | int big_key_preparse(struct key_preparsed_payload *prep) |
49 | { | 49 | { |
50 | struct path *path = (struct path *)&key->payload.data2; | 50 | struct path *path = (struct path *)&prep->payload; |
51 | struct file *file; | 51 | struct file *file; |
52 | ssize_t written; | 52 | ssize_t written; |
53 | size_t datalen = prep->datalen; | 53 | size_t datalen = prep->datalen; |
@@ -58,11 +58,9 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
58 | goto error; | 58 | goto error; |
59 | 59 | ||
60 | /* Set an arbitrary quota */ | 60 | /* Set an arbitrary quota */ |
61 | ret = key_payload_reserve(key, 16); | 61 | prep->quotalen = 16; |
62 | if (ret < 0) | ||
63 | goto error; | ||
64 | 62 | ||
65 | key->type_data.x[1] = datalen; | 63 | prep->type_data[1] = (void *)(unsigned long)datalen; |
66 | 64 | ||
67 | if (datalen > BIG_KEY_FILE_THRESHOLD) { | 65 | if (datalen > BIG_KEY_FILE_THRESHOLD) { |
68 | /* Create a shmem file to store the data in. This will permit the data | 66 | /* Create a shmem file to store the data in. This will permit the data |
@@ -73,7 +71,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
73 | file = shmem_kernel_file_setup("", datalen, 0); | 71 | file = shmem_kernel_file_setup("", datalen, 0); |
74 | if (IS_ERR(file)) { | 72 | if (IS_ERR(file)) { |
75 | ret = PTR_ERR(file); | 73 | ret = PTR_ERR(file); |
76 | goto err_quota; | 74 | goto error; |
77 | } | 75 | } |
78 | 76 | ||
79 | written = kernel_write(file, prep->data, prep->datalen, 0); | 77 | written = kernel_write(file, prep->data, prep->datalen, 0); |
@@ -93,24 +91,33 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
93 | } else { | 91 | } else { |
94 | /* Just store the data in a buffer */ | 92 | /* Just store the data in a buffer */ |
95 | void *data = kmalloc(datalen, GFP_KERNEL); | 93 | void *data = kmalloc(datalen, GFP_KERNEL); |
96 | if (!data) { | 94 | if (!data) |
97 | ret = -ENOMEM; | 95 | return -ENOMEM; |
98 | goto err_quota; | ||
99 | } | ||
100 | 96 | ||
101 | key->payload.data = memcpy(data, prep->data, prep->datalen); | 97 | prep->payload[0] = memcpy(data, prep->data, prep->datalen); |
102 | } | 98 | } |
103 | return 0; | 99 | return 0; |
104 | 100 | ||
105 | err_fput: | 101 | err_fput: |
106 | fput(file); | 102 | fput(file); |
107 | err_quota: | ||
108 | key_payload_reserve(key, 0); | ||
109 | error: | 103 | error: |
110 | return ret; | 104 | return ret; |
111 | } | 105 | } |
112 | 106 | ||
113 | /* | 107 | /* |
108 | * Clear preparsement. | ||
109 | */ | ||
110 | void big_key_free_preparse(struct key_preparsed_payload *prep) | ||
111 | { | ||
112 | if (prep->datalen > BIG_KEY_FILE_THRESHOLD) { | ||
113 | struct path *path = (struct path *)&prep->payload; | ||
114 | path_put(path); | ||
115 | } else { | ||
116 | kfree(prep->payload[0]); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | /* | ||
114 | * dispose of the links from a revoked keyring | 121 | * dispose of the links from a revoked keyring |
115 | * - called with the key sem write-locked | 122 | * - called with the key sem write-locked |
116 | */ | 123 | */ |
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 5fe443d120af..db9675db1026 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c | |||
@@ -970,7 +970,6 @@ struct key_type key_type_encrypted = { | |||
970 | .name = "encrypted", | 970 | .name = "encrypted", |
971 | .instantiate = encrypted_instantiate, | 971 | .instantiate = encrypted_instantiate, |
972 | .update = encrypted_update, | 972 | .update = encrypted_update, |
973 | .match = user_match, | ||
974 | .destroy = encrypted_destroy, | 973 | .destroy = encrypted_destroy, |
975 | .describe = user_describe, | 974 | .describe = user_describe, |
976 | .read = encrypted_read, | 975 | .read = encrypted_read, |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 5f20da01fd8d..b8960c4959a5 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -107,20 +107,16 @@ extern int iterate_over_keyring(const struct key *keyring, | |||
107 | int (*func)(const struct key *key, void *data), | 107 | int (*func)(const struct key *key, void *data), |
108 | void *data); | 108 | void *data); |
109 | 109 | ||
110 | typedef int (*key_match_func_t)(const struct key *, const void *); | ||
111 | |||
112 | struct keyring_search_context { | 110 | struct keyring_search_context { |
113 | struct keyring_index_key index_key; | 111 | struct keyring_index_key index_key; |
114 | const struct cred *cred; | 112 | const struct cred *cred; |
115 | key_match_func_t match; | 113 | struct key_match_data match_data; |
116 | const void *match_data; | ||
117 | unsigned flags; | 114 | unsigned flags; |
118 | #define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */ | 115 | #define KEYRING_SEARCH_NO_STATE_CHECK 0x0001 /* Skip state checks */ |
119 | #define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */ | 116 | #define KEYRING_SEARCH_DO_STATE_CHECK 0x0002 /* Override NO_STATE_CHECK */ |
120 | #define KEYRING_SEARCH_DO_STATE_CHECK 0x0004 /* Override NO_STATE_CHECK */ | 117 | #define KEYRING_SEARCH_NO_UPDATE_TIME 0x0004 /* Don't update times */ |
121 | #define KEYRING_SEARCH_NO_UPDATE_TIME 0x0008 /* Don't update times */ | 118 | #define KEYRING_SEARCH_NO_CHECK_PERM 0x0008 /* Don't check permissions */ |
122 | #define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */ | 119 | #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010 /* Give an error on excessive depth */ |
123 | #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */ | ||
124 | 120 | ||
125 | int (*iterator)(const void *object, void *iterator_data); | 121 | int (*iterator)(const void *object, void *iterator_data); |
126 | 122 | ||
@@ -131,6 +127,8 @@ struct keyring_search_context { | |||
131 | struct timespec now; | 127 | struct timespec now; |
132 | }; | 128 | }; |
133 | 129 | ||
130 | extern bool key_default_cmp(const struct key *key, | ||
131 | const struct key_match_data *match_data); | ||
134 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 132 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
135 | struct keyring_search_context *ctx); | 133 | struct keyring_search_context *ctx); |
136 | 134 | ||
@@ -152,7 +150,8 @@ extern struct key *request_key_and_link(struct key_type *type, | |||
152 | struct key *dest_keyring, | 150 | struct key *dest_keyring, |
153 | unsigned long flags); | 151 | unsigned long flags); |
154 | 152 | ||
155 | extern int lookup_user_key_possessed(const struct key *key, const void *target); | 153 | extern bool lookup_user_key_possessed(const struct key *key, |
154 | const struct key_match_data *match_data); | ||
156 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, | 155 | extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, |
157 | key_perm_t perm); | 156 | key_perm_t perm); |
158 | #define KEY_LOOKUP_CREATE 0x01 | 157 | #define KEY_LOOKUP_CREATE 0x01 |
diff --git a/security/keys/key.c b/security/keys/key.c index 2048a110e7f1..8c0092ca0443 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -437,6 +437,11 @@ static int __key_instantiate_and_link(struct key *key, | |||
437 | /* disable the authorisation key */ | 437 | /* disable the authorisation key */ |
438 | if (authkey) | 438 | if (authkey) |
439 | key_revoke(authkey); | 439 | key_revoke(authkey); |
440 | |||
441 | if (prep->expiry != TIME_T_MAX) { | ||
442 | key->expiry = prep->expiry; | ||
443 | key_schedule_gc(prep->expiry + key_gc_delay); | ||
444 | } | ||
440 | } | 445 | } |
441 | } | 446 | } |
442 | 447 | ||
@@ -479,6 +484,7 @@ int key_instantiate_and_link(struct key *key, | |||
479 | prep.data = data; | 484 | prep.data = data; |
480 | prep.datalen = datalen; | 485 | prep.datalen = datalen; |
481 | prep.quotalen = key->type->def_datalen; | 486 | prep.quotalen = key->type->def_datalen; |
487 | prep.expiry = TIME_T_MAX; | ||
482 | if (key->type->preparse) { | 488 | if (key->type->preparse) { |
483 | ret = key->type->preparse(&prep); | 489 | ret = key->type->preparse(&prep); |
484 | if (ret < 0) | 490 | if (ret < 0) |
@@ -488,7 +494,7 @@ int key_instantiate_and_link(struct key *key, | |||
488 | if (keyring) { | 494 | if (keyring) { |
489 | ret = __key_link_begin(keyring, &key->index_key, &edit); | 495 | ret = __key_link_begin(keyring, &key->index_key, &edit); |
490 | if (ret < 0) | 496 | if (ret < 0) |
491 | goto error_free_preparse; | 497 | goto error; |
492 | } | 498 | } |
493 | 499 | ||
494 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit); | 500 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit); |
@@ -496,10 +502,9 @@ int key_instantiate_and_link(struct key *key, | |||
496 | if (keyring) | 502 | if (keyring) |
497 | __key_link_end(keyring, &key->index_key, edit); | 503 | __key_link_end(keyring, &key->index_key, edit); |
498 | 504 | ||
499 | error_free_preparse: | 505 | error: |
500 | if (key->type->preparse) | 506 | if (key->type->preparse) |
501 | key->type->free_preparse(&prep); | 507 | key->type->free_preparse(&prep); |
502 | error: | ||
503 | return ret; | 508 | return ret; |
504 | } | 509 | } |
505 | 510 | ||
@@ -794,7 +799,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
794 | } | 799 | } |
795 | 800 | ||
796 | key_ref = ERR_PTR(-EINVAL); | 801 | key_ref = ERR_PTR(-EINVAL); |
797 | if (!index_key.type->match || !index_key.type->instantiate || | 802 | if (!index_key.type->instantiate || |
798 | (!index_key.description && !index_key.type->preparse)) | 803 | (!index_key.description && !index_key.type->preparse)) |
799 | goto error_put_type; | 804 | goto error_put_type; |
800 | 805 | ||
@@ -811,11 +816,12 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
811 | prep.datalen = plen; | 816 | prep.datalen = plen; |
812 | prep.quotalen = index_key.type->def_datalen; | 817 | prep.quotalen = index_key.type->def_datalen; |
813 | prep.trusted = flags & KEY_ALLOC_TRUSTED; | 818 | prep.trusted = flags & KEY_ALLOC_TRUSTED; |
819 | prep.expiry = TIME_T_MAX; | ||
814 | if (index_key.type->preparse) { | 820 | if (index_key.type->preparse) { |
815 | ret = index_key.type->preparse(&prep); | 821 | ret = index_key.type->preparse(&prep); |
816 | if (ret < 0) { | 822 | if (ret < 0) { |
817 | key_ref = ERR_PTR(ret); | 823 | key_ref = ERR_PTR(ret); |
818 | goto error_put_type; | 824 | goto error_free_prep; |
819 | } | 825 | } |
820 | if (!index_key.description) | 826 | if (!index_key.description) |
821 | index_key.description = prep.description; | 827 | index_key.description = prep.description; |
@@ -941,6 +947,7 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
941 | prep.data = payload; | 947 | prep.data = payload; |
942 | prep.datalen = plen; | 948 | prep.datalen = plen; |
943 | prep.quotalen = key->type->def_datalen; | 949 | prep.quotalen = key->type->def_datalen; |
950 | prep.expiry = TIME_T_MAX; | ||
944 | if (key->type->preparse) { | 951 | if (key->type->preparse) { |
945 | ret = key->type->preparse(&prep); | 952 | ret = key->type->preparse(&prep); |
946 | if (ret < 0) | 953 | if (ret < 0) |
@@ -956,9 +963,9 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
956 | 963 | ||
957 | up_write(&key->sem); | 964 | up_write(&key->sem); |
958 | 965 | ||
966 | error: | ||
959 | if (key->type->preparse) | 967 | if (key->type->preparse) |
960 | key->type->free_preparse(&prep); | 968 | key->type->free_preparse(&prep); |
961 | error: | ||
962 | return ret; | 969 | return ret; |
963 | } | 970 | } |
964 | EXPORT_SYMBOL(key_update); | 971 | EXPORT_SYMBOL(key_update); |
@@ -1024,6 +1031,38 @@ void key_invalidate(struct key *key) | |||
1024 | EXPORT_SYMBOL(key_invalidate); | 1031 | EXPORT_SYMBOL(key_invalidate); |
1025 | 1032 | ||
1026 | /** | 1033 | /** |
1034 | * generic_key_instantiate - Simple instantiation of a key from preparsed data | ||
1035 | * @key: The key to be instantiated | ||
1036 | * @prep: The preparsed data to load. | ||
1037 | * | ||
1038 | * Instantiate a key from preparsed data. We assume we can just copy the data | ||
1039 | * in directly and clear the old pointers. | ||
1040 | * | ||
1041 | * This can be pointed to directly by the key type instantiate op pointer. | ||
1042 | */ | ||
1043 | int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | ||
1044 | { | ||
1045 | int ret; | ||
1046 | |||
1047 | pr_devel("==>%s()\n", __func__); | ||
1048 | |||
1049 | ret = key_payload_reserve(key, prep->quotalen); | ||
1050 | if (ret == 0) { | ||
1051 | key->type_data.p[0] = prep->type_data[0]; | ||
1052 | key->type_data.p[1] = prep->type_data[1]; | ||
1053 | rcu_assign_keypointer(key, prep->payload[0]); | ||
1054 | key->payload.data2[1] = prep->payload[1]; | ||
1055 | prep->type_data[0] = NULL; | ||
1056 | prep->type_data[1] = NULL; | ||
1057 | prep->payload[0] = NULL; | ||
1058 | prep->payload[1] = NULL; | ||
1059 | } | ||
1060 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
1061 | return ret; | ||
1062 | } | ||
1063 | EXPORT_SYMBOL(generic_key_instantiate); | ||
1064 | |||
1065 | /** | ||
1027 | * register_key_type - Register a type of key. | 1066 | * register_key_type - Register a type of key. |
1028 | * @ktype: The new key type. | 1067 | * @ktype: The new key type. |
1029 | * | 1068 | * |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index cd5bd0cef25d..eff88a5f5d40 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -86,6 +86,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
86 | if (!*description) { | 86 | if (!*description) { |
87 | kfree(description); | 87 | kfree(description); |
88 | description = NULL; | 88 | description = NULL; |
89 | } else if ((description[0] == '.') && | ||
90 | (strncmp(type, "keyring", 7) == 0)) { | ||
91 | ret = -EPERM; | ||
92 | goto error2; | ||
89 | } | 93 | } |
90 | } | 94 | } |
91 | 95 | ||
@@ -404,12 +408,25 @@ long keyctl_invalidate_key(key_serial_t id) | |||
404 | key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH); | 408 | key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH); |
405 | if (IS_ERR(key_ref)) { | 409 | if (IS_ERR(key_ref)) { |
406 | ret = PTR_ERR(key_ref); | 410 | ret = PTR_ERR(key_ref); |
411 | |||
412 | /* Root is permitted to invalidate certain special keys */ | ||
413 | if (capable(CAP_SYS_ADMIN)) { | ||
414 | key_ref = lookup_user_key(id, 0, 0); | ||
415 | if (IS_ERR(key_ref)) | ||
416 | goto error; | ||
417 | if (test_bit(KEY_FLAG_ROOT_CAN_INVAL, | ||
418 | &key_ref_to_ptr(key_ref)->flags)) | ||
419 | goto invalidate; | ||
420 | goto error_put; | ||
421 | } | ||
422 | |||
407 | goto error; | 423 | goto error; |
408 | } | 424 | } |
409 | 425 | ||
426 | invalidate: | ||
410 | key_invalidate(key_ref_to_ptr(key_ref)); | 427 | key_invalidate(key_ref_to_ptr(key_ref)); |
411 | ret = 0; | 428 | ret = 0; |
412 | 429 | error_put: | |
413 | key_ref_put(key_ref); | 430 | key_ref_put(key_ref); |
414 | error: | 431 | error: |
415 | kleave(" = %ld", ret); | 432 | kleave(" = %ld", ret); |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 9cf2575f0d97..8177010174f7 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -73,6 +73,8 @@ static inline unsigned keyring_hash(const char *desc) | |||
73 | * can be treated as ordinary keys in addition to having their own special | 73 | * can be treated as ordinary keys in addition to having their own special |
74 | * operations. | 74 | * operations. |
75 | */ | 75 | */ |
76 | static int keyring_preparse(struct key_preparsed_payload *prep); | ||
77 | static void keyring_free_preparse(struct key_preparsed_payload *prep); | ||
76 | static int keyring_instantiate(struct key *keyring, | 78 | static int keyring_instantiate(struct key *keyring, |
77 | struct key_preparsed_payload *prep); | 79 | struct key_preparsed_payload *prep); |
78 | static void keyring_revoke(struct key *keyring); | 80 | static void keyring_revoke(struct key *keyring); |
@@ -84,8 +86,9 @@ static long keyring_read(const struct key *keyring, | |||
84 | struct key_type key_type_keyring = { | 86 | struct key_type key_type_keyring = { |
85 | .name = "keyring", | 87 | .name = "keyring", |
86 | .def_datalen = 0, | 88 | .def_datalen = 0, |
89 | .preparse = keyring_preparse, | ||
90 | .free_preparse = keyring_free_preparse, | ||
87 | .instantiate = keyring_instantiate, | 91 | .instantiate = keyring_instantiate, |
88 | .match = user_match, | ||
89 | .revoke = keyring_revoke, | 92 | .revoke = keyring_revoke, |
90 | .destroy = keyring_destroy, | 93 | .destroy = keyring_destroy, |
91 | .describe = keyring_describe, | 94 | .describe = keyring_describe, |
@@ -123,6 +126,21 @@ static void keyring_publish_name(struct key *keyring) | |||
123 | } | 126 | } |
124 | 127 | ||
125 | /* | 128 | /* |
129 | * Preparse a keyring payload | ||
130 | */ | ||
131 | static int keyring_preparse(struct key_preparsed_payload *prep) | ||
132 | { | ||
133 | return prep->datalen != 0 ? -EINVAL : 0; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Free a preparse of a user defined key payload | ||
138 | */ | ||
139 | static void keyring_free_preparse(struct key_preparsed_payload *prep) | ||
140 | { | ||
141 | } | ||
142 | |||
143 | /* | ||
126 | * Initialise a keyring. | 144 | * Initialise a keyring. |
127 | * | 145 | * |
128 | * Returns 0 on success, -EINVAL if given any data. | 146 | * Returns 0 on success, -EINVAL if given any data. |
@@ -130,17 +148,10 @@ static void keyring_publish_name(struct key *keyring) | |||
130 | static int keyring_instantiate(struct key *keyring, | 148 | static int keyring_instantiate(struct key *keyring, |
131 | struct key_preparsed_payload *prep) | 149 | struct key_preparsed_payload *prep) |
132 | { | 150 | { |
133 | int ret; | 151 | assoc_array_init(&keyring->keys); |
134 | 152 | /* make the keyring available by name if it has one */ | |
135 | ret = -EINVAL; | 153 | keyring_publish_name(keyring); |
136 | if (prep->datalen == 0) { | 154 | return 0; |
137 | assoc_array_init(&keyring->keys); | ||
138 | /* make the keyring available by name if it has one */ | ||
139 | keyring_publish_name(keyring); | ||
140 | ret = 0; | ||
141 | } | ||
142 | |||
143 | return ret; | ||
144 | } | 155 | } |
145 | 156 | ||
146 | /* | 157 | /* |
@@ -500,6 +511,15 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, | |||
500 | EXPORT_SYMBOL(keyring_alloc); | 511 | EXPORT_SYMBOL(keyring_alloc); |
501 | 512 | ||
502 | /* | 513 | /* |
514 | * By default, we keys found by getting an exact match on their descriptions. | ||
515 | */ | ||
516 | bool key_default_cmp(const struct key *key, | ||
517 | const struct key_match_data *match_data) | ||
518 | { | ||
519 | return strcmp(key->description, match_data->raw_data) == 0; | ||
520 | } | ||
521 | |||
522 | /* | ||
503 | * Iteration function to consider each key found. | 523 | * Iteration function to consider each key found. |
504 | */ | 524 | */ |
505 | static int keyring_search_iterator(const void *object, void *iterator_data) | 525 | static int keyring_search_iterator(const void *object, void *iterator_data) |
@@ -533,7 +553,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) | |||
533 | } | 553 | } |
534 | 554 | ||
535 | /* keys that don't match */ | 555 | /* keys that don't match */ |
536 | if (!ctx->match(key, ctx->match_data)) { | 556 | if (!ctx->match_data.cmp(key, &ctx->match_data)) { |
537 | kleave(" = 0 [!match]"); | 557 | kleave(" = 0 [!match]"); |
538 | return 0; | 558 | return 0; |
539 | } | 559 | } |
@@ -573,8 +593,7 @@ skipped: | |||
573 | */ | 593 | */ |
574 | static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) | 594 | static int search_keyring(struct key *keyring, struct keyring_search_context *ctx) |
575 | { | 595 | { |
576 | if ((ctx->flags & KEYRING_SEARCH_LOOKUP_TYPE) == | 596 | if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_DIRECT) { |
577 | KEYRING_SEARCH_LOOKUP_DIRECT) { | ||
578 | const void *object; | 597 | const void *object; |
579 | 598 | ||
580 | object = assoc_array_find(&keyring->keys, | 599 | object = assoc_array_find(&keyring->keys, |
@@ -615,7 +634,7 @@ static bool search_nested_keyrings(struct key *keyring, | |||
615 | /* Check to see if this top-level keyring is what we are looking for | 634 | /* Check to see if this top-level keyring is what we are looking for |
616 | * and whether it is valid or not. | 635 | * and whether it is valid or not. |
617 | */ | 636 | */ |
618 | if (ctx->flags & KEYRING_SEARCH_LOOKUP_ITERATE || | 637 | if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_ITERATE || |
619 | keyring_compare_object(keyring, &ctx->index_key)) { | 638 | keyring_compare_object(keyring, &ctx->index_key)) { |
620 | ctx->skipped_ret = 2; | 639 | ctx->skipped_ret = 2; |
621 | ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; | 640 | ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK; |
@@ -873,16 +892,25 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
873 | .index_key.type = type, | 892 | .index_key.type = type, |
874 | .index_key.description = description, | 893 | .index_key.description = description, |
875 | .cred = current_cred(), | 894 | .cred = current_cred(), |
876 | .match = type->match, | 895 | .match_data.cmp = key_default_cmp, |
877 | .match_data = description, | 896 | .match_data.raw_data = description, |
878 | .flags = (type->def_lookup_type | | 897 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
879 | KEYRING_SEARCH_DO_STATE_CHECK), | 898 | .flags = KEYRING_SEARCH_DO_STATE_CHECK, |
880 | }; | 899 | }; |
900 | key_ref_t key; | ||
901 | int ret; | ||
902 | |||
903 | if (type->match_preparse) { | ||
904 | ret = type->match_preparse(&ctx.match_data); | ||
905 | if (ret < 0) | ||
906 | return ERR_PTR(ret); | ||
907 | } | ||
881 | 908 | ||
882 | if (!ctx.match) | 909 | key = keyring_search_aux(keyring, &ctx); |
883 | return ERR_PTR(-ENOKEY); | ||
884 | 910 | ||
885 | return keyring_search_aux(keyring, &ctx); | 911 | if (type->match_free) |
912 | type->match_free(&ctx.match_data); | ||
913 | return key; | ||
886 | } | 914 | } |
887 | EXPORT_SYMBOL(keyring_search); | 915 | EXPORT_SYMBOL(keyring_search); |
888 | 916 | ||
@@ -1002,7 +1030,7 @@ static int keyring_detect_cycle_iterator(const void *object, | |||
1002 | 1030 | ||
1003 | /* We might get a keyring with matching index-key that is nonetheless a | 1031 | /* We might get a keyring with matching index-key that is nonetheless a |
1004 | * different keyring. */ | 1032 | * different keyring. */ |
1005 | if (key != ctx->match_data) | 1033 | if (key != ctx->match_data.raw_data) |
1006 | return 0; | 1034 | return 0; |
1007 | 1035 | ||
1008 | ctx->result = ERR_PTR(-EDEADLK); | 1036 | ctx->result = ERR_PTR(-EDEADLK); |
@@ -1019,14 +1047,14 @@ static int keyring_detect_cycle_iterator(const void *object, | |||
1019 | static int keyring_detect_cycle(struct key *A, struct key *B) | 1047 | static int keyring_detect_cycle(struct key *A, struct key *B) |
1020 | { | 1048 | { |
1021 | struct keyring_search_context ctx = { | 1049 | struct keyring_search_context ctx = { |
1022 | .index_key = A->index_key, | 1050 | .index_key = A->index_key, |
1023 | .match_data = A, | 1051 | .match_data.raw_data = A, |
1024 | .iterator = keyring_detect_cycle_iterator, | 1052 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
1025 | .flags = (KEYRING_SEARCH_LOOKUP_DIRECT | | 1053 | .iterator = keyring_detect_cycle_iterator, |
1026 | KEYRING_SEARCH_NO_STATE_CHECK | | 1054 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | |
1027 | KEYRING_SEARCH_NO_UPDATE_TIME | | 1055 | KEYRING_SEARCH_NO_UPDATE_TIME | |
1028 | KEYRING_SEARCH_NO_CHECK_PERM | | 1056 | KEYRING_SEARCH_NO_CHECK_PERM | |
1029 | KEYRING_SEARCH_DETECT_TOO_DEEP), | 1057 | KEYRING_SEARCH_DETECT_TOO_DEEP), |
1030 | }; | 1058 | }; |
1031 | 1059 | ||
1032 | rcu_read_lock(); | 1060 | rcu_read_lock(); |
diff --git a/security/keys/proc.c b/security/keys/proc.c index d3f6f2fd21db..972eeb336b81 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -194,10 +194,10 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
194 | .index_key.type = key->type, | 194 | .index_key.type = key->type, |
195 | .index_key.description = key->description, | 195 | .index_key.description = key->description, |
196 | .cred = current_cred(), | 196 | .cred = current_cred(), |
197 | .match = lookup_user_key_possessed, | 197 | .match_data.cmp = lookup_user_key_possessed, |
198 | .match_data = key, | 198 | .match_data.raw_data = key, |
199 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | 199 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
200 | KEYRING_SEARCH_LOOKUP_DIRECT), | 200 | .flags = KEYRING_SEARCH_NO_STATE_CHECK, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | key_ref = make_key_ref(key, 0); | 203 | key_ref = make_key_ref(key, 0); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 0cf8a130a267..bd536cb221e2 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -489,9 +489,10 @@ found: | |||
489 | /* | 489 | /* |
490 | * See if the key we're looking at is the target key. | 490 | * See if the key we're looking at is the target key. |
491 | */ | 491 | */ |
492 | int lookup_user_key_possessed(const struct key *key, const void *target) | 492 | bool lookup_user_key_possessed(const struct key *key, |
493 | const struct key_match_data *match_data) | ||
493 | { | 494 | { |
494 | return key == target; | 495 | return key == match_data->raw_data; |
495 | } | 496 | } |
496 | 497 | ||
497 | /* | 498 | /* |
@@ -516,9 +517,9 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, | |||
516 | key_perm_t perm) | 517 | key_perm_t perm) |
517 | { | 518 | { |
518 | struct keyring_search_context ctx = { | 519 | struct keyring_search_context ctx = { |
519 | .match = lookup_user_key_possessed, | 520 | .match_data.cmp = lookup_user_key_possessed, |
520 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | | 521 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
521 | KEYRING_SEARCH_LOOKUP_DIRECT), | 522 | .flags = KEYRING_SEARCH_NO_STATE_CHECK, |
522 | }; | 523 | }; |
523 | struct request_key_auth *rka; | 524 | struct request_key_auth *rka; |
524 | struct key *key; | 525 | struct key *key; |
@@ -673,7 +674,7 @@ try_again: | |||
673 | ctx.index_key.type = key->type; | 674 | ctx.index_key.type = key->type; |
674 | ctx.index_key.description = key->description; | 675 | ctx.index_key.description = key->description; |
675 | ctx.index_key.desc_len = strlen(key->description); | 676 | ctx.index_key.desc_len = strlen(key->description); |
676 | ctx.match_data = key; | 677 | ctx.match_data.raw_data = key; |
677 | kdebug("check possessed"); | 678 | kdebug("check possessed"); |
678 | skey_ref = search_process_keyrings(&ctx); | 679 | skey_ref = search_process_keyrings(&ctx); |
679 | kdebug("possessed=%p", skey_ref); | 680 | kdebug("possessed=%p", skey_ref); |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 381411941cc1..dc6ed32b7844 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -531,9 +531,9 @@ struct key *request_key_and_link(struct key_type *type, | |||
531 | .index_key.type = type, | 531 | .index_key.type = type, |
532 | .index_key.description = description, | 532 | .index_key.description = description, |
533 | .cred = current_cred(), | 533 | .cred = current_cred(), |
534 | .match = type->match, | 534 | .match_data.cmp = key_default_cmp, |
535 | .match_data = description, | 535 | .match_data.raw_data = description, |
536 | .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | 536 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
537 | }; | 537 | }; |
538 | struct key *key; | 538 | struct key *key; |
539 | key_ref_t key_ref; | 539 | key_ref_t key_ref; |
@@ -543,6 +543,14 @@ struct key *request_key_and_link(struct key_type *type, | |||
543 | ctx.index_key.type->name, ctx.index_key.description, | 543 | ctx.index_key.type->name, ctx.index_key.description, |
544 | callout_info, callout_len, aux, dest_keyring, flags); | 544 | callout_info, callout_len, aux, dest_keyring, flags); |
545 | 545 | ||
546 | if (type->match_preparse) { | ||
547 | ret = type->match_preparse(&ctx.match_data); | ||
548 | if (ret < 0) { | ||
549 | key = ERR_PTR(ret); | ||
550 | goto error; | ||
551 | } | ||
552 | } | ||
553 | |||
546 | /* search all the process keyrings for a key */ | 554 | /* search all the process keyrings for a key */ |
547 | key_ref = search_process_keyrings(&ctx); | 555 | key_ref = search_process_keyrings(&ctx); |
548 | 556 | ||
@@ -555,7 +563,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
555 | if (ret < 0) { | 563 | if (ret < 0) { |
556 | key_put(key); | 564 | key_put(key); |
557 | key = ERR_PTR(ret); | 565 | key = ERR_PTR(ret); |
558 | goto error; | 566 | goto error_free; |
559 | } | 567 | } |
560 | } | 568 | } |
561 | } else if (PTR_ERR(key_ref) != -EAGAIN) { | 569 | } else if (PTR_ERR(key_ref) != -EAGAIN) { |
@@ -565,12 +573,15 @@ struct key *request_key_and_link(struct key_type *type, | |||
565 | * should consult userspace if we can */ | 573 | * should consult userspace if we can */ |
566 | key = ERR_PTR(-ENOKEY); | 574 | key = ERR_PTR(-ENOKEY); |
567 | if (!callout_info) | 575 | if (!callout_info) |
568 | goto error; | 576 | goto error_free; |
569 | 577 | ||
570 | key = construct_key_and_link(&ctx, callout_info, callout_len, | 578 | key = construct_key_and_link(&ctx, callout_info, callout_len, |
571 | aux, dest_keyring, flags); | 579 | aux, dest_keyring, flags); |
572 | } | 580 | } |
573 | 581 | ||
582 | error_free: | ||
583 | if (type->match_free) | ||
584 | type->match_free(&ctx.match_data); | ||
574 | error: | 585 | error: |
575 | kleave(" = %p", key); | 586 | kleave(" = %p", key); |
576 | return key; | 587 | return key; |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 7495a93b4b90..6639e2cb8853 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | #include <keys/user-type.h> | 21 | #include <keys/user-type.h> |
22 | 22 | ||
23 | static int request_key_auth_preparse(struct key_preparsed_payload *); | ||
24 | static void request_key_auth_free_preparse(struct key_preparsed_payload *); | ||
23 | static int request_key_auth_instantiate(struct key *, | 25 | static int request_key_auth_instantiate(struct key *, |
24 | struct key_preparsed_payload *); | 26 | struct key_preparsed_payload *); |
25 | static void request_key_auth_describe(const struct key *, struct seq_file *); | 27 | static void request_key_auth_describe(const struct key *, struct seq_file *); |
@@ -33,6 +35,8 @@ static long request_key_auth_read(const struct key *, char __user *, size_t); | |||
33 | struct key_type key_type_request_key_auth = { | 35 | struct key_type key_type_request_key_auth = { |
34 | .name = ".request_key_auth", | 36 | .name = ".request_key_auth", |
35 | .def_datalen = sizeof(struct request_key_auth), | 37 | .def_datalen = sizeof(struct request_key_auth), |
38 | .preparse = request_key_auth_preparse, | ||
39 | .free_preparse = request_key_auth_free_preparse, | ||
36 | .instantiate = request_key_auth_instantiate, | 40 | .instantiate = request_key_auth_instantiate, |
37 | .describe = request_key_auth_describe, | 41 | .describe = request_key_auth_describe, |
38 | .revoke = request_key_auth_revoke, | 42 | .revoke = request_key_auth_revoke, |
@@ -40,6 +44,15 @@ struct key_type key_type_request_key_auth = { | |||
40 | .read = request_key_auth_read, | 44 | .read = request_key_auth_read, |
41 | }; | 45 | }; |
42 | 46 | ||
47 | static int request_key_auth_preparse(struct key_preparsed_payload *prep) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static void request_key_auth_free_preparse(struct key_preparsed_payload *prep) | ||
53 | { | ||
54 | } | ||
55 | |||
43 | /* | 56 | /* |
44 | * Instantiate a request-key authorisation key. | 57 | * Instantiate a request-key authorisation key. |
45 | */ | 58 | */ |
@@ -233,9 +246,9 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) | |||
233 | .index_key.type = &key_type_request_key_auth, | 246 | .index_key.type = &key_type_request_key_auth, |
234 | .index_key.description = description, | 247 | .index_key.description = description, |
235 | .cred = current_cred(), | 248 | .cred = current_cred(), |
236 | .match = user_match, | 249 | .match_data.cmp = key_default_cmp, |
237 | .match_data = description, | 250 | .match_data.raw_data = description, |
238 | .flags = KEYRING_SEARCH_LOOKUP_DIRECT, | 251 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, |
239 | }; | 252 | }; |
240 | struct key *authkey; | 253 | struct key *authkey; |
241 | key_ref_t authkey_ref; | 254 | key_ref_t authkey_ref; |
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 6b804aa4529a..c0594cb07ada 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -1096,7 +1096,6 @@ struct key_type key_type_trusted = { | |||
1096 | .name = "trusted", | 1096 | .name = "trusted", |
1097 | .instantiate = trusted_instantiate, | 1097 | .instantiate = trusted_instantiate, |
1098 | .update = trusted_update, | 1098 | .update = trusted_update, |
1099 | .match = user_match, | ||
1100 | .destroy = trusted_destroy, | 1099 | .destroy = trusted_destroy, |
1101 | .describe = user_describe, | 1100 | .describe = user_describe, |
1102 | .read = trusted_read, | 1101 | .read = trusted_read, |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index faa2caeb593f..36b47bbd3d8c 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -26,10 +26,10 @@ static int logon_vet_description(const char *desc); | |||
26 | */ | 26 | */ |
27 | struct key_type key_type_user = { | 27 | struct key_type key_type_user = { |
28 | .name = "user", | 28 | .name = "user", |
29 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 29 | .preparse = user_preparse, |
30 | .instantiate = user_instantiate, | 30 | .free_preparse = user_free_preparse, |
31 | .instantiate = generic_key_instantiate, | ||
31 | .update = user_update, | 32 | .update = user_update, |
32 | .match = user_match, | ||
33 | .revoke = user_revoke, | 33 | .revoke = user_revoke, |
34 | .destroy = user_destroy, | 34 | .destroy = user_destroy, |
35 | .describe = user_describe, | 35 | .describe = user_describe, |
@@ -46,10 +46,10 @@ EXPORT_SYMBOL_GPL(key_type_user); | |||
46 | */ | 46 | */ |
47 | struct key_type key_type_logon = { | 47 | struct key_type key_type_logon = { |
48 | .name = "logon", | 48 | .name = "logon", |
49 | .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | 49 | .preparse = user_preparse, |
50 | .instantiate = user_instantiate, | 50 | .free_preparse = user_free_preparse, |
51 | .instantiate = generic_key_instantiate, | ||
51 | .update = user_update, | 52 | .update = user_update, |
52 | .match = user_match, | ||
53 | .revoke = user_revoke, | 53 | .revoke = user_revoke, |
54 | .destroy = user_destroy, | 54 | .destroy = user_destroy, |
55 | .describe = user_describe, | 55 | .describe = user_describe, |
@@ -58,38 +58,37 @@ struct key_type key_type_logon = { | |||
58 | EXPORT_SYMBOL_GPL(key_type_logon); | 58 | EXPORT_SYMBOL_GPL(key_type_logon); |
59 | 59 | ||
60 | /* | 60 | /* |
61 | * instantiate a user defined key | 61 | * Preparse a user defined key payload |
62 | */ | 62 | */ |
63 | int user_instantiate(struct key *key, struct key_preparsed_payload *prep) | 63 | int user_preparse(struct key_preparsed_payload *prep) |
64 | { | 64 | { |
65 | struct user_key_payload *upayload; | 65 | struct user_key_payload *upayload; |
66 | size_t datalen = prep->datalen; | 66 | size_t datalen = prep->datalen; |
67 | int ret; | ||
68 | 67 | ||
69 | ret = -EINVAL; | ||
70 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 68 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
71 | goto error; | 69 | return -EINVAL; |
72 | |||
73 | ret = key_payload_reserve(key, datalen); | ||
74 | if (ret < 0) | ||
75 | goto error; | ||
76 | 70 | ||
77 | ret = -ENOMEM; | ||
78 | upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); | 71 | upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); |
79 | if (!upayload) | 72 | if (!upayload) |
80 | goto error; | 73 | return -ENOMEM; |
81 | 74 | ||
82 | /* attach the data */ | 75 | /* attach the data */ |
76 | prep->quotalen = datalen; | ||
77 | prep->payload[0] = upayload; | ||
83 | upayload->datalen = datalen; | 78 | upayload->datalen = datalen; |
84 | memcpy(upayload->data, prep->data, datalen); | 79 | memcpy(upayload->data, prep->data, datalen); |
85 | rcu_assign_keypointer(key, upayload); | 80 | return 0; |
86 | ret = 0; | ||
87 | |||
88 | error: | ||
89 | return ret; | ||
90 | } | 81 | } |
82 | EXPORT_SYMBOL_GPL(user_preparse); | ||
91 | 83 | ||
92 | EXPORT_SYMBOL_GPL(user_instantiate); | 84 | /* |
85 | * Free a preparse of a user defined key payload | ||
86 | */ | ||
87 | void user_free_preparse(struct key_preparsed_payload *prep) | ||
88 | { | ||
89 | kfree(prep->payload[0]); | ||
90 | } | ||
91 | EXPORT_SYMBOL_GPL(user_free_preparse); | ||
93 | 92 | ||
94 | /* | 93 | /* |
95 | * update a user defined key | 94 | * update a user defined key |
@@ -136,16 +135,6 @@ error: | |||
136 | EXPORT_SYMBOL_GPL(user_update); | 135 | EXPORT_SYMBOL_GPL(user_update); |
137 | 136 | ||
138 | /* | 137 | /* |
139 | * match users on their name | ||
140 | */ | ||
141 | int user_match(const struct key *key, const void *description) | ||
142 | { | ||
143 | return strcmp(key->description, description) == 0; | ||
144 | } | ||
145 | |||
146 | EXPORT_SYMBOL_GPL(user_match); | ||
147 | |||
148 | /* | ||
149 | * dispose of the links from a revoked keyring | 138 | * dispose of the links from a revoked keyring |
150 | * - called with the key sem write-locked | 139 | * - called with the key sem write-locked |
151 | */ | 140 | */ |
diff --git a/security/security.c b/security/security.c index 31614e9e96e5..e41b1a8d7644 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -845,6 +845,17 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
845 | return security_ops->kernel_create_files_as(new, inode); | 845 | return security_ops->kernel_create_files_as(new, inode); |
846 | } | 846 | } |
847 | 847 | ||
848 | int security_kernel_fw_from_file(struct file *file, char *buf, size_t size) | ||
849 | { | ||
850 | int ret; | ||
851 | |||
852 | ret = security_ops->kernel_fw_from_file(file, buf, size); | ||
853 | if (ret) | ||
854 | return ret; | ||
855 | return ima_fw_from_file(file, buf, size); | ||
856 | } | ||
857 | EXPORT_SYMBOL_GPL(security_kernel_fw_from_file); | ||
858 | |||
848 | int security_kernel_module_request(char *kmod_name) | 859 | int security_kernel_module_request(char *kmod_name) |
849 | { | 860 | { |
850 | return security_ops->kernel_module_request(kmod_name); | 861 | return security_ops->kernel_module_request(kmod_name); |
diff --git a/security/smack/Kconfig b/security/smack/Kconfig index e69de9c642b7..b065f9789418 100644 --- a/security/smack/Kconfig +++ b/security/smack/Kconfig | |||
@@ -12,3 +12,19 @@ config SECURITY_SMACK | |||
12 | of other mandatory security schemes. | 12 | of other mandatory security schemes. |
13 | If you are unsure how to answer this question, answer N. | 13 | If you are unsure how to answer this question, answer N. |
14 | 14 | ||
15 | config SECURITY_SMACK_BRINGUP | ||
16 | bool "Reporting on access granted by Smack rules" | ||
17 | depends on SECURITY_SMACK | ||
18 | default n | ||
19 | help | ||
20 | Enable the bring-up ("b") access mode in Smack rules. | ||
21 | When access is granted by a rule with the "b" mode a | ||
22 | message about the access requested is generated. The | ||
23 | intention is that a process can be granted a wide set | ||
24 | of access initially with the bringup mode set on the | ||
25 | rules. The developer can use the information to | ||
26 | identify which rules are necessary and what accesses | ||
27 | may be inappropriate. The developer can reduce the | ||
28 | access rule set once the behavior is well understood. | ||
29 | This is a superior mechanism to the oft abused | ||
30 | "permissive" mode of other systems. | ||
diff --git a/security/smack/smack.h b/security/smack/smack.h index 020307ef0972..b828a379377c 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -71,11 +71,11 @@ struct smack_known { | |||
71 | #define SMK_CIPSOLEN 24 | 71 | #define SMK_CIPSOLEN 24 |
72 | 72 | ||
73 | struct superblock_smack { | 73 | struct superblock_smack { |
74 | char *smk_root; | 74 | struct smack_known *smk_root; |
75 | char *smk_floor; | 75 | struct smack_known *smk_floor; |
76 | char *smk_hat; | 76 | struct smack_known *smk_hat; |
77 | char *smk_default; | 77 | struct smack_known *smk_default; |
78 | int smk_initialized; | 78 | int smk_initialized; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | struct socket_smack { | 81 | struct socket_smack { |
@@ -88,7 +88,7 @@ struct socket_smack { | |||
88 | * Inode smack data | 88 | * Inode smack data |
89 | */ | 89 | */ |
90 | struct inode_smack { | 90 | struct inode_smack { |
91 | char *smk_inode; /* label of the fso */ | 91 | struct smack_known *smk_inode; /* label of the fso */ |
92 | struct smack_known *smk_task; /* label of the task */ | 92 | struct smack_known *smk_task; /* label of the task */ |
93 | struct smack_known *smk_mmap; /* label of the mmap domain */ | 93 | struct smack_known *smk_mmap; /* label of the mmap domain */ |
94 | struct mutex smk_lock; /* initialization lock */ | 94 | struct mutex smk_lock; /* initialization lock */ |
@@ -112,7 +112,7 @@ struct task_smack { | |||
112 | struct smack_rule { | 112 | struct smack_rule { |
113 | struct list_head list; | 113 | struct list_head list; |
114 | struct smack_known *smk_subject; | 114 | struct smack_known *smk_subject; |
115 | char *smk_object; | 115 | struct smack_known *smk_object; |
116 | int smk_access; | 116 | int smk_access; |
117 | }; | 117 | }; |
118 | 118 | ||
@@ -123,7 +123,7 @@ struct smk_netlbladdr { | |||
123 | struct list_head list; | 123 | struct list_head list; |
124 | struct sockaddr_in smk_host; /* network address */ | 124 | struct sockaddr_in smk_host; /* network address */ |
125 | struct in_addr smk_mask; /* network mask */ | 125 | struct in_addr smk_mask; /* network mask */ |
126 | char *smk_label; /* label */ | 126 | struct smack_known *smk_label; /* label */ |
127 | }; | 127 | }; |
128 | 128 | ||
129 | /* | 129 | /* |
@@ -191,6 +191,7 @@ struct smk_port_label { | |||
191 | */ | 191 | */ |
192 | #define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */ | 192 | #define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */ |
193 | #define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ | 193 | #define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ |
194 | #define MAY_BRINGUP 0x00004000 /* Report use of this rule */ | ||
194 | 195 | ||
195 | /* | 196 | /* |
196 | * Just to make the common cases easier to deal with | 197 | * Just to make the common cases easier to deal with |
@@ -200,9 +201,9 @@ struct smk_port_label { | |||
200 | #define MAY_NOT 0 | 201 | #define MAY_NOT 0 |
201 | 202 | ||
202 | /* | 203 | /* |
203 | * Number of access types used by Smack (rwxatl) | 204 | * Number of access types used by Smack (rwxatlb) |
204 | */ | 205 | */ |
205 | #define SMK_NUM_ACCESS_TYPE 6 | 206 | #define SMK_NUM_ACCESS_TYPE 7 |
206 | 207 | ||
207 | /* SMACK data */ | 208 | /* SMACK data */ |
208 | struct smack_audit_data { | 209 | struct smack_audit_data { |
@@ -226,23 +227,23 @@ struct smk_audit_info { | |||
226 | /* | 227 | /* |
227 | * These functions are in smack_lsm.c | 228 | * These functions are in smack_lsm.c |
228 | */ | 229 | */ |
229 | struct inode_smack *new_inode_smack(char *); | 230 | struct inode_smack *new_inode_smack(struct smack_known *); |
230 | 231 | ||
231 | /* | 232 | /* |
232 | * These functions are in smack_access.c | 233 | * These functions are in smack_access.c |
233 | */ | 234 | */ |
234 | int smk_access_entry(char *, char *, struct list_head *); | 235 | int smk_access_entry(char *, char *, struct list_head *); |
235 | int smk_access(struct smack_known *, char *, int, struct smk_audit_info *); | 236 | int smk_access(struct smack_known *, struct smack_known *, |
236 | int smk_tskacc(struct task_smack *, char *, u32, struct smk_audit_info *); | 237 | int, struct smk_audit_info *); |
237 | int smk_curacc(char *, u32, struct smk_audit_info *); | 238 | int smk_tskacc(struct task_smack *, struct smack_known *, |
239 | u32, struct smk_audit_info *); | ||
240 | int smk_curacc(struct smack_known *, u32, struct smk_audit_info *); | ||
238 | struct smack_known *smack_from_secid(const u32); | 241 | struct smack_known *smack_from_secid(const u32); |
239 | char *smk_parse_smack(const char *string, int len); | 242 | char *smk_parse_smack(const char *string, int len); |
240 | int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); | 243 | int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); |
241 | char *smk_import(const char *, int); | ||
242 | struct smack_known *smk_import_entry(const char *, int); | 244 | struct smack_known *smk_import_entry(const char *, int); |
243 | void smk_insert_entry(struct smack_known *skp); | 245 | void smk_insert_entry(struct smack_known *skp); |
244 | struct smack_known *smk_find_entry(const char *); | 246 | struct smack_known *smk_find_entry(const char *); |
245 | u32 smack_to_secid(const char *); | ||
246 | 247 | ||
247 | /* | 248 | /* |
248 | * Shared data. | 249 | * Shared data. |
@@ -252,7 +253,7 @@ extern int smack_cipso_mapped; | |||
252 | extern struct smack_known *smack_net_ambient; | 253 | extern struct smack_known *smack_net_ambient; |
253 | extern struct smack_known *smack_onlycap; | 254 | extern struct smack_known *smack_onlycap; |
254 | extern struct smack_known *smack_syslog_label; | 255 | extern struct smack_known *smack_syslog_label; |
255 | extern const char *smack_cipso_option; | 256 | extern struct smack_known smack_cipso_option; |
256 | extern int smack_ptrace_rule; | 257 | extern int smack_ptrace_rule; |
257 | 258 | ||
258 | extern struct smack_known smack_known_floor; | 259 | extern struct smack_known smack_known_floor; |
@@ -281,9 +282,9 @@ static inline int smk_inode_transmutable(const struct inode *isp) | |||
281 | } | 282 | } |
282 | 283 | ||
283 | /* | 284 | /* |
284 | * Present a pointer to the smack label in an inode blob. | 285 | * Present a pointer to the smack label entry in an inode blob. |
285 | */ | 286 | */ |
286 | static inline char *smk_of_inode(const struct inode *isp) | 287 | static inline struct smack_known *smk_of_inode(const struct inode *isp) |
287 | { | 288 | { |
288 | struct inode_smack *sip = isp->i_security; | 289 | struct inode_smack *sip = isp->i_security; |
289 | return sip->smk_inode; | 290 | return sip->smk_inode; |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index f97d0842e621..5b970ffde024 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -94,7 +94,7 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
94 | struct smack_rule *srp; | 94 | struct smack_rule *srp; |
95 | 95 | ||
96 | list_for_each_entry_rcu(srp, rule_list, list) { | 96 | list_for_each_entry_rcu(srp, rule_list, list) { |
97 | if (srp->smk_object == object_label && | 97 | if (srp->smk_object->smk_known == object_label && |
98 | srp->smk_subject->smk_known == subject_label) { | 98 | srp->smk_subject->smk_known == subject_label) { |
99 | may = srp->smk_access; | 99 | may = srp->smk_access; |
100 | break; | 100 | break; |
@@ -111,8 +111,8 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
111 | 111 | ||
112 | /** | 112 | /** |
113 | * smk_access - determine if a subject has a specific access to an object | 113 | * smk_access - determine if a subject has a specific access to an object |
114 | * @subject_known: a pointer to the subject's Smack label entry | 114 | * @subject: a pointer to the subject's Smack label entry |
115 | * @object_label: a pointer to the object's Smack label | 115 | * @object: a pointer to the object's Smack label entry |
116 | * @request: the access requested, in "MAY" format | 116 | * @request: the access requested, in "MAY" format |
117 | * @a : a pointer to the audit data | 117 | * @a : a pointer to the audit data |
118 | * | 118 | * |
@@ -122,8 +122,8 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
122 | * | 122 | * |
123 | * Smack labels are shared on smack_list | 123 | * Smack labels are shared on smack_list |
124 | */ | 124 | */ |
125 | int smk_access(struct smack_known *subject_known, char *object_label, | 125 | int smk_access(struct smack_known *subject, struct smack_known *object, |
126 | int request, struct smk_audit_info *a) | 126 | int request, struct smk_audit_info *a) |
127 | { | 127 | { |
128 | int may = MAY_NOT; | 128 | int may = MAY_NOT; |
129 | int rc = 0; | 129 | int rc = 0; |
@@ -133,7 +133,7 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
133 | * | 133 | * |
134 | * A star subject can't access any object. | 134 | * A star subject can't access any object. |
135 | */ | 135 | */ |
136 | if (subject_known == &smack_known_star) { | 136 | if (subject == &smack_known_star) { |
137 | rc = -EACCES; | 137 | rc = -EACCES; |
138 | goto out_audit; | 138 | goto out_audit; |
139 | } | 139 | } |
@@ -142,28 +142,28 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
142 | * Tasks cannot be assigned the internet label. | 142 | * Tasks cannot be assigned the internet label. |
143 | * An internet subject can access any object. | 143 | * An internet subject can access any object. |
144 | */ | 144 | */ |
145 | if (object_label == smack_known_web.smk_known || | 145 | if (object == &smack_known_web || |
146 | subject_known == &smack_known_web) | 146 | subject == &smack_known_web) |
147 | goto out_audit; | 147 | goto out_audit; |
148 | /* | 148 | /* |
149 | * A star object can be accessed by any subject. | 149 | * A star object can be accessed by any subject. |
150 | */ | 150 | */ |
151 | if (object_label == smack_known_star.smk_known) | 151 | if (object == &smack_known_star) |
152 | goto out_audit; | 152 | goto out_audit; |
153 | /* | 153 | /* |
154 | * An object can be accessed in any way by a subject | 154 | * An object can be accessed in any way by a subject |
155 | * with the same label. | 155 | * with the same label. |
156 | */ | 156 | */ |
157 | if (subject_known->smk_known == object_label) | 157 | if (subject->smk_known == object->smk_known) |
158 | goto out_audit; | 158 | goto out_audit; |
159 | /* | 159 | /* |
160 | * A hat subject can read any object. | 160 | * A hat subject can read any object. |
161 | * A floor object can be read by any subject. | 161 | * A floor object can be read by any subject. |
162 | */ | 162 | */ |
163 | if ((request & MAY_ANYREAD) == request) { | 163 | if ((request & MAY_ANYREAD) == request) { |
164 | if (object_label == smack_known_floor.smk_known) | 164 | if (object == &smack_known_floor) |
165 | goto out_audit; | 165 | goto out_audit; |
166 | if (subject_known == &smack_known_hat) | 166 | if (subject == &smack_known_hat) |
167 | goto out_audit; | 167 | goto out_audit; |
168 | } | 168 | } |
169 | /* | 169 | /* |
@@ -174,27 +174,38 @@ int smk_access(struct smack_known *subject_known, char *object_label, | |||
174 | * indicates there is no entry for this pair. | 174 | * indicates there is no entry for this pair. |
175 | */ | 175 | */ |
176 | rcu_read_lock(); | 176 | rcu_read_lock(); |
177 | may = smk_access_entry(subject_known->smk_known, object_label, | 177 | may = smk_access_entry(subject->smk_known, object->smk_known, |
178 | &subject_known->smk_rules); | 178 | &subject->smk_rules); |
179 | rcu_read_unlock(); | 179 | rcu_read_unlock(); |
180 | 180 | ||
181 | if (may > 0 && (request & may) == request) | 181 | if (may <= 0 || (request & may) != request) { |
182 | rc = -EACCES; | ||
182 | goto out_audit; | 183 | goto out_audit; |
184 | } | ||
185 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
186 | /* | ||
187 | * Return a positive value if using bringup mode. | ||
188 | * This allows the hooks to identify checks that | ||
189 | * succeed because of "b" rules. | ||
190 | */ | ||
191 | if (may & MAY_BRINGUP) | ||
192 | rc = MAY_BRINGUP; | ||
193 | #endif | ||
183 | 194 | ||
184 | rc = -EACCES; | ||
185 | out_audit: | 195 | out_audit: |
186 | #ifdef CONFIG_AUDIT | 196 | #ifdef CONFIG_AUDIT |
187 | if (a) | 197 | if (a) |
188 | smack_log(subject_known->smk_known, object_label, request, | 198 | smack_log(subject->smk_known, object->smk_known, |
189 | rc, a); | 199 | request, rc, a); |
190 | #endif | 200 | #endif |
201 | |||
191 | return rc; | 202 | return rc; |
192 | } | 203 | } |
193 | 204 | ||
194 | /** | 205 | /** |
195 | * smk_tskacc - determine if a task has a specific access to an object | 206 | * smk_tskacc - determine if a task has a specific access to an object |
196 | * @tsp: a pointer to the subject task | 207 | * @tsp: a pointer to the subject's task |
197 | * @obj_label: a pointer to the object's Smack label | 208 | * @obj_known: a pointer to the object's label entry |
198 | * @mode: the access requested, in "MAY" format | 209 | * @mode: the access requested, in "MAY" format |
199 | * @a : common audit data | 210 | * @a : common audit data |
200 | * | 211 | * |
@@ -203,24 +214,25 @@ out_audit: | |||
203 | * non zero otherwise. It allows that the task may have the capability | 214 | * non zero otherwise. It allows that the task may have the capability |
204 | * to override the rules. | 215 | * to override the rules. |
205 | */ | 216 | */ |
206 | int smk_tskacc(struct task_smack *subject, char *obj_label, | 217 | int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known, |
207 | u32 mode, struct smk_audit_info *a) | 218 | u32 mode, struct smk_audit_info *a) |
208 | { | 219 | { |
209 | struct smack_known *skp = smk_of_task(subject); | 220 | struct smack_known *sbj_known = smk_of_task(tsp); |
210 | int may; | 221 | int may; |
211 | int rc; | 222 | int rc; |
212 | 223 | ||
213 | /* | 224 | /* |
214 | * Check the global rule list | 225 | * Check the global rule list |
215 | */ | 226 | */ |
216 | rc = smk_access(skp, obj_label, mode, NULL); | 227 | rc = smk_access(sbj_known, obj_known, mode, NULL); |
217 | if (rc == 0) { | 228 | if (rc >= 0) { |
218 | /* | 229 | /* |
219 | * If there is an entry in the task's rule list | 230 | * If there is an entry in the task's rule list |
220 | * it can further restrict access. | 231 | * it can further restrict access. |
221 | */ | 232 | */ |
222 | may = smk_access_entry(skp->smk_known, obj_label, | 233 | may = smk_access_entry(sbj_known->smk_known, |
223 | &subject->smk_rules); | 234 | obj_known->smk_known, |
235 | &tsp->smk_rules); | ||
224 | if (may < 0) | 236 | if (may < 0) |
225 | goto out_audit; | 237 | goto out_audit; |
226 | if ((mode & may) == mode) | 238 | if ((mode & may) == mode) |
@@ -237,14 +249,15 @@ int smk_tskacc(struct task_smack *subject, char *obj_label, | |||
237 | out_audit: | 249 | out_audit: |
238 | #ifdef CONFIG_AUDIT | 250 | #ifdef CONFIG_AUDIT |
239 | if (a) | 251 | if (a) |
240 | smack_log(skp->smk_known, obj_label, mode, rc, a); | 252 | smack_log(sbj_known->smk_known, obj_known->smk_known, |
253 | mode, rc, a); | ||
241 | #endif | 254 | #endif |
242 | return rc; | 255 | return rc; |
243 | } | 256 | } |
244 | 257 | ||
245 | /** | 258 | /** |
246 | * smk_curacc - determine if current has a specific access to an object | 259 | * smk_curacc - determine if current has a specific access to an object |
247 | * @obj_label: a pointer to the object's Smack label | 260 | * @obj_known: a pointer to the object's Smack label entry |
248 | * @mode: the access requested, in "MAY" format | 261 | * @mode: the access requested, in "MAY" format |
249 | * @a : common audit data | 262 | * @a : common audit data |
250 | * | 263 | * |
@@ -253,11 +266,12 @@ out_audit: | |||
253 | * non zero otherwise. It allows that current may have the capability | 266 | * non zero otherwise. It allows that current may have the capability |
254 | * to override the rules. | 267 | * to override the rules. |
255 | */ | 268 | */ |
256 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | 269 | int smk_curacc(struct smack_known *obj_known, |
270 | u32 mode, struct smk_audit_info *a) | ||
257 | { | 271 | { |
258 | struct task_smack *tsp = current_security(); | 272 | struct task_smack *tsp = current_security(); |
259 | 273 | ||
260 | return smk_tskacc(tsp, obj_label, mode, a); | 274 | return smk_tskacc(tsp, obj_known, mode, a); |
261 | } | 275 | } |
262 | 276 | ||
263 | #ifdef CONFIG_AUDIT | 277 | #ifdef CONFIG_AUDIT |
@@ -328,6 +342,13 @@ void smack_log(char *subject_label, char *object_label, int request, | |||
328 | struct smack_audit_data *sad; | 342 | struct smack_audit_data *sad; |
329 | struct common_audit_data *a = &ad->a; | 343 | struct common_audit_data *a = &ad->a; |
330 | 344 | ||
345 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
346 | /* | ||
347 | * The result may be positive in bringup mode. | ||
348 | */ | ||
349 | if (result > 0) | ||
350 | result = 0; | ||
351 | #endif | ||
331 | /* check if we have to log the current event */ | 352 | /* check if we have to log the current event */ |
332 | if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) | 353 | if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) |
333 | return; | 354 | return; |
@@ -544,27 +565,6 @@ unlockout: | |||
544 | } | 565 | } |
545 | 566 | ||
546 | /** | 567 | /** |
547 | * smk_import - import a smack label | ||
548 | * @string: a text string that might be a Smack label | ||
549 | * @len: the maximum size, or zero if it is NULL terminated. | ||
550 | * | ||
551 | * Returns a pointer to the label in the label list that | ||
552 | * matches the passed string, adding it if necessary. | ||
553 | */ | ||
554 | char *smk_import(const char *string, int len) | ||
555 | { | ||
556 | struct smack_known *skp; | ||
557 | |||
558 | /* labels cannot begin with a '-' */ | ||
559 | if (string[0] == '-') | ||
560 | return NULL; | ||
561 | skp = smk_import_entry(string, len); | ||
562 | if (skp == NULL) | ||
563 | return NULL; | ||
564 | return skp->smk_known; | ||
565 | } | ||
566 | |||
567 | /** | ||
568 | * smack_from_secid - find the Smack label associated with a secid | 568 | * smack_from_secid - find the Smack label associated with a secid |
569 | * @secid: an integer that might be associated with a Smack label | 569 | * @secid: an integer that might be associated with a Smack label |
570 | * | 570 | * |
@@ -590,19 +590,3 @@ struct smack_known *smack_from_secid(const u32 secid) | |||
590 | rcu_read_unlock(); | 590 | rcu_read_unlock(); |
591 | return &smack_known_invalid; | 591 | return &smack_known_invalid; |
592 | } | 592 | } |
593 | |||
594 | /** | ||
595 | * smack_to_secid - find the secid associated with a Smack label | ||
596 | * @smack: the Smack label | ||
597 | * | ||
598 | * Returns the appropriate secid if there is one, | ||
599 | * otherwise 0 | ||
600 | */ | ||
601 | u32 smack_to_secid(const char *smack) | ||
602 | { | ||
603 | struct smack_known *skp = smk_find_entry(smack); | ||
604 | |||
605 | if (skp == NULL) | ||
606 | return 0; | ||
607 | return skp->smk_secid; | ||
608 | } | ||
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index e6ab307ce86e..93dc876734a4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -54,6 +54,151 @@ | |||
54 | 54 | ||
55 | LIST_HEAD(smk_ipv6_port_list); | 55 | LIST_HEAD(smk_ipv6_port_list); |
56 | 56 | ||
57 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
58 | static void smk_bu_mode(int mode, char *s) | ||
59 | { | ||
60 | int i = 0; | ||
61 | |||
62 | if (mode & MAY_READ) | ||
63 | s[i++] = 'r'; | ||
64 | if (mode & MAY_WRITE) | ||
65 | s[i++] = 'w'; | ||
66 | if (mode & MAY_EXEC) | ||
67 | s[i++] = 'x'; | ||
68 | if (mode & MAY_APPEND) | ||
69 | s[i++] = 'a'; | ||
70 | if (mode & MAY_TRANSMUTE) | ||
71 | s[i++] = 't'; | ||
72 | if (mode & MAY_LOCK) | ||
73 | s[i++] = 'l'; | ||
74 | if (i == 0) | ||
75 | s[i++] = '-'; | ||
76 | s[i] = '\0'; | ||
77 | } | ||
78 | #endif | ||
79 | |||
80 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
81 | static int smk_bu_note(char *note, struct smack_known *sskp, | ||
82 | struct smack_known *oskp, int mode, int rc) | ||
83 | { | ||
84 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
85 | |||
86 | if (rc <= 0) | ||
87 | return rc; | ||
88 | |||
89 | smk_bu_mode(mode, acc); | ||
90 | pr_info("Smack Bringup: (%s %s %s) %s\n", | ||
91 | sskp->smk_known, oskp->smk_known, acc, note); | ||
92 | return 0; | ||
93 | } | ||
94 | #else | ||
95 | #define smk_bu_note(note, sskp, oskp, mode, RC) (RC) | ||
96 | #endif | ||
97 | |||
98 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
99 | static int smk_bu_current(char *note, struct smack_known *oskp, | ||
100 | int mode, int rc) | ||
101 | { | ||
102 | struct task_smack *tsp = current_security(); | ||
103 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
104 | |||
105 | if (rc <= 0) | ||
106 | return rc; | ||
107 | |||
108 | smk_bu_mode(mode, acc); | ||
109 | pr_info("Smack Bringup: (%s %s %s) %s %s\n", | ||
110 | tsp->smk_task->smk_known, oskp->smk_known, | ||
111 | acc, current->comm, note); | ||
112 | return 0; | ||
113 | } | ||
114 | #else | ||
115 | #define smk_bu_current(note, oskp, mode, RC) (RC) | ||
116 | #endif | ||
117 | |||
118 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
119 | static int smk_bu_task(struct task_struct *otp, int mode, int rc) | ||
120 | { | ||
121 | struct task_smack *tsp = current_security(); | ||
122 | struct task_smack *otsp = task_security(otp); | ||
123 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
124 | |||
125 | if (rc <= 0) | ||
126 | return rc; | ||
127 | |||
128 | smk_bu_mode(mode, acc); | ||
129 | pr_info("Smack Bringup: (%s %s %s) %s to %s\n", | ||
130 | tsp->smk_task->smk_known, otsp->smk_task->smk_known, acc, | ||
131 | current->comm, otp->comm); | ||
132 | return 0; | ||
133 | } | ||
134 | #else | ||
135 | #define smk_bu_task(otp, mode, RC) (RC) | ||
136 | #endif | ||
137 | |||
138 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
139 | static int smk_bu_inode(struct inode *inode, int mode, int rc) | ||
140 | { | ||
141 | struct task_smack *tsp = current_security(); | ||
142 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
143 | |||
144 | if (rc <= 0) | ||
145 | return rc; | ||
146 | |||
147 | smk_bu_mode(mode, acc); | ||
148 | pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n", | ||
149 | tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc, | ||
150 | inode->i_sb->s_id, inode->i_ino, current->comm); | ||
151 | return 0; | ||
152 | } | ||
153 | #else | ||
154 | #define smk_bu_inode(inode, mode, RC) (RC) | ||
155 | #endif | ||
156 | |||
157 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
158 | static int smk_bu_file(struct file *file, int mode, int rc) | ||
159 | { | ||
160 | struct task_smack *tsp = current_security(); | ||
161 | struct smack_known *sskp = tsp->smk_task; | ||
162 | struct inode *inode = file->f_inode; | ||
163 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
164 | |||
165 | if (rc <= 0) | ||
166 | return rc; | ||
167 | |||
168 | smk_bu_mode(mode, acc); | ||
169 | pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %s) %s\n", | ||
170 | sskp->smk_known, (char *)file->f_security, acc, | ||
171 | inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name, | ||
172 | current->comm); | ||
173 | return 0; | ||
174 | } | ||
175 | #else | ||
176 | #define smk_bu_file(file, mode, RC) (RC) | ||
177 | #endif | ||
178 | |||
179 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | ||
180 | static int smk_bu_credfile(const struct cred *cred, struct file *file, | ||
181 | int mode, int rc) | ||
182 | { | ||
183 | struct task_smack *tsp = cred->security; | ||
184 | struct smack_known *sskp = tsp->smk_task; | ||
185 | struct inode *inode = file->f_inode; | ||
186 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | ||
187 | |||
188 | if (rc <= 0) | ||
189 | return rc; | ||
190 | |||
191 | smk_bu_mode(mode, acc); | ||
192 | pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %s) %s\n", | ||
193 | sskp->smk_known, smk_of_inode(inode)->smk_known, acc, | ||
194 | inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name, | ||
195 | current->comm); | ||
196 | return 0; | ||
197 | } | ||
198 | #else | ||
199 | #define smk_bu_credfile(cred, file, mode, RC) (RC) | ||
200 | #endif | ||
201 | |||
57 | /** | 202 | /** |
58 | * smk_fetch - Fetch the smack label from a file. | 203 | * smk_fetch - Fetch the smack label from a file. |
59 | * @ip: a pointer to the inode | 204 | * @ip: a pointer to the inode |
@@ -87,11 +232,11 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip, | |||
87 | 232 | ||
88 | /** | 233 | /** |
89 | * new_inode_smack - allocate an inode security blob | 234 | * new_inode_smack - allocate an inode security blob |
90 | * @smack: a pointer to the Smack label to use in the blob | 235 | * @skp: a pointer to the Smack label entry to use in the blob |
91 | * | 236 | * |
92 | * Returns the new blob or NULL if there's no memory available | 237 | * Returns the new blob or NULL if there's no memory available |
93 | */ | 238 | */ |
94 | struct inode_smack *new_inode_smack(char *smack) | 239 | struct inode_smack *new_inode_smack(struct smack_known *skp) |
95 | { | 240 | { |
96 | struct inode_smack *isp; | 241 | struct inode_smack *isp; |
97 | 242 | ||
@@ -99,7 +244,7 @@ struct inode_smack *new_inode_smack(char *smack) | |||
99 | if (isp == NULL) | 244 | if (isp == NULL) |
100 | return NULL; | 245 | return NULL; |
101 | 246 | ||
102 | isp->smk_inode = smack; | 247 | isp->smk_inode = skp; |
103 | isp->smk_flags = 0; | 248 | isp->smk_flags = 0; |
104 | mutex_init(&isp->smk_lock); | 249 | mutex_init(&isp->smk_lock); |
105 | 250 | ||
@@ -178,20 +323,20 @@ static inline unsigned int smk_ptrace_mode(unsigned int mode) | |||
178 | /** | 323 | /** |
179 | * smk_ptrace_rule_check - helper for ptrace access | 324 | * smk_ptrace_rule_check - helper for ptrace access |
180 | * @tracer: tracer process | 325 | * @tracer: tracer process |
181 | * @tracee_label: label of the process that's about to be traced, | 326 | * @tracee_known: label entry of the process that's about to be traced |
182 | * the pointer must originate from smack structures | ||
183 | * @mode: ptrace attachment mode (PTRACE_MODE_*) | 327 | * @mode: ptrace attachment mode (PTRACE_MODE_*) |
184 | * @func: name of the function that called us, used for audit | 328 | * @func: name of the function that called us, used for audit |
185 | * | 329 | * |
186 | * Returns 0 on access granted, -error on error | 330 | * Returns 0 on access granted, -error on error |
187 | */ | 331 | */ |
188 | static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | 332 | static int smk_ptrace_rule_check(struct task_struct *tracer, |
333 | struct smack_known *tracee_known, | ||
189 | unsigned int mode, const char *func) | 334 | unsigned int mode, const char *func) |
190 | { | 335 | { |
191 | int rc; | 336 | int rc; |
192 | struct smk_audit_info ad, *saip = NULL; | 337 | struct smk_audit_info ad, *saip = NULL; |
193 | struct task_smack *tsp; | 338 | struct task_smack *tsp; |
194 | struct smack_known *skp; | 339 | struct smack_known *tracer_known; |
195 | 340 | ||
196 | if ((mode & PTRACE_MODE_NOAUDIT) == 0) { | 341 | if ((mode & PTRACE_MODE_NOAUDIT) == 0) { |
197 | smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); | 342 | smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); |
@@ -200,12 +345,12 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | |||
200 | } | 345 | } |
201 | 346 | ||
202 | tsp = task_security(tracer); | 347 | tsp = task_security(tracer); |
203 | skp = smk_of_task(tsp); | 348 | tracer_known = smk_of_task(tsp); |
204 | 349 | ||
205 | if ((mode & PTRACE_MODE_ATTACH) && | 350 | if ((mode & PTRACE_MODE_ATTACH) && |
206 | (smack_ptrace_rule == SMACK_PTRACE_EXACT || | 351 | (smack_ptrace_rule == SMACK_PTRACE_EXACT || |
207 | smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { | 352 | smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { |
208 | if (skp->smk_known == tracee_label) | 353 | if (tracer_known->smk_known == tracee_known->smk_known) |
209 | rc = 0; | 354 | rc = 0; |
210 | else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) | 355 | else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) |
211 | rc = -EACCES; | 356 | rc = -EACCES; |
@@ -215,13 +360,15 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | |||
215 | rc = -EACCES; | 360 | rc = -EACCES; |
216 | 361 | ||
217 | if (saip) | 362 | if (saip) |
218 | smack_log(skp->smk_known, tracee_label, 0, rc, saip); | 363 | smack_log(tracer_known->smk_known, |
364 | tracee_known->smk_known, | ||
365 | 0, rc, saip); | ||
219 | 366 | ||
220 | return rc; | 367 | return rc; |
221 | } | 368 | } |
222 | 369 | ||
223 | /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ | 370 | /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ |
224 | rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); | 371 | rc = smk_tskacc(tsp, tracee_known, smk_ptrace_mode(mode), saip); |
225 | return rc; | 372 | return rc; |
226 | } | 373 | } |
227 | 374 | ||
@@ -250,7 +397,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
250 | 397 | ||
251 | skp = smk_of_task(task_security(ctp)); | 398 | skp = smk_of_task(task_security(ctp)); |
252 | 399 | ||
253 | rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__); | 400 | rc = smk_ptrace_rule_check(current, skp, mode, __func__); |
254 | return rc; | 401 | return rc; |
255 | } | 402 | } |
256 | 403 | ||
@@ -273,8 +420,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
273 | 420 | ||
274 | skp = smk_of_task(current_security()); | 421 | skp = smk_of_task(current_security()); |
275 | 422 | ||
276 | rc = smk_ptrace_rule_check(ptp, skp->smk_known, | 423 | rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__); |
277 | PTRACE_MODE_ATTACH, __func__); | ||
278 | return rc; | 424 | return rc; |
279 | } | 425 | } |
280 | 426 | ||
@@ -318,10 +464,10 @@ static int smack_sb_alloc_security(struct super_block *sb) | |||
318 | if (sbsp == NULL) | 464 | if (sbsp == NULL) |
319 | return -ENOMEM; | 465 | return -ENOMEM; |
320 | 466 | ||
321 | sbsp->smk_root = smack_known_floor.smk_known; | 467 | sbsp->smk_root = &smack_known_floor; |
322 | sbsp->smk_default = smack_known_floor.smk_known; | 468 | sbsp->smk_default = &smack_known_floor; |
323 | sbsp->smk_floor = smack_known_floor.smk_known; | 469 | sbsp->smk_floor = &smack_known_floor; |
324 | sbsp->smk_hat = smack_known_hat.smk_known; | 470 | sbsp->smk_hat = &smack_known_hat; |
325 | /* | 471 | /* |
326 | * smk_initialized will be zero from kzalloc. | 472 | * smk_initialized will be zero from kzalloc. |
327 | */ | 473 | */ |
@@ -405,7 +551,6 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
405 | struct smack_known *skp; | 551 | struct smack_known *skp; |
406 | char *op; | 552 | char *op; |
407 | char *commap; | 553 | char *commap; |
408 | char *nsp; | ||
409 | int transmute = 0; | 554 | int transmute = 0; |
410 | int specified = 0; | 555 | int specified = 0; |
411 | 556 | ||
@@ -421,38 +566,38 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
421 | 566 | ||
422 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { | 567 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { |
423 | op += strlen(SMK_FSHAT); | 568 | op += strlen(SMK_FSHAT); |
424 | nsp = smk_import(op, 0); | 569 | skp = smk_import_entry(op, 0); |
425 | if (nsp != NULL) { | 570 | if (skp != NULL) { |
426 | sp->smk_hat = nsp; | 571 | sp->smk_hat = skp; |
427 | specified = 1; | 572 | specified = 1; |
428 | } | 573 | } |
429 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { | 574 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { |
430 | op += strlen(SMK_FSFLOOR); | 575 | op += strlen(SMK_FSFLOOR); |
431 | nsp = smk_import(op, 0); | 576 | skp = smk_import_entry(op, 0); |
432 | if (nsp != NULL) { | 577 | if (skp != NULL) { |
433 | sp->smk_floor = nsp; | 578 | sp->smk_floor = skp; |
434 | specified = 1; | 579 | specified = 1; |
435 | } | 580 | } |
436 | } else if (strncmp(op, SMK_FSDEFAULT, | 581 | } else if (strncmp(op, SMK_FSDEFAULT, |
437 | strlen(SMK_FSDEFAULT)) == 0) { | 582 | strlen(SMK_FSDEFAULT)) == 0) { |
438 | op += strlen(SMK_FSDEFAULT); | 583 | op += strlen(SMK_FSDEFAULT); |
439 | nsp = smk_import(op, 0); | 584 | skp = smk_import_entry(op, 0); |
440 | if (nsp != NULL) { | 585 | if (skp != NULL) { |
441 | sp->smk_default = nsp; | 586 | sp->smk_default = skp; |
442 | specified = 1; | 587 | specified = 1; |
443 | } | 588 | } |
444 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { | 589 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { |
445 | op += strlen(SMK_FSROOT); | 590 | op += strlen(SMK_FSROOT); |
446 | nsp = smk_import(op, 0); | 591 | skp = smk_import_entry(op, 0); |
447 | if (nsp != NULL) { | 592 | if (skp != NULL) { |
448 | sp->smk_root = nsp; | 593 | sp->smk_root = skp; |
449 | specified = 1; | 594 | specified = 1; |
450 | } | 595 | } |
451 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { | 596 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { |
452 | op += strlen(SMK_FSTRANS); | 597 | op += strlen(SMK_FSTRANS); |
453 | nsp = smk_import(op, 0); | 598 | skp = smk_import_entry(op, 0); |
454 | if (nsp != NULL) { | 599 | if (skp != NULL) { |
455 | sp->smk_root = nsp; | 600 | sp->smk_root = skp; |
456 | transmute = 1; | 601 | transmute = 1; |
457 | specified = 1; | 602 | specified = 1; |
458 | } | 603 | } |
@@ -469,8 +614,8 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
469 | * Unprivileged mounts get root and default from the caller. | 614 | * Unprivileged mounts get root and default from the caller. |
470 | */ | 615 | */ |
471 | skp = smk_of_current(); | 616 | skp = smk_of_current(); |
472 | sp->smk_root = skp->smk_known; | 617 | sp->smk_root = skp; |
473 | sp->smk_default = skp->smk_known; | 618 | sp->smk_default = skp; |
474 | } | 619 | } |
475 | /* | 620 | /* |
476 | * Initialize the root inode. | 621 | * Initialize the root inode. |
@@ -507,6 +652,7 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
507 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 652 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
508 | 653 | ||
509 | rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); | 654 | rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad); |
655 | rc = smk_bu_current("statfs", sbp->smk_floor, MAY_READ, rc); | ||
510 | return rc; | 656 | return rc; |
511 | } | 657 | } |
512 | 658 | ||
@@ -546,7 +692,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) | |||
546 | tracer = ptrace_parent(current); | 692 | tracer = ptrace_parent(current); |
547 | if (likely(tracer != NULL)) | 693 | if (likely(tracer != NULL)) |
548 | rc = smk_ptrace_rule_check(tracer, | 694 | rc = smk_ptrace_rule_check(tracer, |
549 | isp->smk_task->smk_known, | 695 | isp->smk_task, |
550 | PTRACE_MODE_ATTACH, | 696 | PTRACE_MODE_ATTACH, |
551 | __func__); | 697 | __func__); |
552 | rcu_read_unlock(); | 698 | rcu_read_unlock(); |
@@ -607,7 +753,7 @@ static int smack_inode_alloc_security(struct inode *inode) | |||
607 | { | 753 | { |
608 | struct smack_known *skp = smk_of_current(); | 754 | struct smack_known *skp = smk_of_current(); |
609 | 755 | ||
610 | inode->i_security = new_inode_smack(skp->smk_known); | 756 | inode->i_security = new_inode_smack(skp); |
611 | if (inode->i_security == NULL) | 757 | if (inode->i_security == NULL) |
612 | return -ENOMEM; | 758 | return -ENOMEM; |
613 | return 0; | 759 | return 0; |
@@ -627,8 +773,8 @@ static void smack_inode_free_security(struct inode *inode) | |||
627 | 773 | ||
628 | /** | 774 | /** |
629 | * smack_inode_init_security - copy out the smack from an inode | 775 | * smack_inode_init_security - copy out the smack from an inode |
630 | * @inode: the inode | 776 | * @inode: the newly created inode |
631 | * @dir: unused | 777 | * @dir: containing directory object |
632 | * @qstr: unused | 778 | * @qstr: unused |
633 | * @name: where to put the attribute name | 779 | * @name: where to put the attribute name |
634 | * @value: where to put the attribute value | 780 | * @value: where to put the attribute value |
@@ -642,8 +788,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
642 | { | 788 | { |
643 | struct inode_smack *issp = inode->i_security; | 789 | struct inode_smack *issp = inode->i_security; |
644 | struct smack_known *skp = smk_of_current(); | 790 | struct smack_known *skp = smk_of_current(); |
645 | char *isp = smk_of_inode(inode); | 791 | struct smack_known *isp = smk_of_inode(inode); |
646 | char *dsp = smk_of_inode(dir); | 792 | struct smack_known *dsp = smk_of_inode(dir); |
647 | int may; | 793 | int may; |
648 | 794 | ||
649 | if (name) | 795 | if (name) |
@@ -651,7 +797,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
651 | 797 | ||
652 | if (value) { | 798 | if (value) { |
653 | rcu_read_lock(); | 799 | rcu_read_lock(); |
654 | may = smk_access_entry(skp->smk_known, dsp, &skp->smk_rules); | 800 | may = smk_access_entry(skp->smk_known, dsp->smk_known, |
801 | &skp->smk_rules); | ||
655 | rcu_read_unlock(); | 802 | rcu_read_unlock(); |
656 | 803 | ||
657 | /* | 804 | /* |
@@ -666,13 +813,13 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
666 | issp->smk_flags |= SMK_INODE_CHANGED; | 813 | issp->smk_flags |= SMK_INODE_CHANGED; |
667 | } | 814 | } |
668 | 815 | ||
669 | *value = kstrdup(isp, GFP_NOFS); | 816 | *value = kstrdup(isp->smk_known, GFP_NOFS); |
670 | if (*value == NULL) | 817 | if (*value == NULL) |
671 | return -ENOMEM; | 818 | return -ENOMEM; |
672 | } | 819 | } |
673 | 820 | ||
674 | if (len) | 821 | if (len) |
675 | *len = strlen(isp) + 1; | 822 | *len = strlen(isp->smk_known); |
676 | 823 | ||
677 | return 0; | 824 | return 0; |
678 | } | 825 | } |
@@ -688,7 +835,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
688 | static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, | 835 | static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, |
689 | struct dentry *new_dentry) | 836 | struct dentry *new_dentry) |
690 | { | 837 | { |
691 | char *isp; | 838 | struct smack_known *isp; |
692 | struct smk_audit_info ad; | 839 | struct smk_audit_info ad; |
693 | int rc; | 840 | int rc; |
694 | 841 | ||
@@ -697,11 +844,13 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir, | |||
697 | 844 | ||
698 | isp = smk_of_inode(old_dentry->d_inode); | 845 | isp = smk_of_inode(old_dentry->d_inode); |
699 | rc = smk_curacc(isp, MAY_WRITE, &ad); | 846 | rc = smk_curacc(isp, MAY_WRITE, &ad); |
847 | rc = smk_bu_inode(old_dentry->d_inode, MAY_WRITE, rc); | ||
700 | 848 | ||
701 | if (rc == 0 && new_dentry->d_inode != NULL) { | 849 | if (rc == 0 && new_dentry->d_inode != NULL) { |
702 | isp = smk_of_inode(new_dentry->d_inode); | 850 | isp = smk_of_inode(new_dentry->d_inode); |
703 | smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); | 851 | smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); |
704 | rc = smk_curacc(isp, MAY_WRITE, &ad); | 852 | rc = smk_curacc(isp, MAY_WRITE, &ad); |
853 | rc = smk_bu_inode(new_dentry->d_inode, MAY_WRITE, rc); | ||
705 | } | 854 | } |
706 | 855 | ||
707 | return rc; | 856 | return rc; |
@@ -728,6 +877,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) | |||
728 | * You need write access to the thing you're unlinking | 877 | * You need write access to the thing you're unlinking |
729 | */ | 878 | */ |
730 | rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad); | 879 | rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad); |
880 | rc = smk_bu_inode(ip, MAY_WRITE, rc); | ||
731 | if (rc == 0) { | 881 | if (rc == 0) { |
732 | /* | 882 | /* |
733 | * You also need write access to the containing directory | 883 | * You also need write access to the containing directory |
@@ -735,6 +885,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry) | |||
735 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | 885 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); |
736 | smk_ad_setfield_u_fs_inode(&ad, dir); | 886 | smk_ad_setfield_u_fs_inode(&ad, dir); |
737 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); | 887 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); |
888 | rc = smk_bu_inode(dir, MAY_WRITE, rc); | ||
738 | } | 889 | } |
739 | return rc; | 890 | return rc; |
740 | } | 891 | } |
@@ -759,6 +910,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
759 | * You need write access to the thing you're removing | 910 | * You need write access to the thing you're removing |
760 | */ | 911 | */ |
761 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 912 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
913 | rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); | ||
762 | if (rc == 0) { | 914 | if (rc == 0) { |
763 | /* | 915 | /* |
764 | * You also need write access to the containing directory | 916 | * You also need write access to the containing directory |
@@ -766,6 +918,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
766 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | 918 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); |
767 | smk_ad_setfield_u_fs_inode(&ad, dir); | 919 | smk_ad_setfield_u_fs_inode(&ad, dir); |
768 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); | 920 | rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad); |
921 | rc = smk_bu_inode(dir, MAY_WRITE, rc); | ||
769 | } | 922 | } |
770 | 923 | ||
771 | return rc; | 924 | return rc; |
@@ -773,10 +926,10 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry) | |||
773 | 926 | ||
774 | /** | 927 | /** |
775 | * smack_inode_rename - Smack check on rename | 928 | * smack_inode_rename - Smack check on rename |
776 | * @old_inode: the old directory | 929 | * @old_inode: unused |
777 | * @old_dentry: unused | 930 | * @old_dentry: the old object |
778 | * @new_inode: the new directory | 931 | * @new_inode: unused |
779 | * @new_dentry: unused | 932 | * @new_dentry: the new object |
780 | * | 933 | * |
781 | * Read and write access is required on both the old and | 934 | * Read and write access is required on both the old and |
782 | * new directories. | 935 | * new directories. |
@@ -789,7 +942,7 @@ static int smack_inode_rename(struct inode *old_inode, | |||
789 | struct dentry *new_dentry) | 942 | struct dentry *new_dentry) |
790 | { | 943 | { |
791 | int rc; | 944 | int rc; |
792 | char *isp; | 945 | struct smack_known *isp; |
793 | struct smk_audit_info ad; | 946 | struct smk_audit_info ad; |
794 | 947 | ||
795 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 948 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
@@ -797,11 +950,13 @@ static int smack_inode_rename(struct inode *old_inode, | |||
797 | 950 | ||
798 | isp = smk_of_inode(old_dentry->d_inode); | 951 | isp = smk_of_inode(old_dentry->d_inode); |
799 | rc = smk_curacc(isp, MAY_READWRITE, &ad); | 952 | rc = smk_curacc(isp, MAY_READWRITE, &ad); |
953 | rc = smk_bu_inode(old_dentry->d_inode, MAY_READWRITE, rc); | ||
800 | 954 | ||
801 | if (rc == 0 && new_dentry->d_inode != NULL) { | 955 | if (rc == 0 && new_dentry->d_inode != NULL) { |
802 | isp = smk_of_inode(new_dentry->d_inode); | 956 | isp = smk_of_inode(new_dentry->d_inode); |
803 | smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); | 957 | smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry); |
804 | rc = smk_curacc(isp, MAY_READWRITE, &ad); | 958 | rc = smk_curacc(isp, MAY_READWRITE, &ad); |
959 | rc = smk_bu_inode(new_dentry->d_inode, MAY_READWRITE, rc); | ||
805 | } | 960 | } |
806 | return rc; | 961 | return rc; |
807 | } | 962 | } |
@@ -819,6 +974,7 @@ static int smack_inode_permission(struct inode *inode, int mask) | |||
819 | { | 974 | { |
820 | struct smk_audit_info ad; | 975 | struct smk_audit_info ad; |
821 | int no_block = mask & MAY_NOT_BLOCK; | 976 | int no_block = mask & MAY_NOT_BLOCK; |
977 | int rc; | ||
822 | 978 | ||
823 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); | 979 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
824 | /* | 980 | /* |
@@ -832,7 +988,9 @@ static int smack_inode_permission(struct inode *inode, int mask) | |||
832 | return -ECHILD; | 988 | return -ECHILD; |
833 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); | 989 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE); |
834 | smk_ad_setfield_u_fs_inode(&ad, inode); | 990 | smk_ad_setfield_u_fs_inode(&ad, inode); |
835 | return smk_curacc(smk_of_inode(inode), mask, &ad); | 991 | rc = smk_curacc(smk_of_inode(inode), mask, &ad); |
992 | rc = smk_bu_inode(inode, mask, rc); | ||
993 | return rc; | ||
836 | } | 994 | } |
837 | 995 | ||
838 | /** | 996 | /** |
@@ -845,6 +1003,8 @@ static int smack_inode_permission(struct inode *inode, int mask) | |||
845 | static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 1003 | static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
846 | { | 1004 | { |
847 | struct smk_audit_info ad; | 1005 | struct smk_audit_info ad; |
1006 | int rc; | ||
1007 | |||
848 | /* | 1008 | /* |
849 | * Need to allow for clearing the setuid bit. | 1009 | * Need to allow for clearing the setuid bit. |
850 | */ | 1010 | */ |
@@ -853,12 +1013,14 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
853 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 1013 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
854 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1014 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
855 | 1015 | ||
856 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 1016 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
1017 | rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); | ||
1018 | return rc; | ||
857 | } | 1019 | } |
858 | 1020 | ||
859 | /** | 1021 | /** |
860 | * smack_inode_getattr - Smack check for getting attributes | 1022 | * smack_inode_getattr - Smack check for getting attributes |
861 | * @mnt: unused | 1023 | * @mnt: vfsmount of the object |
862 | * @dentry: the object | 1024 | * @dentry: the object |
863 | * | 1025 | * |
864 | * Returns 0 if access is permitted, an error code otherwise | 1026 | * Returns 0 if access is permitted, an error code otherwise |
@@ -867,21 +1029,24 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | |||
867 | { | 1029 | { |
868 | struct smk_audit_info ad; | 1030 | struct smk_audit_info ad; |
869 | struct path path; | 1031 | struct path path; |
1032 | int rc; | ||
870 | 1033 | ||
871 | path.dentry = dentry; | 1034 | path.dentry = dentry; |
872 | path.mnt = mnt; | 1035 | path.mnt = mnt; |
873 | 1036 | ||
874 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1037 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
875 | smk_ad_setfield_u_fs_path(&ad, path); | 1038 | smk_ad_setfield_u_fs_path(&ad, path); |
876 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 1039 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
1040 | rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc); | ||
1041 | return rc; | ||
877 | } | 1042 | } |
878 | 1043 | ||
879 | /** | 1044 | /** |
880 | * smack_inode_setxattr - Smack check for setting xattrs | 1045 | * smack_inode_setxattr - Smack check for setting xattrs |
881 | * @dentry: the object | 1046 | * @dentry: the object |
882 | * @name: name of the attribute | 1047 | * @name: name of the attribute |
883 | * @value: unused | 1048 | * @value: value of the attribute |
884 | * @size: unused | 1049 | * @size: size of the value |
885 | * @flags: unused | 1050 | * @flags: unused |
886 | * | 1051 | * |
887 | * This protects the Smack attribute explicitly. | 1052 | * This protects the Smack attribute explicitly. |
@@ -923,7 +1088,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
923 | rc = -EPERM; | 1088 | rc = -EPERM; |
924 | 1089 | ||
925 | if (rc == 0 && check_import) { | 1090 | if (rc == 0 && check_import) { |
926 | skp = smk_import_entry(value, size); | 1091 | skp = size ? smk_import_entry(value, size) : NULL; |
927 | if (skp == NULL || (check_star && | 1092 | if (skp == NULL || (check_star && |
928 | (skp == &smack_known_star || skp == &smack_known_web))) | 1093 | (skp == &smack_known_star || skp == &smack_known_web))) |
929 | rc = -EINVAL; | 1094 | rc = -EINVAL; |
@@ -932,8 +1097,10 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
932 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 1097 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
933 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1098 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
934 | 1099 | ||
935 | if (rc == 0) | 1100 | if (rc == 0) { |
936 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 1101 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
1102 | rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); | ||
1103 | } | ||
937 | 1104 | ||
938 | return rc; | 1105 | return rc; |
939 | } | 1106 | } |
@@ -963,9 +1130,9 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
963 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { | 1130 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { |
964 | skp = smk_import_entry(value, size); | 1131 | skp = smk_import_entry(value, size); |
965 | if (skp != NULL) | 1132 | if (skp != NULL) |
966 | isp->smk_inode = skp->smk_known; | 1133 | isp->smk_inode = skp; |
967 | else | 1134 | else |
968 | isp->smk_inode = smack_known_invalid.smk_known; | 1135 | isp->smk_inode = &smack_known_invalid; |
969 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | 1136 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { |
970 | skp = smk_import_entry(value, size); | 1137 | skp = smk_import_entry(value, size); |
971 | if (skp != NULL) | 1138 | if (skp != NULL) |
@@ -993,11 +1160,14 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
993 | static int smack_inode_getxattr(struct dentry *dentry, const char *name) | 1160 | static int smack_inode_getxattr(struct dentry *dentry, const char *name) |
994 | { | 1161 | { |
995 | struct smk_audit_info ad; | 1162 | struct smk_audit_info ad; |
1163 | int rc; | ||
996 | 1164 | ||
997 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 1165 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
998 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1166 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
999 | 1167 | ||
1000 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 1168 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
1169 | rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc); | ||
1170 | return rc; | ||
1001 | } | 1171 | } |
1002 | 1172 | ||
1003 | /** | 1173 | /** |
@@ -1033,6 +1203,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
1033 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1203 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
1034 | 1204 | ||
1035 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | 1205 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
1206 | rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc); | ||
1036 | if (rc != 0) | 1207 | if (rc != 0) |
1037 | return rc; | 1208 | return rc; |
1038 | 1209 | ||
@@ -1070,14 +1241,14 @@ static int smack_inode_getsecurity(const struct inode *inode, | |||
1070 | struct socket *sock; | 1241 | struct socket *sock; |
1071 | struct super_block *sbp; | 1242 | struct super_block *sbp; |
1072 | struct inode *ip = (struct inode *)inode; | 1243 | struct inode *ip = (struct inode *)inode; |
1073 | char *isp; | 1244 | struct smack_known *isp; |
1074 | int ilen; | 1245 | int ilen; |
1075 | int rc = 0; | 1246 | int rc = 0; |
1076 | 1247 | ||
1077 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { | 1248 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
1078 | isp = smk_of_inode(inode); | 1249 | isp = smk_of_inode(inode); |
1079 | ilen = strlen(isp) + 1; | 1250 | ilen = strlen(isp->smk_known); |
1080 | *buffer = isp; | 1251 | *buffer = isp->smk_known; |
1081 | return ilen; | 1252 | return ilen; |
1082 | } | 1253 | } |
1083 | 1254 | ||
@@ -1095,15 +1266,15 @@ static int smack_inode_getsecurity(const struct inode *inode, | |||
1095 | ssp = sock->sk->sk_security; | 1266 | ssp = sock->sk->sk_security; |
1096 | 1267 | ||
1097 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) | 1268 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) |
1098 | isp = ssp->smk_in->smk_known; | 1269 | isp = ssp->smk_in; |
1099 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) | 1270 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) |
1100 | isp = ssp->smk_out->smk_known; | 1271 | isp = ssp->smk_out; |
1101 | else | 1272 | else |
1102 | return -EOPNOTSUPP; | 1273 | return -EOPNOTSUPP; |
1103 | 1274 | ||
1104 | ilen = strlen(isp) + 1; | 1275 | ilen = strlen(isp->smk_known); |
1105 | if (rc == 0) { | 1276 | if (rc == 0) { |
1106 | *buffer = isp; | 1277 | *buffer = isp->smk_known; |
1107 | rc = ilen; | 1278 | rc = ilen; |
1108 | } | 1279 | } |
1109 | 1280 | ||
@@ -1122,13 +1293,12 @@ static int smack_inode_getsecurity(const struct inode *inode, | |||
1122 | static int smack_inode_listsecurity(struct inode *inode, char *buffer, | 1293 | static int smack_inode_listsecurity(struct inode *inode, char *buffer, |
1123 | size_t buffer_size) | 1294 | size_t buffer_size) |
1124 | { | 1295 | { |
1125 | int len = strlen(XATTR_NAME_SMACK); | 1296 | int len = sizeof(XATTR_NAME_SMACK); |
1126 | 1297 | ||
1127 | if (buffer != NULL && len <= buffer_size) { | 1298 | if (buffer != NULL && len <= buffer_size) |
1128 | memcpy(buffer, XATTR_NAME_SMACK, len); | 1299 | memcpy(buffer, XATTR_NAME_SMACK, len); |
1129 | return len; | 1300 | |
1130 | } | 1301 | return len; |
1131 | return -EINVAL; | ||
1132 | } | 1302 | } |
1133 | 1303 | ||
1134 | /** | 1304 | /** |
@@ -1140,7 +1310,7 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid) | |||
1140 | { | 1310 | { |
1141 | struct inode_smack *isp = inode->i_security; | 1311 | struct inode_smack *isp = inode->i_security; |
1142 | 1312 | ||
1143 | *secid = smack_to_secid(isp->smk_inode); | 1313 | *secid = isp->smk_inode->smk_secid; |
1144 | } | 1314 | } |
1145 | 1315 | ||
1146 | /* | 1316 | /* |
@@ -1179,7 +1349,7 @@ static int smack_file_alloc_security(struct file *file) | |||
1179 | { | 1349 | { |
1180 | struct smack_known *skp = smk_of_current(); | 1350 | struct smack_known *skp = smk_of_current(); |
1181 | 1351 | ||
1182 | file->f_security = skp->smk_known; | 1352 | file->f_security = skp; |
1183 | return 0; | 1353 | return 0; |
1184 | } | 1354 | } |
1185 | 1355 | ||
@@ -1214,11 +1384,15 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, | |||
1214 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1384 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1215 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1385 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1216 | 1386 | ||
1217 | if (_IOC_DIR(cmd) & _IOC_WRITE) | 1387 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
1218 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); | 1388 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); |
1389 | rc = smk_bu_file(file, MAY_WRITE, rc); | ||
1390 | } | ||
1219 | 1391 | ||
1220 | if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) | 1392 | if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) { |
1221 | rc = smk_curacc(file->f_security, MAY_READ, &ad); | 1393 | rc = smk_curacc(file->f_security, MAY_READ, &ad); |
1394 | rc = smk_bu_file(file, MAY_READ, rc); | ||
1395 | } | ||
1222 | 1396 | ||
1223 | return rc; | 1397 | return rc; |
1224 | } | 1398 | } |
@@ -1233,10 +1407,13 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, | |||
1233 | static int smack_file_lock(struct file *file, unsigned int cmd) | 1407 | static int smack_file_lock(struct file *file, unsigned int cmd) |
1234 | { | 1408 | { |
1235 | struct smk_audit_info ad; | 1409 | struct smk_audit_info ad; |
1410 | int rc; | ||
1236 | 1411 | ||
1237 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1412 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1238 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1413 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1239 | return smk_curacc(file->f_security, MAY_LOCK, &ad); | 1414 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); |
1415 | rc = smk_bu_file(file, MAY_LOCK, rc); | ||
1416 | return rc; | ||
1240 | } | 1417 | } |
1241 | 1418 | ||
1242 | /** | 1419 | /** |
@@ -1266,12 +1443,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1266 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1443 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1267 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1444 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1268 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); | 1445 | rc = smk_curacc(file->f_security, MAY_LOCK, &ad); |
1446 | rc = smk_bu_file(file, MAY_LOCK, rc); | ||
1269 | break; | 1447 | break; |
1270 | case F_SETOWN: | 1448 | case F_SETOWN: |
1271 | case F_SETSIG: | 1449 | case F_SETSIG: |
1272 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1450 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1273 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1451 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1274 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); | 1452 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); |
1453 | rc = smk_bu_file(file, MAY_WRITE, rc); | ||
1275 | break; | 1454 | break; |
1276 | default: | 1455 | default: |
1277 | break; | 1456 | break; |
@@ -1298,7 +1477,7 @@ static int smack_mmap_file(struct file *file, | |||
1298 | struct smack_known *mkp; | 1477 | struct smack_known *mkp; |
1299 | struct smack_rule *srp; | 1478 | struct smack_rule *srp; |
1300 | struct task_smack *tsp; | 1479 | struct task_smack *tsp; |
1301 | char *osmack; | 1480 | struct smack_known *okp; |
1302 | struct inode_smack *isp; | 1481 | struct inode_smack *isp; |
1303 | int may; | 1482 | int may; |
1304 | int mmay; | 1483 | int mmay; |
@@ -1324,18 +1503,19 @@ static int smack_mmap_file(struct file *file, | |||
1324 | * to that rule's object label. | 1503 | * to that rule's object label. |
1325 | */ | 1504 | */ |
1326 | list_for_each_entry_rcu(srp, &skp->smk_rules, list) { | 1505 | list_for_each_entry_rcu(srp, &skp->smk_rules, list) { |
1327 | osmack = srp->smk_object; | 1506 | okp = srp->smk_object; |
1328 | /* | 1507 | /* |
1329 | * Matching labels always allows access. | 1508 | * Matching labels always allows access. |
1330 | */ | 1509 | */ |
1331 | if (mkp->smk_known == osmack) | 1510 | if (mkp->smk_known == okp->smk_known) |
1332 | continue; | 1511 | continue; |
1333 | /* | 1512 | /* |
1334 | * If there is a matching local rule take | 1513 | * If there is a matching local rule take |
1335 | * that into account as well. | 1514 | * that into account as well. |
1336 | */ | 1515 | */ |
1337 | may = smk_access_entry(srp->smk_subject->smk_known, osmack, | 1516 | may = smk_access_entry(srp->smk_subject->smk_known, |
1338 | &tsp->smk_rules); | 1517 | okp->smk_known, |
1518 | &tsp->smk_rules); | ||
1339 | if (may == -ENOENT) | 1519 | if (may == -ENOENT) |
1340 | may = srp->smk_access; | 1520 | may = srp->smk_access; |
1341 | else | 1521 | else |
@@ -1352,8 +1532,8 @@ static int smack_mmap_file(struct file *file, | |||
1352 | * If there isn't one a SMACK64MMAP subject | 1532 | * If there isn't one a SMACK64MMAP subject |
1353 | * can't have as much access as current. | 1533 | * can't have as much access as current. |
1354 | */ | 1534 | */ |
1355 | mmay = smk_access_entry(mkp->smk_known, osmack, | 1535 | mmay = smk_access_entry(mkp->smk_known, okp->smk_known, |
1356 | &mkp->smk_rules); | 1536 | &mkp->smk_rules); |
1357 | if (mmay == -ENOENT) { | 1537 | if (mmay == -ENOENT) { |
1358 | rc = -EACCES; | 1538 | rc = -EACCES; |
1359 | break; | 1539 | break; |
@@ -1362,8 +1542,8 @@ static int smack_mmap_file(struct file *file, | |||
1362 | * If there is a local entry it modifies the | 1542 | * If there is a local entry it modifies the |
1363 | * potential access, too. | 1543 | * potential access, too. |
1364 | */ | 1544 | */ |
1365 | tmay = smk_access_entry(mkp->smk_known, osmack, | 1545 | tmay = smk_access_entry(mkp->smk_known, okp->smk_known, |
1366 | &tsp->smk_rules); | 1546 | &tsp->smk_rules); |
1367 | if (tmay != -ENOENT) | 1547 | if (tmay != -ENOENT) |
1368 | mmay &= tmay; | 1548 | mmay &= tmay; |
1369 | 1549 | ||
@@ -1394,7 +1574,7 @@ static int smack_file_set_fowner(struct file *file) | |||
1394 | { | 1574 | { |
1395 | struct smack_known *skp = smk_of_current(); | 1575 | struct smack_known *skp = smk_of_current(); |
1396 | 1576 | ||
1397 | file->f_security = skp->smk_known; | 1577 | file->f_security = skp; |
1398 | return 0; | 1578 | return 0; |
1399 | } | 1579 | } |
1400 | 1580 | ||
@@ -1424,14 +1604,15 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
1424 | file = container_of(fown, struct file, f_owner); | 1604 | file = container_of(fown, struct file, f_owner); |
1425 | 1605 | ||
1426 | /* we don't log here as rc can be overriden */ | 1606 | /* we don't log here as rc can be overriden */ |
1427 | skp = smk_find_entry(file->f_security); | 1607 | skp = file->f_security; |
1428 | rc = smk_access(skp, tkp->smk_known, MAY_WRITE, NULL); | 1608 | rc = smk_access(skp, tkp, MAY_WRITE, NULL); |
1609 | rc = smk_bu_note("sigiotask", skp, tkp, MAY_WRITE, rc); | ||
1429 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) | 1610 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) |
1430 | rc = 0; | 1611 | rc = 0; |
1431 | 1612 | ||
1432 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1613 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1433 | smk_ad_setfield_u_tsk(&ad, tsk); | 1614 | smk_ad_setfield_u_tsk(&ad, tsk); |
1434 | smack_log(file->f_security, tkp->smk_known, MAY_WRITE, rc, &ad); | 1615 | smack_log(skp->smk_known, tkp->smk_known, MAY_WRITE, rc, &ad); |
1435 | return rc; | 1616 | return rc; |
1436 | } | 1617 | } |
1437 | 1618 | ||
@@ -1443,6 +1624,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
1443 | */ | 1624 | */ |
1444 | static int smack_file_receive(struct file *file) | 1625 | static int smack_file_receive(struct file *file) |
1445 | { | 1626 | { |
1627 | int rc; | ||
1446 | int may = 0; | 1628 | int may = 0; |
1447 | struct smk_audit_info ad; | 1629 | struct smk_audit_info ad; |
1448 | 1630 | ||
@@ -1456,7 +1638,9 @@ static int smack_file_receive(struct file *file) | |||
1456 | if (file->f_mode & FMODE_WRITE) | 1638 | if (file->f_mode & FMODE_WRITE) |
1457 | may |= MAY_WRITE; | 1639 | may |= MAY_WRITE; |
1458 | 1640 | ||
1459 | return smk_curacc(file->f_security, may, &ad); | 1641 | rc = smk_curacc(file->f_security, may, &ad); |
1642 | rc = smk_bu_file(file, may, rc); | ||
1643 | return rc; | ||
1460 | } | 1644 | } |
1461 | 1645 | ||
1462 | /** | 1646 | /** |
@@ -1478,12 +1662,15 @@ static int smack_file_open(struct file *file, const struct cred *cred) | |||
1478 | struct smk_audit_info ad; | 1662 | struct smk_audit_info ad; |
1479 | int rc; | 1663 | int rc; |
1480 | 1664 | ||
1481 | if (smack_privileged(CAP_MAC_OVERRIDE)) | 1665 | if (smack_privileged(CAP_MAC_OVERRIDE)) { |
1666 | file->f_security = isp->smk_inode; | ||
1482 | return 0; | 1667 | return 0; |
1668 | } | ||
1483 | 1669 | ||
1484 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 1670 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1485 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1671 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
1486 | rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad); | 1672 | rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad); |
1673 | rc = smk_bu_credfile(cred, file, MAY_READ, rc); | ||
1487 | if (rc == 0) | 1674 | if (rc == 0) |
1488 | file->f_security = isp->smk_inode; | 1675 | file->f_security = isp->smk_inode; |
1489 | 1676 | ||
@@ -1622,7 +1809,7 @@ static int smack_kernel_create_files_as(struct cred *new, | |||
1622 | struct inode_smack *isp = inode->i_security; | 1809 | struct inode_smack *isp = inode->i_security; |
1623 | struct task_smack *tsp = new->security; | 1810 | struct task_smack *tsp = new->security; |
1624 | 1811 | ||
1625 | tsp->smk_forked = smk_find_entry(isp->smk_inode); | 1812 | tsp->smk_forked = isp->smk_inode; |
1626 | tsp->smk_task = tsp->smk_forked; | 1813 | tsp->smk_task = tsp->smk_forked; |
1627 | return 0; | 1814 | return 0; |
1628 | } | 1815 | } |
@@ -1640,10 +1827,13 @@ static int smk_curacc_on_task(struct task_struct *p, int access, | |||
1640 | { | 1827 | { |
1641 | struct smk_audit_info ad; | 1828 | struct smk_audit_info ad; |
1642 | struct smack_known *skp = smk_of_task(task_security(p)); | 1829 | struct smack_known *skp = smk_of_task(task_security(p)); |
1830 | int rc; | ||
1643 | 1831 | ||
1644 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); | 1832 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); |
1645 | smk_ad_setfield_u_tsk(&ad, p); | 1833 | smk_ad_setfield_u_tsk(&ad, p); |
1646 | return smk_curacc(skp->smk_known, access, &ad); | 1834 | rc = smk_curacc(skp, access, &ad); |
1835 | rc = smk_bu_task(p, access, rc); | ||
1836 | return rc; | ||
1647 | } | 1837 | } |
1648 | 1838 | ||
1649 | /** | 1839 | /** |
@@ -1797,6 +1987,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1797 | struct smk_audit_info ad; | 1987 | struct smk_audit_info ad; |
1798 | struct smack_known *skp; | 1988 | struct smack_known *skp; |
1799 | struct smack_known *tkp = smk_of_task(task_security(p)); | 1989 | struct smack_known *tkp = smk_of_task(task_security(p)); |
1990 | int rc; | ||
1800 | 1991 | ||
1801 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1992 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1802 | smk_ad_setfield_u_tsk(&ad, p); | 1993 | smk_ad_setfield_u_tsk(&ad, p); |
@@ -1804,15 +1995,20 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1804 | * Sending a signal requires that the sender | 1995 | * Sending a signal requires that the sender |
1805 | * can write the receiver. | 1996 | * can write the receiver. |
1806 | */ | 1997 | */ |
1807 | if (secid == 0) | 1998 | if (secid == 0) { |
1808 | return smk_curacc(tkp->smk_known, MAY_WRITE, &ad); | 1999 | rc = smk_curacc(tkp, MAY_WRITE, &ad); |
2000 | rc = smk_bu_task(p, MAY_WRITE, rc); | ||
2001 | return rc; | ||
2002 | } | ||
1809 | /* | 2003 | /* |
1810 | * If the secid isn't 0 we're dealing with some USB IO | 2004 | * If the secid isn't 0 we're dealing with some USB IO |
1811 | * specific behavior. This is not clean. For one thing | 2005 | * specific behavior. This is not clean. For one thing |
1812 | * we can't take privilege into account. | 2006 | * we can't take privilege into account. |
1813 | */ | 2007 | */ |
1814 | skp = smack_from_secid(secid); | 2008 | skp = smack_from_secid(secid); |
1815 | return smk_access(skp, tkp->smk_known, MAY_WRITE, &ad); | 2009 | rc = smk_access(skp, tkp, MAY_WRITE, &ad); |
2010 | rc = smk_bu_note("USB signal", skp, tkp, MAY_WRITE, rc); | ||
2011 | return rc; | ||
1816 | } | 2012 | } |
1817 | 2013 | ||
1818 | /** | 2014 | /** |
@@ -1846,7 +2042,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | |||
1846 | struct inode_smack *isp = inode->i_security; | 2042 | struct inode_smack *isp = inode->i_security; |
1847 | struct smack_known *skp = smk_of_task(task_security(p)); | 2043 | struct smack_known *skp = smk_of_task(task_security(p)); |
1848 | 2044 | ||
1849 | isp->smk_inode = skp->smk_known; | 2045 | isp->smk_inode = skp; |
1850 | } | 2046 | } |
1851 | 2047 | ||
1852 | /* | 2048 | /* |
@@ -1904,7 +2100,7 @@ static void smack_sk_free_security(struct sock *sk) | |||
1904 | * | 2100 | * |
1905 | * Returns the label of the far end or NULL if it's not special. | 2101 | * Returns the label of the far end or NULL if it's not special. |
1906 | */ | 2102 | */ |
1907 | static char *smack_host_label(struct sockaddr_in *sip) | 2103 | static struct smack_known *smack_host_label(struct sockaddr_in *sip) |
1908 | { | 2104 | { |
1909 | struct smk_netlbladdr *snp; | 2105 | struct smk_netlbladdr *snp; |
1910 | struct in_addr *siap = &sip->sin_addr; | 2106 | struct in_addr *siap = &sip->sin_addr; |
@@ -1921,7 +2117,7 @@ static char *smack_host_label(struct sockaddr_in *sip) | |||
1921 | if ((&snp->smk_host.sin_addr)->s_addr == | 2117 | if ((&snp->smk_host.sin_addr)->s_addr == |
1922 | (siap->s_addr & (&snp->smk_mask)->s_addr)) { | 2118 | (siap->s_addr & (&snp->smk_mask)->s_addr)) { |
1923 | /* we have found the special CIPSO option */ | 2119 | /* we have found the special CIPSO option */ |
1924 | if (snp->smk_label == smack_cipso_option) | 2120 | if (snp->smk_label == &smack_cipso_option) |
1925 | return NULL; | 2121 | return NULL; |
1926 | return snp->smk_label; | 2122 | return snp->smk_label; |
1927 | } | 2123 | } |
@@ -1986,13 +2182,13 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
1986 | struct smack_known *skp; | 2182 | struct smack_known *skp; |
1987 | int rc; | 2183 | int rc; |
1988 | int sk_lbl; | 2184 | int sk_lbl; |
1989 | char *hostsp; | 2185 | struct smack_known *hkp; |
1990 | struct socket_smack *ssp = sk->sk_security; | 2186 | struct socket_smack *ssp = sk->sk_security; |
1991 | struct smk_audit_info ad; | 2187 | struct smk_audit_info ad; |
1992 | 2188 | ||
1993 | rcu_read_lock(); | 2189 | rcu_read_lock(); |
1994 | hostsp = smack_host_label(sap); | 2190 | hkp = smack_host_label(sap); |
1995 | if (hostsp != NULL) { | 2191 | if (hkp != NULL) { |
1996 | #ifdef CONFIG_AUDIT | 2192 | #ifdef CONFIG_AUDIT |
1997 | struct lsm_network_audit net; | 2193 | struct lsm_network_audit net; |
1998 | 2194 | ||
@@ -2003,7 +2199,8 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
2003 | #endif | 2199 | #endif |
2004 | sk_lbl = SMACK_UNLABELED_SOCKET; | 2200 | sk_lbl = SMACK_UNLABELED_SOCKET; |
2005 | skp = ssp->smk_out; | 2201 | skp = ssp->smk_out; |
2006 | rc = smk_access(skp, hostsp, MAY_WRITE, &ad); | 2202 | rc = smk_access(skp, hkp, MAY_WRITE, &ad); |
2203 | rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc); | ||
2007 | } else { | 2204 | } else { |
2008 | sk_lbl = SMACK_CIPSO_SOCKET; | 2205 | sk_lbl = SMACK_CIPSO_SOCKET; |
2009 | rc = 0; | 2206 | rc = 0; |
@@ -2104,18 +2301,19 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, | |||
2104 | struct socket_smack *ssp = sk->sk_security; | 2301 | struct socket_smack *ssp = sk->sk_security; |
2105 | struct smack_known *skp; | 2302 | struct smack_known *skp; |
2106 | unsigned short port = 0; | 2303 | unsigned short port = 0; |
2107 | char *object; | 2304 | struct smack_known *object; |
2108 | struct smk_audit_info ad; | 2305 | struct smk_audit_info ad; |
2306 | int rc; | ||
2109 | #ifdef CONFIG_AUDIT | 2307 | #ifdef CONFIG_AUDIT |
2110 | struct lsm_network_audit net; | 2308 | struct lsm_network_audit net; |
2111 | #endif | 2309 | #endif |
2112 | 2310 | ||
2113 | if (act == SMK_RECEIVING) { | 2311 | if (act == SMK_RECEIVING) { |
2114 | skp = smack_net_ambient; | 2312 | skp = smack_net_ambient; |
2115 | object = ssp->smk_in->smk_known; | 2313 | object = ssp->smk_in; |
2116 | } else { | 2314 | } else { |
2117 | skp = ssp->smk_out; | 2315 | skp = ssp->smk_out; |
2118 | object = smack_net_ambient->smk_known; | 2316 | object = smack_net_ambient; |
2119 | } | 2317 | } |
2120 | 2318 | ||
2121 | /* | 2319 | /* |
@@ -2142,7 +2340,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, | |||
2142 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { | 2340 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { |
2143 | if (spp->smk_port != port) | 2341 | if (spp->smk_port != port) |
2144 | continue; | 2342 | continue; |
2145 | object = spp->smk_in->smk_known; | 2343 | object = spp->smk_in; |
2146 | if (act == SMK_CONNECTING) | 2344 | if (act == SMK_CONNECTING) |
2147 | ssp->smk_packet = spp->smk_out; | 2345 | ssp->smk_packet = spp->smk_out; |
2148 | break; | 2346 | break; |
@@ -2159,7 +2357,9 @@ auditout: | |||
2159 | else | 2357 | else |
2160 | ad.a.u.net->v6info.daddr = address->sin6_addr; | 2358 | ad.a.u.net->v6info.daddr = address->sin6_addr; |
2161 | #endif | 2359 | #endif |
2162 | return smk_access(skp, object, MAY_WRITE, &ad); | 2360 | rc = smk_access(skp, object, MAY_WRITE, &ad); |
2361 | rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc); | ||
2362 | return rc; | ||
2163 | } | 2363 | } |
2164 | 2364 | ||
2165 | /** | 2365 | /** |
@@ -2191,7 +2391,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
2191 | return -EINVAL; | 2391 | return -EINVAL; |
2192 | 2392 | ||
2193 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { | 2393 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
2194 | nsp->smk_inode = skp->smk_known; | 2394 | nsp->smk_inode = skp; |
2195 | nsp->smk_flags |= SMK_INODE_INSTANT; | 2395 | nsp->smk_flags |= SMK_INODE_INSTANT; |
2196 | return 0; | 2396 | return 0; |
2197 | } | 2397 | } |
@@ -2333,7 +2533,7 @@ static int smack_msg_msg_alloc_security(struct msg_msg *msg) | |||
2333 | { | 2533 | { |
2334 | struct smack_known *skp = smk_of_current(); | 2534 | struct smack_known *skp = smk_of_current(); |
2335 | 2535 | ||
2336 | msg->security = skp->smk_known; | 2536 | msg->security = skp; |
2337 | return 0; | 2537 | return 0; |
2338 | } | 2538 | } |
2339 | 2539 | ||
@@ -2354,9 +2554,9 @@ static void smack_msg_msg_free_security(struct msg_msg *msg) | |||
2354 | * | 2554 | * |
2355 | * Returns a pointer to the smack value | 2555 | * Returns a pointer to the smack value |
2356 | */ | 2556 | */ |
2357 | static char *smack_of_shm(struct shmid_kernel *shp) | 2557 | static struct smack_known *smack_of_shm(struct shmid_kernel *shp) |
2358 | { | 2558 | { |
2359 | return (char *)shp->shm_perm.security; | 2559 | return (struct smack_known *)shp->shm_perm.security; |
2360 | } | 2560 | } |
2361 | 2561 | ||
2362 | /** | 2562 | /** |
@@ -2370,7 +2570,7 @@ static int smack_shm_alloc_security(struct shmid_kernel *shp) | |||
2370 | struct kern_ipc_perm *isp = &shp->shm_perm; | 2570 | struct kern_ipc_perm *isp = &shp->shm_perm; |
2371 | struct smack_known *skp = smk_of_current(); | 2571 | struct smack_known *skp = smk_of_current(); |
2372 | 2572 | ||
2373 | isp->security = skp->smk_known; | 2573 | isp->security = skp; |
2374 | return 0; | 2574 | return 0; |
2375 | } | 2575 | } |
2376 | 2576 | ||
@@ -2396,14 +2596,17 @@ static void smack_shm_free_security(struct shmid_kernel *shp) | |||
2396 | */ | 2596 | */ |
2397 | static int smk_curacc_shm(struct shmid_kernel *shp, int access) | 2597 | static int smk_curacc_shm(struct shmid_kernel *shp, int access) |
2398 | { | 2598 | { |
2399 | char *ssp = smack_of_shm(shp); | 2599 | struct smack_known *ssp = smack_of_shm(shp); |
2400 | struct smk_audit_info ad; | 2600 | struct smk_audit_info ad; |
2601 | int rc; | ||
2401 | 2602 | ||
2402 | #ifdef CONFIG_AUDIT | 2603 | #ifdef CONFIG_AUDIT |
2403 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); | 2604 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); |
2404 | ad.a.u.ipc_id = shp->shm_perm.id; | 2605 | ad.a.u.ipc_id = shp->shm_perm.id; |
2405 | #endif | 2606 | #endif |
2406 | return smk_curacc(ssp, access, &ad); | 2607 | rc = smk_curacc(ssp, access, &ad); |
2608 | rc = smk_bu_current("shm", ssp, access, rc); | ||
2609 | return rc; | ||
2407 | } | 2610 | } |
2408 | 2611 | ||
2409 | /** | 2612 | /** |
@@ -2478,9 +2681,9 @@ static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, | |||
2478 | * | 2681 | * |
2479 | * Returns a pointer to the smack value | 2682 | * Returns a pointer to the smack value |
2480 | */ | 2683 | */ |
2481 | static char *smack_of_sem(struct sem_array *sma) | 2684 | static struct smack_known *smack_of_sem(struct sem_array *sma) |
2482 | { | 2685 | { |
2483 | return (char *)sma->sem_perm.security; | 2686 | return (struct smack_known *)sma->sem_perm.security; |
2484 | } | 2687 | } |
2485 | 2688 | ||
2486 | /** | 2689 | /** |
@@ -2494,7 +2697,7 @@ static int smack_sem_alloc_security(struct sem_array *sma) | |||
2494 | struct kern_ipc_perm *isp = &sma->sem_perm; | 2697 | struct kern_ipc_perm *isp = &sma->sem_perm; |
2495 | struct smack_known *skp = smk_of_current(); | 2698 | struct smack_known *skp = smk_of_current(); |
2496 | 2699 | ||
2497 | isp->security = skp->smk_known; | 2700 | isp->security = skp; |
2498 | return 0; | 2701 | return 0; |
2499 | } | 2702 | } |
2500 | 2703 | ||
@@ -2520,14 +2723,17 @@ static void smack_sem_free_security(struct sem_array *sma) | |||
2520 | */ | 2723 | */ |
2521 | static int smk_curacc_sem(struct sem_array *sma, int access) | 2724 | static int smk_curacc_sem(struct sem_array *sma, int access) |
2522 | { | 2725 | { |
2523 | char *ssp = smack_of_sem(sma); | 2726 | struct smack_known *ssp = smack_of_sem(sma); |
2524 | struct smk_audit_info ad; | 2727 | struct smk_audit_info ad; |
2728 | int rc; | ||
2525 | 2729 | ||
2526 | #ifdef CONFIG_AUDIT | 2730 | #ifdef CONFIG_AUDIT |
2527 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); | 2731 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); |
2528 | ad.a.u.ipc_id = sma->sem_perm.id; | 2732 | ad.a.u.ipc_id = sma->sem_perm.id; |
2529 | #endif | 2733 | #endif |
2530 | return smk_curacc(ssp, access, &ad); | 2734 | rc = smk_curacc(ssp, access, &ad); |
2735 | rc = smk_bu_current("sem", ssp, access, rc); | ||
2736 | return rc; | ||
2531 | } | 2737 | } |
2532 | 2738 | ||
2533 | /** | 2739 | /** |
@@ -2613,7 +2819,7 @@ static int smack_msg_queue_alloc_security(struct msg_queue *msq) | |||
2613 | struct kern_ipc_perm *kisp = &msq->q_perm; | 2819 | struct kern_ipc_perm *kisp = &msq->q_perm; |
2614 | struct smack_known *skp = smk_of_current(); | 2820 | struct smack_known *skp = smk_of_current(); |
2615 | 2821 | ||
2616 | kisp->security = skp->smk_known; | 2822 | kisp->security = skp; |
2617 | return 0; | 2823 | return 0; |
2618 | } | 2824 | } |
2619 | 2825 | ||
@@ -2634,11 +2840,11 @@ static void smack_msg_queue_free_security(struct msg_queue *msq) | |||
2634 | * smack_of_msq - the smack pointer for the msq | 2840 | * smack_of_msq - the smack pointer for the msq |
2635 | * @msq: the object | 2841 | * @msq: the object |
2636 | * | 2842 | * |
2637 | * Returns a pointer to the smack value | 2843 | * Returns a pointer to the smack label entry |
2638 | */ | 2844 | */ |
2639 | static char *smack_of_msq(struct msg_queue *msq) | 2845 | static struct smack_known *smack_of_msq(struct msg_queue *msq) |
2640 | { | 2846 | { |
2641 | return (char *)msq->q_perm.security; | 2847 | return (struct smack_known *)msq->q_perm.security; |
2642 | } | 2848 | } |
2643 | 2849 | ||
2644 | /** | 2850 | /** |
@@ -2650,14 +2856,17 @@ static char *smack_of_msq(struct msg_queue *msq) | |||
2650 | */ | 2856 | */ |
2651 | static int smk_curacc_msq(struct msg_queue *msq, int access) | 2857 | static int smk_curacc_msq(struct msg_queue *msq, int access) |
2652 | { | 2858 | { |
2653 | char *msp = smack_of_msq(msq); | 2859 | struct smack_known *msp = smack_of_msq(msq); |
2654 | struct smk_audit_info ad; | 2860 | struct smk_audit_info ad; |
2861 | int rc; | ||
2655 | 2862 | ||
2656 | #ifdef CONFIG_AUDIT | 2863 | #ifdef CONFIG_AUDIT |
2657 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); | 2864 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); |
2658 | ad.a.u.ipc_id = msq->q_perm.id; | 2865 | ad.a.u.ipc_id = msq->q_perm.id; |
2659 | #endif | 2866 | #endif |
2660 | return smk_curacc(msp, access, &ad); | 2867 | rc = smk_curacc(msp, access, &ad); |
2868 | rc = smk_bu_current("msq", msp, access, rc); | ||
2869 | return rc; | ||
2661 | } | 2870 | } |
2662 | 2871 | ||
2663 | /** | 2872 | /** |
@@ -2750,15 +2959,18 @@ static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
2750 | */ | 2959 | */ |
2751 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | 2960 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) |
2752 | { | 2961 | { |
2753 | char *isp = ipp->security; | 2962 | struct smack_known *iskp = ipp->security; |
2754 | int may = smack_flags_to_may(flag); | 2963 | int may = smack_flags_to_may(flag); |
2755 | struct smk_audit_info ad; | 2964 | struct smk_audit_info ad; |
2965 | int rc; | ||
2756 | 2966 | ||
2757 | #ifdef CONFIG_AUDIT | 2967 | #ifdef CONFIG_AUDIT |
2758 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); | 2968 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC); |
2759 | ad.a.u.ipc_id = ipp->id; | 2969 | ad.a.u.ipc_id = ipp->id; |
2760 | #endif | 2970 | #endif |
2761 | return smk_curacc(isp, may, &ad); | 2971 | rc = smk_curacc(iskp, may, &ad); |
2972 | rc = smk_bu_current("svipc", iskp, may, rc); | ||
2973 | return rc; | ||
2762 | } | 2974 | } |
2763 | 2975 | ||
2764 | /** | 2976 | /** |
@@ -2768,9 +2980,9 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | |||
2768 | */ | 2980 | */ |
2769 | static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) | 2981 | static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) |
2770 | { | 2982 | { |
2771 | char *smack = ipp->security; | 2983 | struct smack_known *iskp = ipp->security; |
2772 | 2984 | ||
2773 | *secid = smack_to_secid(smack); | 2985 | *secid = iskp->smk_secid; |
2774 | } | 2986 | } |
2775 | 2987 | ||
2776 | /** | 2988 | /** |
@@ -2787,7 +2999,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2787 | struct inode_smack *isp; | 2999 | struct inode_smack *isp; |
2788 | struct smack_known *skp; | 3000 | struct smack_known *skp; |
2789 | struct smack_known *ckp = smk_of_current(); | 3001 | struct smack_known *ckp = smk_of_current(); |
2790 | char *final; | 3002 | struct smack_known *final; |
2791 | char trattr[TRANS_TRUE_SIZE]; | 3003 | char trattr[TRANS_TRUE_SIZE]; |
2792 | int transflag = 0; | 3004 | int transflag = 0; |
2793 | int rc; | 3005 | int rc; |
@@ -2827,8 +3039,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2827 | * so there's no opportunity to set the mount | 3039 | * so there's no opportunity to set the mount |
2828 | * options. | 3040 | * options. |
2829 | */ | 3041 | */ |
2830 | sbsp->smk_root = smack_known_star.smk_known; | 3042 | sbsp->smk_root = &smack_known_star; |
2831 | sbsp->smk_default = smack_known_star.smk_known; | 3043 | sbsp->smk_default = &smack_known_star; |
2832 | } | 3044 | } |
2833 | isp->smk_inode = sbsp->smk_root; | 3045 | isp->smk_inode = sbsp->smk_root; |
2834 | isp->smk_flags |= SMK_INODE_INSTANT; | 3046 | isp->smk_flags |= SMK_INODE_INSTANT; |
@@ -2858,7 +3070,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2858 | * | 3070 | * |
2859 | * Cgroupfs is special | 3071 | * Cgroupfs is special |
2860 | */ | 3072 | */ |
2861 | final = smack_known_star.smk_known; | 3073 | final = &smack_known_star; |
2862 | break; | 3074 | break; |
2863 | case DEVPTS_SUPER_MAGIC: | 3075 | case DEVPTS_SUPER_MAGIC: |
2864 | /* | 3076 | /* |
@@ -2866,7 +3078,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2866 | * Programs that change smack have to treat the | 3078 | * Programs that change smack have to treat the |
2867 | * pty with respect. | 3079 | * pty with respect. |
2868 | */ | 3080 | */ |
2869 | final = ckp->smk_known; | 3081 | final = ckp; |
2870 | break; | 3082 | break; |
2871 | case PROC_SUPER_MAGIC: | 3083 | case PROC_SUPER_MAGIC: |
2872 | /* | 3084 | /* |
@@ -2880,7 +3092,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2880 | * but watch out, because they're volitile, | 3092 | * but watch out, because they're volitile, |
2881 | * getting recreated on every reboot. | 3093 | * getting recreated on every reboot. |
2882 | */ | 3094 | */ |
2883 | final = smack_known_star.smk_known; | 3095 | final = &smack_known_star; |
2884 | /* | 3096 | /* |
2885 | * No break. | 3097 | * No break. |
2886 | * | 3098 | * |
@@ -2899,7 +3111,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2899 | * UNIX domain sockets use lower level socket data. | 3111 | * UNIX domain sockets use lower level socket data. |
2900 | */ | 3112 | */ |
2901 | if (S_ISSOCK(inode->i_mode)) { | 3113 | if (S_ISSOCK(inode->i_mode)) { |
2902 | final = smack_known_star.smk_known; | 3114 | final = &smack_known_star; |
2903 | break; | 3115 | break; |
2904 | } | 3116 | } |
2905 | /* | 3117 | /* |
@@ -2916,7 +3128,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2916 | dp = dget(opt_dentry); | 3128 | dp = dget(opt_dentry); |
2917 | skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); | 3129 | skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
2918 | if (skp != NULL) | 3130 | if (skp != NULL) |
2919 | final = skp->smk_known; | 3131 | final = skp; |
2920 | 3132 | ||
2921 | /* | 3133 | /* |
2922 | * Transmuting directory | 3134 | * Transmuting directory |
@@ -2965,7 +3177,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2965 | } | 3177 | } |
2966 | 3178 | ||
2967 | if (final == NULL) | 3179 | if (final == NULL) |
2968 | isp->smk_inode = ckp->smk_known; | 3180 | isp->smk_inode = ckp; |
2969 | else | 3181 | else |
2970 | isp->smk_inode = final; | 3182 | isp->smk_inode = final; |
2971 | 3183 | ||
@@ -3090,9 +3302,13 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
3090 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 3302 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
3091 | smk_ad_setfield_u_net_sk(&ad, other); | 3303 | smk_ad_setfield_u_net_sk(&ad, other); |
3092 | #endif | 3304 | #endif |
3093 | rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad); | 3305 | rc = smk_access(skp, okp, MAY_WRITE, &ad); |
3094 | if (rc == 0) | 3306 | rc = smk_bu_note("UDS connect", skp, okp, MAY_WRITE, rc); |
3095 | rc = smk_access(okp, okp->smk_known, MAY_WRITE, NULL); | 3307 | if (rc == 0) { |
3308 | rc = smk_access(okp, skp, MAY_WRITE, NULL); | ||
3309 | rc = smk_bu_note("UDS connect", okp, skp, | ||
3310 | MAY_WRITE, rc); | ||
3311 | } | ||
3096 | } | 3312 | } |
3097 | 3313 | ||
3098 | /* | 3314 | /* |
@@ -3118,8 +3334,8 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
3118 | { | 3334 | { |
3119 | struct socket_smack *ssp = sock->sk->sk_security; | 3335 | struct socket_smack *ssp = sock->sk->sk_security; |
3120 | struct socket_smack *osp = other->sk->sk_security; | 3336 | struct socket_smack *osp = other->sk->sk_security; |
3121 | struct smack_known *skp; | ||
3122 | struct smk_audit_info ad; | 3337 | struct smk_audit_info ad; |
3338 | int rc; | ||
3123 | 3339 | ||
3124 | #ifdef CONFIG_AUDIT | 3340 | #ifdef CONFIG_AUDIT |
3125 | struct lsm_network_audit net; | 3341 | struct lsm_network_audit net; |
@@ -3131,8 +3347,9 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
3131 | if (smack_privileged(CAP_MAC_OVERRIDE)) | 3347 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
3132 | return 0; | 3348 | return 0; |
3133 | 3349 | ||
3134 | skp = ssp->smk_out; | 3350 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); |
3135 | return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad); | 3351 | rc = smk_bu_note("UDS send", ssp->smk_out, osp->smk_in, MAY_WRITE, rc); |
3352 | return rc; | ||
3136 | } | 3353 | } |
3137 | 3354 | ||
3138 | /** | 3355 | /** |
@@ -3346,7 +3563,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
3346 | * This is the simplist possible security model | 3563 | * This is the simplist possible security model |
3347 | * for networking. | 3564 | * for networking. |
3348 | */ | 3565 | */ |
3349 | rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); | 3566 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); |
3567 | rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in, | ||
3568 | MAY_WRITE, rc); | ||
3350 | if (rc != 0) | 3569 | if (rc != 0) |
3351 | netlbl_skbuff_err(skb, rc, 0); | 3570 | netlbl_skbuff_err(skb, rc, 0); |
3352 | break; | 3571 | break; |
@@ -3489,7 +3708,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3489 | struct netlbl_lsm_secattr secattr; | 3708 | struct netlbl_lsm_secattr secattr; |
3490 | struct sockaddr_in addr; | 3709 | struct sockaddr_in addr; |
3491 | struct iphdr *hdr; | 3710 | struct iphdr *hdr; |
3492 | char *hsp; | 3711 | struct smack_known *hskp; |
3493 | int rc; | 3712 | int rc; |
3494 | struct smk_audit_info ad; | 3713 | struct smk_audit_info ad; |
3495 | #ifdef CONFIG_AUDIT | 3714 | #ifdef CONFIG_AUDIT |
@@ -3526,7 +3745,8 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3526 | * Receiving a packet requires that the other end be able to write | 3745 | * Receiving a packet requires that the other end be able to write |
3527 | * here. Read access is not required. | 3746 | * here. Read access is not required. |
3528 | */ | 3747 | */ |
3529 | rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); | 3748 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); |
3749 | rc = smk_bu_note("IPv4 connect", skp, ssp->smk_in, MAY_WRITE, rc); | ||
3530 | if (rc != 0) | 3750 | if (rc != 0) |
3531 | return rc; | 3751 | return rc; |
3532 | 3752 | ||
@@ -3544,10 +3764,10 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3544 | hdr = ip_hdr(skb); | 3764 | hdr = ip_hdr(skb); |
3545 | addr.sin_addr.s_addr = hdr->saddr; | 3765 | addr.sin_addr.s_addr = hdr->saddr; |
3546 | rcu_read_lock(); | 3766 | rcu_read_lock(); |
3547 | hsp = smack_host_label(&addr); | 3767 | hskp = smack_host_label(&addr); |
3548 | rcu_read_unlock(); | 3768 | rcu_read_unlock(); |
3549 | 3769 | ||
3550 | if (hsp == NULL) | 3770 | if (hskp == NULL) |
3551 | rc = netlbl_req_setattr(req, &skp->smk_netlabel); | 3771 | rc = netlbl_req_setattr(req, &skp->smk_netlabel); |
3552 | else | 3772 | else |
3553 | netlbl_req_delattr(req); | 3773 | netlbl_req_delattr(req); |
@@ -3599,7 +3819,7 @@ static int smack_key_alloc(struct key *key, const struct cred *cred, | |||
3599 | { | 3819 | { |
3600 | struct smack_known *skp = smk_of_task(cred->security); | 3820 | struct smack_known *skp = smk_of_task(cred->security); |
3601 | 3821 | ||
3602 | key->security = skp->smk_known; | 3822 | key->security = skp; |
3603 | return 0; | 3823 | return 0; |
3604 | } | 3824 | } |
3605 | 3825 | ||
@@ -3630,6 +3850,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
3630 | struct smk_audit_info ad; | 3850 | struct smk_audit_info ad; |
3631 | struct smack_known *tkp = smk_of_task(cred->security); | 3851 | struct smack_known *tkp = smk_of_task(cred->security); |
3632 | int request = 0; | 3852 | int request = 0; |
3853 | int rc; | ||
3633 | 3854 | ||
3634 | keyp = key_ref_to_ptr(key_ref); | 3855 | keyp = key_ref_to_ptr(key_ref); |
3635 | if (keyp == NULL) | 3856 | if (keyp == NULL) |
@@ -3654,7 +3875,9 @@ static int smack_key_permission(key_ref_t key_ref, | |||
3654 | request = MAY_READ; | 3875 | request = MAY_READ; |
3655 | if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR)) | 3876 | if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR)) |
3656 | request = MAY_WRITE; | 3877 | request = MAY_WRITE; |
3657 | return smk_access(tkp, keyp->security, request, &ad); | 3878 | rc = smk_access(tkp, keyp->security, request, &ad); |
3879 | rc = smk_bu_note("key access", tkp, keyp->security, request, rc); | ||
3880 | return rc; | ||
3658 | } | 3881 | } |
3659 | #endif /* CONFIG_KEYS */ | 3882 | #endif /* CONFIG_KEYS */ |
3660 | 3883 | ||
@@ -3685,6 +3908,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
3685 | */ | 3908 | */ |
3686 | static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | 3909 | static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) |
3687 | { | 3910 | { |
3911 | struct smack_known *skp; | ||
3688 | char **rule = (char **)vrule; | 3912 | char **rule = (char **)vrule; |
3689 | *rule = NULL; | 3913 | *rule = NULL; |
3690 | 3914 | ||
@@ -3694,7 +3918,9 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) | |||
3694 | if (op != Audit_equal && op != Audit_not_equal) | 3918 | if (op != Audit_equal && op != Audit_not_equal) |
3695 | return -EINVAL; | 3919 | return -EINVAL; |
3696 | 3920 | ||
3697 | *rule = smk_import(rulestr, 0); | 3921 | skp = smk_import_entry(rulestr, 0); |
3922 | if (skp) | ||
3923 | *rule = skp->smk_known; | ||
3698 | 3924 | ||
3699 | return 0; | 3925 | return 0; |
3700 | } | 3926 | } |
@@ -3813,7 +4039,12 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
3813 | */ | 4039 | */ |
3814 | static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) | 4040 | static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) |
3815 | { | 4041 | { |
3816 | *secid = smack_to_secid(secdata); | 4042 | struct smack_known *skp = smk_find_entry(secdata); |
4043 | |||
4044 | if (skp) | ||
4045 | *secid = skp->smk_secid; | ||
4046 | else | ||
4047 | *secid = 0; | ||
3817 | return 0; | 4048 | return 0; |
3818 | } | 4049 | } |
3819 | 4050 | ||
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 3c720ff10591..bce4e8f1b267 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -131,14 +131,17 @@ LIST_HEAD(smack_rule_list); | |||
131 | 131 | ||
132 | struct smack_parsed_rule { | 132 | struct smack_parsed_rule { |
133 | struct smack_known *smk_subject; | 133 | struct smack_known *smk_subject; |
134 | char *smk_object; | 134 | struct smack_known *smk_object; |
135 | int smk_access1; | 135 | int smk_access1; |
136 | int smk_access2; | 136 | int smk_access2; |
137 | }; | 137 | }; |
138 | 138 | ||
139 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | 139 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
140 | 140 | ||
141 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; | 141 | struct smack_known smack_cipso_option = { |
142 | .smk_known = SMACK_CIPSO_OPTION, | ||
143 | .smk_secid = 0, | ||
144 | }; | ||
142 | 145 | ||
143 | /* | 146 | /* |
144 | * Values for parsing cipso rules | 147 | * Values for parsing cipso rules |
@@ -304,6 +307,10 @@ static int smk_perm_from_str(const char *string) | |||
304 | case 'L': | 307 | case 'L': |
305 | perm |= MAY_LOCK; | 308 | perm |= MAY_LOCK; |
306 | break; | 309 | break; |
310 | case 'b': | ||
311 | case 'B': | ||
312 | perm |= MAY_BRINGUP; | ||
313 | break; | ||
307 | default: | 314 | default: |
308 | return perm; | 315 | return perm; |
309 | } | 316 | } |
@@ -335,7 +342,7 @@ static int smk_fill_rule(const char *subject, const char *object, | |||
335 | if (rule->smk_subject == NULL) | 342 | if (rule->smk_subject == NULL) |
336 | return -EINVAL; | 343 | return -EINVAL; |
337 | 344 | ||
338 | rule->smk_object = smk_import(object, len); | 345 | rule->smk_object = smk_import_entry(object, len); |
339 | if (rule->smk_object == NULL) | 346 | if (rule->smk_object == NULL) |
340 | return -EINVAL; | 347 | return -EINVAL; |
341 | } else { | 348 | } else { |
@@ -355,7 +362,7 @@ static int smk_fill_rule(const char *subject, const char *object, | |||
355 | kfree(cp); | 362 | kfree(cp); |
356 | if (skp == NULL) | 363 | if (skp == NULL) |
357 | return -ENOENT; | 364 | return -ENOENT; |
358 | rule->smk_object = skp->smk_known; | 365 | rule->smk_object = skp; |
359 | } | 366 | } |
360 | 367 | ||
361 | rule->smk_access1 = smk_perm_from_str(access1); | 368 | rule->smk_access1 = smk_perm_from_str(access1); |
@@ -594,13 +601,15 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | |||
594 | * anything you read back. | 601 | * anything you read back. |
595 | */ | 602 | */ |
596 | if (strlen(srp->smk_subject->smk_known) >= max || | 603 | if (strlen(srp->smk_subject->smk_known) >= max || |
597 | strlen(srp->smk_object) >= max) | 604 | strlen(srp->smk_object->smk_known) >= max) |
598 | return; | 605 | return; |
599 | 606 | ||
600 | if (srp->smk_access == 0) | 607 | if (srp->smk_access == 0) |
601 | return; | 608 | return; |
602 | 609 | ||
603 | seq_printf(s, "%s %s", srp->smk_subject->smk_known, srp->smk_object); | 610 | seq_printf(s, "%s %s", |
611 | srp->smk_subject->smk_known, | ||
612 | srp->smk_object->smk_known); | ||
604 | 613 | ||
605 | seq_putc(s, ' '); | 614 | seq_putc(s, ' '); |
606 | 615 | ||
@@ -616,6 +625,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | |||
616 | seq_putc(s, 't'); | 625 | seq_putc(s, 't'); |
617 | if (srp->smk_access & MAY_LOCK) | 626 | if (srp->smk_access & MAY_LOCK) |
618 | seq_putc(s, 'l'); | 627 | seq_putc(s, 'l'); |
628 | if (srp->smk_access & MAY_BRINGUP) | ||
629 | seq_putc(s, 'b'); | ||
619 | 630 | ||
620 | seq_putc(s, '\n'); | 631 | seq_putc(s, '\n'); |
621 | } | 632 | } |
@@ -1067,7 +1078,7 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v) | |||
1067 | for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++); | 1078 | for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++); |
1068 | 1079 | ||
1069 | seq_printf(s, "%u.%u.%u.%u/%d %s\n", | 1080 | seq_printf(s, "%u.%u.%u.%u/%d %s\n", |
1070 | hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label); | 1081 | hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label->smk_known); |
1071 | 1082 | ||
1072 | return 0; | 1083 | return 0; |
1073 | } | 1084 | } |
@@ -1147,10 +1158,10 @@ static void smk_netlbladdr_insert(struct smk_netlbladdr *new) | |||
1147 | static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | 1158 | static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, |
1148 | size_t count, loff_t *ppos) | 1159 | size_t count, loff_t *ppos) |
1149 | { | 1160 | { |
1150 | struct smk_netlbladdr *skp; | 1161 | struct smk_netlbladdr *snp; |
1151 | struct sockaddr_in newname; | 1162 | struct sockaddr_in newname; |
1152 | char *smack; | 1163 | char *smack; |
1153 | char *sp; | 1164 | struct smack_known *skp; |
1154 | char *data; | 1165 | char *data; |
1155 | char *host = (char *)&newname.sin_addr.s_addr; | 1166 | char *host = (char *)&newname.sin_addr.s_addr; |
1156 | int rc; | 1167 | int rc; |
@@ -1213,15 +1224,15 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1213 | * If smack begins with '-', it is an option, don't import it | 1224 | * If smack begins with '-', it is an option, don't import it |
1214 | */ | 1225 | */ |
1215 | if (smack[0] != '-') { | 1226 | if (smack[0] != '-') { |
1216 | sp = smk_import(smack, 0); | 1227 | skp = smk_import_entry(smack, 0); |
1217 | if (sp == NULL) { | 1228 | if (skp == NULL) { |
1218 | rc = -EINVAL; | 1229 | rc = -EINVAL; |
1219 | goto free_out; | 1230 | goto free_out; |
1220 | } | 1231 | } |
1221 | } else { | 1232 | } else { |
1222 | /* check known options */ | 1233 | /* check known options */ |
1223 | if (strcmp(smack, smack_cipso_option) == 0) | 1234 | if (strcmp(smack, smack_cipso_option.smk_known) == 0) |
1224 | sp = (char *)smack_cipso_option; | 1235 | skp = &smack_cipso_option; |
1225 | else { | 1236 | else { |
1226 | rc = -EINVAL; | 1237 | rc = -EINVAL; |
1227 | goto free_out; | 1238 | goto free_out; |
@@ -1244,9 +1255,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1244 | nsa = newname.sin_addr.s_addr; | 1255 | nsa = newname.sin_addr.s_addr; |
1245 | /* try to find if the prefix is already in the list */ | 1256 | /* try to find if the prefix is already in the list */ |
1246 | found = 0; | 1257 | found = 0; |
1247 | list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) { | 1258 | list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list) { |
1248 | if (skp->smk_host.sin_addr.s_addr == nsa && | 1259 | if (snp->smk_host.sin_addr.s_addr == nsa && |
1249 | skp->smk_mask.s_addr == mask.s_addr) { | 1260 | snp->smk_mask.s_addr == mask.s_addr) { |
1250 | found = 1; | 1261 | found = 1; |
1251 | break; | 1262 | break; |
1252 | } | 1263 | } |
@@ -1254,26 +1265,26 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1254 | smk_netlabel_audit_set(&audit_info); | 1265 | smk_netlabel_audit_set(&audit_info); |
1255 | 1266 | ||
1256 | if (found == 0) { | 1267 | if (found == 0) { |
1257 | skp = kzalloc(sizeof(*skp), GFP_KERNEL); | 1268 | snp = kzalloc(sizeof(*snp), GFP_KERNEL); |
1258 | if (skp == NULL) | 1269 | if (snp == NULL) |
1259 | rc = -ENOMEM; | 1270 | rc = -ENOMEM; |
1260 | else { | 1271 | else { |
1261 | rc = 0; | 1272 | rc = 0; |
1262 | skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr; | 1273 | snp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr; |
1263 | skp->smk_mask.s_addr = mask.s_addr; | 1274 | snp->smk_mask.s_addr = mask.s_addr; |
1264 | skp->smk_label = sp; | 1275 | snp->smk_label = skp; |
1265 | smk_netlbladdr_insert(skp); | 1276 | smk_netlbladdr_insert(snp); |
1266 | } | 1277 | } |
1267 | } else { | 1278 | } else { |
1268 | /* we delete the unlabeled entry, only if the previous label | 1279 | /* we delete the unlabeled entry, only if the previous label |
1269 | * wasn't the special CIPSO option */ | 1280 | * wasn't the special CIPSO option */ |
1270 | if (skp->smk_label != smack_cipso_option) | 1281 | if (snp->smk_label != &smack_cipso_option) |
1271 | rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, | 1282 | rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, |
1272 | &skp->smk_host.sin_addr, &skp->smk_mask, | 1283 | &snp->smk_host.sin_addr, &snp->smk_mask, |
1273 | PF_INET, &audit_info); | 1284 | PF_INET, &audit_info); |
1274 | else | 1285 | else |
1275 | rc = 0; | 1286 | rc = 0; |
1276 | skp->smk_label = sp; | 1287 | snp->smk_label = skp; |
1277 | } | 1288 | } |
1278 | 1289 | ||
1279 | /* | 1290 | /* |
@@ -1281,10 +1292,10 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1281 | * this host so that incoming packets get labeled. | 1292 | * this host so that incoming packets get labeled. |
1282 | * but only if we didn't get the special CIPSO option | 1293 | * but only if we didn't get the special CIPSO option |
1283 | */ | 1294 | */ |
1284 | if (rc == 0 && sp != smack_cipso_option) | 1295 | if (rc == 0 && skp != &smack_cipso_option) |
1285 | rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, | 1296 | rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, |
1286 | &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET, | 1297 | &snp->smk_host.sin_addr, &snp->smk_mask, PF_INET, |
1287 | smack_to_secid(skp->smk_label), &audit_info); | 1298 | snp->smk_label->smk_secid, &audit_info); |
1288 | 1299 | ||
1289 | if (rc == 0) | 1300 | if (rc == 0) |
1290 | rc = count; | 1301 | rc = count; |
@@ -1677,7 +1688,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1677 | if (smack_onlycap != NULL && smack_onlycap != skp) | 1688 | if (smack_onlycap != NULL && smack_onlycap != skp) |
1678 | return -EPERM; | 1689 | return -EPERM; |
1679 | 1690 | ||
1680 | data = kzalloc(count, GFP_KERNEL); | 1691 | data = kzalloc(count + 1, GFP_KERNEL); |
1681 | if (data == NULL) | 1692 | if (data == NULL) |
1682 | return -ENOMEM; | 1693 | return -ENOMEM; |
1683 | 1694 | ||
@@ -1880,7 +1891,10 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, | |||
1880 | else if (res != -ENOENT) | 1891 | else if (res != -ENOENT) |
1881 | return -EINVAL; | 1892 | return -EINVAL; |
1882 | 1893 | ||
1883 | data[0] = res == 0 ? '1' : '0'; | 1894 | /* |
1895 | * smk_access() can return a value > 0 in the "bringup" case. | ||
1896 | */ | ||
1897 | data[0] = res >= 0 ? '1' : '0'; | ||
1884 | data[1] = '\0'; | 1898 | data[1] = '\0'; |
1885 | 1899 | ||
1886 | simple_transaction_set(file, 2); | 1900 | simple_transaction_set(file, 2); |
@@ -2228,7 +2242,7 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf, | |||
2228 | if (!smack_privileged(CAP_MAC_ADMIN)) | 2242 | if (!smack_privileged(CAP_MAC_ADMIN)) |
2229 | return -EPERM; | 2243 | return -EPERM; |
2230 | 2244 | ||
2231 | data = kzalloc(count, GFP_KERNEL); | 2245 | data = kzalloc(count + 1, GFP_KERNEL); |
2232 | if (data == NULL) | 2246 | if (data == NULL) |
2233 | return -ENOMEM; | 2247 | return -ENOMEM; |
2234 | 2248 | ||