From 4cf1bc1f10452065a29d576fc5693fc4fab5b919 Mon Sep 17 00:00:00 2001 From: KP Singh Date: Fri, 6 Nov 2020 10:37:40 +0000 Subject: bpf: Implement task local storage Similar to bpf_local_storage for sockets and inodes add local storage for task_struct. The life-cycle of storage is managed with the life-cycle of the task_struct. i.e. the storage is destroyed along with the owning task with a callback to the bpf_task_storage_free from the task_free LSM hook. The BPF LSM allocates an __rcu pointer to the bpf_local_storage in the security blob which are now stackable and can co-exist with other LSMs. The userspace map operations can be done by using a pid fd as a key passed to the lookup, update and delete operations. Signed-off-by: KP Singh Signed-off-by: Alexei Starovoitov Acked-by: Song Liu Acked-by: Martin KaFai Lau Link: https://lore.kernel.org/bpf/20201106103747.2780972-3-kpsingh@chromium.org --- security/bpf/hooks.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'security') diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c index 788667d582ae..e5971fa74fd7 100644 --- a/security/bpf/hooks.c +++ b/security/bpf/hooks.c @@ -12,6 +12,7 @@ static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = { #include #undef LSM_HOOK LSM_HOOK_INIT(inode_free_security, bpf_inode_storage_free), + LSM_HOOK_INIT(task_free, bpf_task_storage_free), }; static int __init bpf_lsm_init(void) @@ -23,6 +24,7 @@ static int __init bpf_lsm_init(void) struct lsm_blob_sizes bpf_lsm_blob_sizes __lsm_ro_after_init = { .lbs_inode = sizeof(struct bpf_storage_blob), + .lbs_task = sizeof(struct bpf_storage_blob), }; DEFINE_LSM(bpf) = { -- cgit v1.2.3 From 8eb621698fd4c49703d512fe437d84ab822bc59e Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 16 Sep 2020 11:12:03 +0100 Subject: keys: Provide the original description to the key preparser Provide the proposed description (add key) or the original description (update/instantiate key) when preparsing a key so that the key type can validate it against the data. This is important for rxrpc server keys as we need to check that they have the right amount of key material present - and it's better to do that when the key is loaded rather than deep in trying to process a response packet. Signed-off-by: David Howells cc: Jarkko Sakkinen cc: keyrings@vger.kernel.org --- security/keys/key.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'security') diff --git a/security/keys/key.c b/security/keys/key.c index e282c6179b21..ebe752b137aa 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -504,6 +504,7 @@ int key_instantiate_and_link(struct key *key, int ret; memset(&prep, 0, sizeof(prep)); + prep.orig_description = key->description; prep.data = data; prep.datalen = datalen; prep.quotalen = key->type->def_datalen; @@ -854,6 +855,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, goto error_put_type; memset(&prep, 0, sizeof(prep)); + prep.orig_description = description; prep.data = payload; prep.datalen = plen; prep.quotalen = index_key.type->def_datalen; -- cgit v1.2.3 From 403319be5de51167cd70ddf594b76c95e6d26844 Mon Sep 17 00:00:00 2001 From: KP Singh Date: Tue, 24 Nov 2020 15:12:08 +0000 Subject: ima: Implement ima_inode_hash This is in preparation to add a helper for BPF LSM programs to use IMA hashes when attached to LSM hooks. There are LSM hooks like inode_unlink which do not have a struct file * argument and cannot use the existing ima_file_hash API. An inode based API is, therefore, useful in LSM based detections like an executable trying to delete itself which rely on the inode_unlink LSM hook. Moreover, the ima_file_hash function does nothing with the struct file pointer apart from calling file_inode on it and converting it to an inode. Signed-off-by: KP Singh Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Acked-by: Mimi Zohar Link: https://lore.kernel.org/bpf/20201124151210.1081188-2-kpsingh@chromium.org --- security/integrity/ima/ima_main.c | 78 +++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 24 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2d1af8899cab..cb2deaa188e7 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -501,37 +501,14 @@ int ima_file_check(struct file *file, int mask) } EXPORT_SYMBOL_GPL(ima_file_check); -/** - * ima_file_hash - return the stored measurement if a file has been hashed and - * is in the iint cache. - * @file: pointer to the file - * @buf: buffer in which to store the hash - * @buf_size: length of the buffer - * - * On success, return the hash algorithm (as defined in the enum hash_algo). - * If buf is not NULL, this function also outputs the hash into buf. - * If the hash is larger than buf_size, then only buf_size bytes will be copied. - * It generally just makes sense to pass a buffer capable of holding the largest - * possible hash: IMA_MAX_DIGEST_SIZE. - * The file hash returned is based on the entire file, including the appended - * signature. - * - * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. - * If the parameters are incorrect, return -EINVAL. - */ -int ima_file_hash(struct file *file, char *buf, size_t buf_size) +static int __ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) { - struct inode *inode; struct integrity_iint_cache *iint; int hash_algo; - if (!file) - return -EINVAL; - if (!ima_policy_flag) return -EOPNOTSUPP; - inode = file_inode(file); iint = integrity_iint_find(inode); if (!iint) return -EOPNOTSUPP; @@ -558,8 +535,61 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size) return hash_algo; } + +/** + * ima_file_hash - return the stored measurement if a file has been hashed and + * is in the iint cache. + * @file: pointer to the file + * @buf: buffer in which to store the hash + * @buf_size: length of the buffer + * + * On success, return the hash algorithm (as defined in the enum hash_algo). + * If buf is not NULL, this function also outputs the hash into buf. + * If the hash is larger than buf_size, then only buf_size bytes will be copied. + * It generally just makes sense to pass a buffer capable of holding the largest + * possible hash: IMA_MAX_DIGEST_SIZE. + * The file hash returned is based on the entire file, including the appended + * signature. + * + * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. + * If the parameters are incorrect, return -EINVAL. + */ +int ima_file_hash(struct file *file, char *buf, size_t buf_size) +{ + if (!file) + return -EINVAL; + + return __ima_inode_hash(file_inode(file), buf, buf_size); +} EXPORT_SYMBOL_GPL(ima_file_hash); +/** + * ima_inode_hash - return the stored measurement if the inode has been hashed + * and is in the iint cache. + * @inode: pointer to the inode + * @buf: buffer in which to store the hash + * @buf_size: length of the buffer + * + * On success, return the hash algorithm (as defined in the enum hash_algo). + * If buf is not NULL, this function also outputs the hash into buf. + * If the hash is larger than buf_size, then only buf_size bytes will be copied. + * It generally just makes sense to pass a buffer capable of holding the largest + * possible hash: IMA_MAX_DIGEST_SIZE. + * The hash returned is based on the entire contents, including the appended + * signature. + * + * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. + * If the parameters are incorrect, return -EINVAL. + */ +int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) +{ + if (!inode) + return -EINVAL; + + return __ima_inode_hash(inode, buf, buf_size); +} +EXPORT_SYMBOL_GPL(ima_inode_hash); + /** * ima_post_create_tmpfile - mark newly created tmpfile as new * @file : newly created tmpfile -- cgit v1.2.3 From c7a5899eb26e2a4d516d53f65b6dd67be2228041 Mon Sep 17 00:00:00 2001 From: Antony Antony Date: Tue, 17 Nov 2020 17:47:23 +0100 Subject: xfrm: redact SA secret with lockdown confidentiality redact XFRM SA secret in the netlink response to xfrm_get_sa() or dumpall sa. Enable lockdown, confidentiality mode, at boot or at run time. e.g. when enabled: cat /sys/kernel/security/lockdown none integrity [confidentiality] ip xfrm state src 172.16.1.200 dst 172.16.1.100 proto esp spi 0x00000002 reqid 2 mode tunnel replay-window 0 aead rfc4106(gcm(aes)) 0x0000000000000000000000000000000000000000 96 note: the aead secret is redacted. Redacting secret is also a FIPS 140-2 requirement. v1->v2 - add size checks before memset calls v2->v3 - replace spaces with tabs for consistency v3->v4 - use kernel lockdown instead of a /proc setting v4->v5 - remove kconfig option Reviewed-by: Stephan Mueller Signed-off-by: Antony Antony Signed-off-by: Steffen Klassert --- security/security.c | 1 + 1 file changed, 1 insertion(+) (limited to 'security') diff --git a/security/security.c b/security/security.c index a28045dc9e7f..abff77c1c8a7 100644 --- a/security/security.c +++ b/security/security.c @@ -65,6 +65,7 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = { [LOCKDOWN_PERF] = "unsafe use of perf", [LOCKDOWN_TRACEFS] = "use of tracefs", [LOCKDOWN_XMON_RW] = "xmon read and write access", + [LOCKDOWN_XFRM_SECRET] = "xfrm SA secret", [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality", }; -- cgit v1.2.3 From 41dd9596d6b239a125c3d19f9d0ca90bdbfbf876 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 30 Nov 2020 16:36:29 +0100 Subject: security: add const qualifier to struct sock in various places A followup change to tcp_request_sock_op would have to drop the 'const' qualifier from the 'route_req' function as the 'security_inet_conn_request' call is moved there - and that function expects a 'struct sock *'. However, it turns out its also possible to add a const qualifier to security_inet_conn_request instead. Signed-off-by: Florian Westphal Acked-by: James Morris Signed-off-by: Jakub Kicinski --- security/apparmor/include/net.h | 2 +- security/apparmor/lsm.c | 2 +- security/apparmor/net.c | 6 +++--- security/lsm_audit.c | 4 ++-- security/security.c | 2 +- security/selinux/hooks.c | 2 +- security/smack/smack_lsm.c | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) (limited to 'security') diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h index 2431c011800d..aadb4b29fb66 100644 --- a/security/apparmor/include/net.h +++ b/security/apparmor/include/net.h @@ -107,6 +107,6 @@ int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, struct socket *sock); int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, - u32 secid, struct sock *sk); + u32 secid, const struct sock *sk); #endif /* __AA_NET_H */ diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index ffeaee5ed968..1b0aba8eb723 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1147,7 +1147,7 @@ static void apparmor_sock_graft(struct sock *sk, struct socket *parent) } #ifdef CONFIG_NETWORK_SECMARK -static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb, +static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { struct aa_sk_ctx *ctx = SK_CTX(sk); diff --git a/security/apparmor/net.c b/security/apparmor/net.c index fa0e85568450..e0c1b50d6edd 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -211,7 +211,7 @@ static int apparmor_secmark_init(struct aa_secmark *secmark) } static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, - struct common_audit_data *sa, struct sock *sk) + struct common_audit_data *sa) { int i, ret; struct aa_perms perms = { }; @@ -244,13 +244,13 @@ static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, } int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, - u32 secid, struct sock *sk) + u32 secid, const struct sock *sk) { struct aa_profile *profile; DEFINE_AUDIT_SK(sa, op, sk); return fn_for_each_confined(label, profile, aa_secmark_perm(profile, request, secid, - &sa, sk)); + &sa)); } #endif diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 53d0d183db8f..078f9cdcd7f5 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -183,7 +183,7 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb, static inline void print_ipv6_addr(struct audit_buffer *ab, - struct in6_addr *addr, __be16 port, + const struct in6_addr *addr, __be16 port, char *name1, char *name2) { if (!ipv6_addr_any(addr)) @@ -322,7 +322,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, } case LSM_AUDIT_DATA_NET: if (a->u.net->sk) { - struct sock *sk = a->u.net->sk; + const struct sock *sk = a->u.net->sk; struct unix_sock *u; struct unix_address *addr; int len = 0; diff --git a/security/security.c b/security/security.c index a28045dc9e7f..6509f95d203f 100644 --- a/security/security.c +++ b/security/security.c @@ -2225,7 +2225,7 @@ void security_sock_graft(struct sock *sk, struct socket *parent) } EXPORT_SYMBOL(security_sock_graft); -int security_inet_conn_request(struct sock *sk, +int security_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { return call_int_hook(inet_conn_request, 0, sk, skb, req); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6b1826fc3658..6fa593006802 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5355,7 +5355,7 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk, selinux_netlbl_sctp_sk_clone(sk, newsk); } -static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, +static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { struct sk_security_struct *sksec = sk->sk_security; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 5c90b9fa4d40..3a62d6aa74a6 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3864,7 +3864,7 @@ static inline struct smack_known *smack_from_skb(struct sk_buff *skb) * * Returns smack_known of the IP options or NULL if that won't work. */ -static struct smack_known *smack_from_netlbl(struct sock *sk, u16 family, +static struct smack_known *smack_from_netlbl(const struct sock *sk, u16 family, struct sk_buff *skb) { struct netlbl_lsm_secattr secattr; @@ -4114,7 +4114,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) * Returns 0 if a task with the packet label could write to * the socket, otherwise an error code */ -static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, +static int smack_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { u16 family = sk->sk_family; -- cgit v1.2.3