[PATCH v7 22/28] SELinux: Verify LSM display sanity in binder
Casey Schaufler
casey at schaufler-ca.com
Fri Aug 9 00:56:31 UTC 2019
On 8/8/2019 2:55 PM, Kees Cook wrote:
> On Wed, Aug 07, 2019 at 12:44:04PM -0700, Casey Schaufler wrote:
>> Verify that the tasks on the ends of a binder transaction
>> use LSM display values that don't cause SELinux contexts
>> to be interpreted by another LSM or another LSM's context
>> to be interpreted by SELinux. No judgement is made in cases
>> that where SELinux contexts are not used in the binder
>> transaction.
>>
>> Signed-off-by: Casey Schaufler <casey at schaufler-ca.com>
>> ---
>> security/selinux/hooks.c | 34 ++++++++++++++++++++++++++++++++++
>> 1 file changed, 34 insertions(+)
>>
>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>> index 352be16a887d..fcad2e3432d2 100644
>> --- a/security/selinux/hooks.c
>> +++ b/security/selinux/hooks.c
>> @@ -2009,6 +2009,28 @@ static inline u32 open_file_to_av(struct file *file)
>> return av;
>> }
>>
>> +/*
>> + * Verify that if the "display" LSM is SELinux for either task
>> + * that it is for both tasks.
>> + */
>> +static inline bool compatible_task_displays(struct task_struct *here,
>> + struct task_struct *there)
>> +{
>> + int h = lsm_task_display(here);
>> + int t = lsm_task_display(there);
>> +
>> + if (h == t)
>> + return true;
>> +
>> + /* unspecified is only ok if SELinux isn't going to be involved */
>> + if (selinux_lsmid.slot == 0)
>> + return ((h == 0 && t == LSMBLOB_INVALID) ||
>> + (t == 0 && h == LSMBLOB_INVALID));
> What is "0" here? Doesn't that just mean the first LSM. I though only -1
> had a special meaning (and had a #define name for it).
I try not to write obscure code, but I seem to have done so here.
The lsm in slot 0 (the first registered "display" lsm) will
get used if the display value is LSMBLOB_INVALID. We've already
checked to see if the display values are the same, and they're not.
If selinux is in slot 0, one of the display values is 0 and the
other is LSMBLOB_INVALID, the displays are compatible. Otherwise,
they're not. If selinux is not in slot 0 and either of the displays
slots is selinux's slot, it's not compatible.
Simple, no?
I'll have a go at making the code more obvious or, failing
that, better documented.
>
> -Kees
>
>> +
>> + /* it's ok only if neither display is SELinux */
>> + return (h != selinux_lsmid.slot && t != selinux_lsmid.slot);
>> +}
>> +
>> /* Hook functions begin here. */
>>
>> static int selinux_binder_set_context_mgr(struct task_struct *mgr)
>> @@ -2016,6 +2038,9 @@ static int selinux_binder_set_context_mgr(struct task_struct *mgr)
>> u32 mysid = current_sid();
>> u32 mgrsid = task_sid(mgr);
>>
>> + if (!compatible_task_displays(current, mgr))
>> + return -EINVAL;
>> +
>> return avc_has_perm(&selinux_state,
>> mysid, mgrsid, SECCLASS_BINDER,
>> BINDER__SET_CONTEXT_MGR, NULL);
>> @@ -2029,6 +2054,9 @@ static int selinux_binder_transaction(struct task_struct *from,
>> u32 tosid = task_sid(to);
>> int rc;
>>
>> + if (!compatible_task_displays(from, to))
>> + return -EINVAL;
>> +
>> if (mysid != fromsid) {
>> rc = avc_has_perm(&selinux_state,
>> mysid, fromsid, SECCLASS_BINDER,
>> @@ -2048,6 +2076,9 @@ static int selinux_binder_transfer_binder(struct task_struct *from,
>> u32 fromsid = task_sid(from);
>> u32 tosid = task_sid(to);
>>
>> + if (!compatible_task_displays(from, to))
>> + return -EINVAL;
>> +
>> return avc_has_perm(&selinux_state,
>> fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
>> NULL);
>> @@ -2064,6 +2095,9 @@ static int selinux_binder_transfer_file(struct task_struct *from,
>> struct common_audit_data ad;
>> int rc;
>>
>> + if (!compatible_task_displays(from, to))
>> + return -EINVAL;
>> +
>> ad.type = LSM_AUDIT_DATA_PATH;
>> ad.u.path = file->f_path;
>>
>> --
>> 2.20.1
>>
More information about the Linux-security-module-archive
mailing list