SMACK LSM checks wrong object label during ingress network traffic

Casey Schaufler casey at schaufler-ca.com
Wed Aug 31 14:38:32 UTC 2022


On 8/31/2022 5:13 AM, Lontke, Michael wrote:
> On Tue, 2022-08-30 at 07:06 -0700, Casey Schaufler wrote:
>> On 8/30/2022 2:30 AM, Lontke, Michael wrote:
>>> On Fri, 2022-08-26 at 09:15 -0700, Casey Schaufler wrote:
>>>> On 8/26/2022 1:40 AM, Lontke, Michael wrote:
>>>>> On Thu, 2022-08-25 at 08:59 -0700, Casey Schaufler wrote:
>>>>>> On 8/25/2022 2:25 AM, Lontke, Michael wrote:
>>>>>>> Hello Mr. Schaufler,
>>>>>>>
>>>>>>> we observed the following behavior of the SMACK LSM kernel
>>>>>>> feature.
>>>>>>>
>>>>>>> PROBLEM: SMACK LSM is checking the wrong label when
>>>>>>> receiving
>>>>>>> network
>>>>>>> packets during high system load.
>>>>>>>
>>>>>>> Full Descrpition of the Problem: During a test scenario
>>>>>>> involving
>>>>>>> high
>>>>>>> system load (cpu, memory and io) in combination with
>>>>>>> ingress
>>>>>>> tcp
>>>>>>> network traffic, SMACK is checking wrong object labels
>>>>>>> leading
>>>>>>> to
>>>>>>> denied access for valid scenarios.
>>>>>>> In below test scenario the label 'stresstest' is only used
>>>>>>> for
>>>>>>> the
>>>>>>> application 'stress' but appears in SMACK audit logs as
>>>>>>> object
>>>>>>> together
>>>>>>> with netlabels.
>>>>>>>
>>>>>>> This issue initially appeared on hardware with kernel
>>>>>>> version
>>>>>>> 4.14.237
>>>>>>> but was also being reproduced with qemu for kernel version
>>>>>>> 4.14.290
>>>>>>> and
>>>>>>> latest 6.0-rc2. The used rootfs was generated via buildroot
>>>>>>> version
>>>>>>> 2022.08-rc1.
>>>>>>>
>>>>>>>
>>>>>>> KEYWORDS: smack, networking
>>>>>>>
>>>>>>> KERNEL INFORMATION: Linux stable kernel
>>>>>>>
>>>>>>> KERNEL VERSION: 4.14.237, 4.14.290, 6.0-rc2
>>>>>>>
>>>>>>>
>>>>>>> KERNEL CONFIG: smack related kernel configuration
>>>>>>>
>>>>>>> CONFIG_NETLABEL=y
>>>>>>>
>>>>>>> CONFIG_SECURITY_NETWORK=y
>>>>>>>
>>>>>>> CONFIG_SECURITY_SMACK=y
>>>>>>>
>>>>>>> CONFIG_DEFAULT_SECURITY_SMACK=y
>>>>>>>
>>>>>>> CONFIG_DEFAULT_SECURITY="smack"
>>>>>> What is the value for CONFIG_SECURITY_SMACK_NETFILTER ?
>>>>> # CONFIG_NETWORK_SECMARK is not set
>>>>> therefore CONFIG_SECURITY_SMACK_NETFILTER is not set as well.
>>>>>
>>>>>> The implementation for IPv6 is much more robust for the
>>>>>> netfilter enabled path.
>>>>> You are stating that
>>>>>
>>>>> CONFIG_NETWORK_SECMARK=y
>>>>> CONFIG_SECURITY_SMACK_NETFILTER=y
>>>>>
>>>>> and therefore using SMACK_IPV6_SECMARK_LABELING instead of
>>>>> SMACK_IPV6_PORT_LABELING path in kernel code is more reliable?
>>>> Yes. The netfilter version is used in all known commercial
>>>> deployments
>>>> of Smack, and hence has gotten more attention. The port labeling
>>>> code
>>>> is a "clever hack". I hope to replace it with CALIPSO now that
>>>> CALIPSO
>>>> is supported by newlabel.
>>>>
>>> Today I tested with your suggested configuration (secmark +
>>> netfilter).
>>> Executing the same test case I run into almost the same issue:
>>>
>>> [  288.200206] audit: type=1400 audit(1661844069.376:742):
>>> lsm=SMACK
>>> fn=smack_socket_sock_rcv_skb action=denied subject="net_host"
>>> object="stresstest" requested=w pid=185 comm="stress" saddr=<host-
>>> ipv6-
>>> addr> src=49812 daddr=<qemu-ipv6-addr> dest=42511 netif=ens3
>>>
>>> Instead of defining the netlabel via /sys/fs/smackfs/ip6hosts I
>>> added a
>>> nehosttfilter rule to mark the package with secmark:
>> The netfilter rule is unnecessary if you set the host label. Smack
>> will
>> set the secmark based on the host label. The approach you've use
>> should
>> work just fine. Seeing that the problem occurs in both cases will
>> help
>> narrow down the possibilities. With the configuration and cases you
>> provided I am able to reproduce the problem reliably. I am working on
>> tracking down what I think is a lack of locking issue. Any more
>> information
>> you can provide could be most helpful.
> I added some debug output and stack dumps:
>
> [   48.056297] SMACK DEBUG: smack_sk_alloc_security:2321 -
> sk=ffff8feb1cc3a200 - smk_in=stresstest smk_out=stresstest
> skp=ffff8feb1cc51000
> [   48.056792] CPU: 0 PID: 1544 Comm: stress Not tainted 4.14.0+ #9
> [   48.057085] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
> BIOS 1.10.2-1ubuntu1 04/01/2014
> [   48.057463] Call Trace:
> [   48.057600]  <IRQ>
> [   48.057741]  dump_stack+0x4d/0x71
> [   48.057936]  smack_sk_alloc_security+0x109/0x110
> [   48.058165]  security_sk_alloc+0x3e/0x60
> [   48.058364]  sk_prot_alloc+0x53/0x130
> [   48.058553]  sk_clone_lock+0x19/0x3d0
> [   48.058737]  inet_csk_clone_lock+0x11/0xe0
> [   48.058953]  tcp_create_openreq_child+0x1e/0x420
> [   48.059172]  tcp_v6_syn_recv_sock+0x91/0x710
> [   48.059380]  tcp_check_req+0x3b2/0x510
> [   48.059558]  ? tcp_v6_inbound_md5_hash+0x54/0x1c0
> [   48.059782]  tcp_v6_rcv+0x4c1/0x950
> [   48.059954]  ? ip6table_mangle_hook+0x41/0x120
> [   48.060172]  ip6_input_finish+0xb9/0x420
> [   48.060374]  ip6_input+0x2b/0x90
> [   48.060535]  ? ip6_rcv_finish+0xa0/0xa0
> [   48.060718]  ip6_rcv_finish+0x41/0xa0
> [   48.060892]  ipv6_rcv+0x31d/0x520
> [   48.061053]  ? ip6_make_skb+0x1b0/0x1b0
> [   48.061240]  __netif_receive_skb_core+0x33a/0xa90
> [   48.061490]  ? ipv6_gro_receive+0x1b5/0x350
> [   48.061687]  __netif_receive_skb+0x13/0x60
> [   48.061895]  ? __netif_receive_skb+0x13/0x60
> [   48.062089]  netif_receive_skb_internal+0x23/0xb0
> [   48.062305]  napi_gro_receive+0xbd/0xe0
> [   48.062485]  e1000_clean_rx_irq+0x1c9/0x4e0
> [   48.062686]  e1000_clean+0x260/0x860
> [   48.062860]  net_rx_action+0x11b/0x350
> [   48.063031]  ? e1000_intr+0x78/0xf0
> [   48.063202]  __do_softirq+0xcf/0x2a8
> [   48.063376]  irq_exit+0xab/0xb0
> [   48.063528]  do_IRQ+0x7b/0xc0
> [   48.063679]  common_interrupt+0x90/0x90
> [   48.063854]  </IRQ>
> [   48.063977] RIP: 0033:0x56307cef0baf
> [   48.064135] RSP: 002b:00007ffcd9734540 EFLAGS: 00000206 ORIG_RAX:
> ffffffffffffffc4
> [   48.064466] RAX: 0000000037581fac RBX: 0000000000003a98 RCX:
> 0000000037581fac
> [   48.064765] RDX: 000000003b388e7d RSI: 00007ffcd973451c RDI:
> 00007f2023c62680
> [   48.065033] RBP: 0000000000000003 R08: 0000000000000000 R09:
> 00007f2023c62024
> [   48.065326] R10: 0000000000000000 R11: 0000000000000246 R12:
> 0000000000000000
> [   48.065625] R13: 0000000000000003 R14: 0000000000000001 R15:
> 000056307cef2004
> [   48.066462] SMACK DEBUG: smack_socket_sock_rcv_skb:4057 -
> sk=ffff8feb1cc3a200 smk_in=stresstest rc=-13
> [   48.066852] CPU: 0 PID: 1544 Comm: stress Not tainted 4.14.0+ #9
> [   48.067142] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
> BIOS 1.10.2-1ubuntu1 04/01/2014
> [   48.067507] Call Trace:
> [   48.067620]  <IRQ>
> [   48.067738]  dump_stack+0x4d/0x71
> [   48.067898]  smack_socket_sock_rcv_skb+0x269/0x270
> [   48.068109]  ? default_wake_function+0xd/0x10
> [   48.068301]  ? pollwake+0x61/0x70
> [   48.068464]  ? wake_up_q+0x70/0x70
> [   48.068621]  ? __wake_up_common+0x68/0x120
> [   48.068806]  security_sock_rcv_skb+0x36/0x50
> [   48.068987]  sk_filter_trim_cap+0x2c/0x150
> [   48.069156]  ? tcp_v6_inbound_md5_hash+0x54/0x1c0
> [   48.069356]  tcp_filter+0x26/0x40
> [   48.069510]  tcp_v6_rcv+0x805/0x950
> [   48.069663]  ? ip6table_mangle_hook+0x41/0x120
> [   48.069856]  ip6_input_finish+0xb9/0x420
> [   48.070029]  ip6_input+0x2b/0x90
> [   48.070174]  ? ip6_rcv_finish+0xa0/0xa0
> [   48.070337]  ip6_rcv_finish+0x9a/0xa0
> [   48.070498]  ipv6_rcv+0x31d/0x520
> [   48.070651]  ? ip6_make_skb+0x1b0/0x1b0
> [   48.070832]  __netif_receive_skb_core+0x33a/0xa90
> [   48.071028]  ? ipv6_gro_receive+0x1b5/0x350
> [   48.071214]  __netif_receive_skb+0x13/0x60
> [   48.071396]  ? __netif_receive_skb+0x13/0x60
> [   48.071595]  netif_receive_skb_internal+0x23/0xb0
> [   48.071808]  napi_gro_receive+0xbd/0xe0
> [   48.072001]  e1000_clean_rx_irq+0x1c9/0x4e0
> [   48.072197]  e1000_clean+0x260/0x860
> [   48.072376]  net_rx_action+0x11b/0x350
> [   48.072542]  ? e1000_intr+0x78/0xf0
> [   48.072709]  __do_softirq+0xcf/0x2a8
> [   48.072881]  irq_exit+0xab/0xb0
> [   48.073041]  do_IRQ+0x7b/0xc0
> [   48.073232]  common_interrupt+0x90/0x90
> [   48.073433]  </IRQ>
> [   48.073544] RIP: 0033:0x56307cef0baf
> [   48.073697] RSP: 002b:00007ffcd9734540 EFLAGS: 00000206 ORIG_RAX:
> ffffffffffffffc4
> [   48.074007] RAX: 0000000037581fac RBX: 0000000000003a98 RCX:
> 0000000037581fac
> [   48.074297] RDX: 000000003b388e7d RSI: 00007ffcd973451c RDI:
> 00007f2023c62680
> [   48.074580] RBP: 0000000000000003 R08: 0000000000000000 R09:
> 00007f2023c62024
> [   48.074875] R10: 0000000000000000 R11: 0000000000000246 R12:
> 0000000000000000
> [   48.075157] R13: 0000000000000003 R14: 0000000000000001 R15:
> 000056307cef2004
> [   48.075903] SMACK DEBUG: smack_sock_graft:4185 - sk=ffff8feb1cc3a200
> - before smk_in=stresstest smk_out=stresstest
> [   48.076643] CPU: 0 PID: 1634 Comm: socat Not tainted 4.14.0+ #9
> [   48.076892] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
> BIOS 1.10.2-1ubuntu1 04/01/2014
> [   48.077329] Call Trace:
> [   48.077485]  dump_stack+0x4d/0x71
> [   48.077654]  smack_sock_graft+0xe9/0xf0
> [   48.077834]  security_sock_graft+0x28/0x40
> [   48.078024]  inet_accept+0xa8/0x140
> [   48.078198]  SYSC_accept4+0xe8/0x1e0
> [   48.078372]  ? __audit_syscall_entry+0xba/0x100
> [   48.078580]  ? syscall_trace_enter+0x1c3/0x2b0
> [   48.078781]  SyS_accept+0xb/0x10
> [   48.078933]  do_syscall_64+0x4e/0x100
> [   48.079105]  entry_SYSCALL64_slow_path+0x25/0x25
> [   48.079314] RIP: 0033:0x7f8d116b85ea
> [   48.079465] RSP: 002b:00007fff87c2ef28 EFLAGS: 00000246 ORIG_RAX:
> 000000000000002b
> [   48.079778] RAX: ffffffffffffffda RBX: 00007fff87c2f160 RCX:
> 00007f8d116b85ea
> [   48.080063] RDX: 00007fff87c2f134 RSI: 00007fff87c2f160 RDI:
> 0000000000000005
> [   48.080363] RBP: 00007fff87c2f134 R08: 00007fff87c2f134 R09:
> 0000000000000000
> [   48.080648] R10: 0000000000000040 R11: 0000000000000246 R12:
> 0000000000000005
> [   48.080903] R13: 00000000ffffffff R14: 00007fff87c2f160 R15:
> 00007fff87c2f1e0
> [   48.081236] SMACK DEBUG: smack_sock_graft:4193 - sk=ffff8feb1cc3a200
> - after smk_in=tcp_test smk_out=tcp_test
>
>
> It looks like the socket is already initialized with the wrong security
> context. It is later corrected by smack_sock_graft, but tool late since
> it is called during accept.
>
> We looked into smack_sk_alloc_security and thought this line could be
> the issue:
>
> struct smack_known *skp = smk_of_current();
>
> Looking at how selinux solved it, we saw it initializes with a blank
> security context and later copys the correct context within
> security_sk_clone LSM hook.
> At least with this patch we don't see our issue anymore:

I will run the patch through my tests, but it looks reasonable.
Assuming it passes, and I expect it will, I'll add it to the Smack
next branch. May I add your "Signed-off-by:" ? Also, let me know
if anyone wants to add a "Reported-by:". Thank you for tracking this
down and contributing to Smack.

>
> From: Lontke Michael <michael.lontke at elektrobit.com>
> Date: Wed, 31 Aug 2022 14:03:26 +0200
> Subject: [PATCH] SMACK: Add sk_clone_security LSM hook
>
> Using smk_of_current() during sk_alloc_security hook leads in rare
> cases
> to a faulty initialization of the security context of the created
> socket.
>
> By adding the LSM hook sk_clone_security to SMACK this initialization
> fault is corrected by copying the security context of the old socket
> pointer to the newly cloned one.
> ---
>  security/smack/smack_lsm.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 286171a16ed2..8eb47396376f 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -2348,6 +2348,21 @@ static void smack_sk_free_security(struct sock
> *sk)
>  	kfree(sk->sk_security);
>  }
>  
> +/**
> + * smack_sk_clone_security - Copy security context
> + * @sk: the old socket
> + * @newsk: the new socket
> + *
> + * Copy the security context of the old socket pointer to the cloned
> + */
> +static void smack_sk_clone_security(const struct sock *sk, struct sock
> *newsk)
> +{
> +	struct socket_smack *ssp_old = sk->sk_security;
> +	struct socket_smack *ssp_new = newsk->sk_security;
> +
> +	*ssp_new = *ssp_old;
> +}
> +
>  /**
>  * smack_ipv4host_label - check host based restrictions
>  * @sip: the object end
> @@ -4710,6 +4725,7 @@ static struct security_hook_list smack_hooks[]
> __lsm_ro_after_init = {
>  	LSM_HOOK_INIT(socket_getpeersec_dgram,
> smack_socket_getpeersec_dgram),
>  	LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
>  	LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
> +	LSM_HOOK_INIT(sk_clone_security, smack_sk_clone_security),
>  	LSM_HOOK_INIT(sock_graft, smack_sock_graft),
>  	LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
>  	LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),



More information about the Linux-security-module-archive mailing list