2019-06-01 11:08:55 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2017-01-16 11:42:17 +03:00
/*
* AppArmor security module
*
* This file contains AppArmor security identifier ( secid ) manipulation fns
*
2017-08-01 03:36:45 +03:00
* Copyright 2009 - 2017 Canonical Ltd .
2017-01-16 11:42:17 +03:00
*
2017-08-01 03:36:45 +03:00
* AppArmor allocates a unique secid for every label used . If a label
* is replaced it receives the secid of the label it is replacing .
2017-01-16 11:42:17 +03:00
*/
# include <linux/errno.h>
# include <linux/err.h>
2017-08-01 03:36:45 +03:00
# include <linux/gfp.h>
2018-05-22 12:32:59 +03:00
# include <linux/idr.h>
2017-08-01 03:36:45 +03:00
# include <linux/slab.h>
# include <linux/spinlock.h>
2017-01-16 11:42:17 +03:00
2017-08-01 03:36:45 +03:00
# include "include/cred.h"
# include "include/lib.h"
2017-01-16 11:42:17 +03:00
# include "include/secid.h"
2017-08-01 03:36:45 +03:00
# include "include/label.h"
# include "include/policy_ns.h"
2017-01-16 11:42:17 +03:00
2017-08-01 03:36:45 +03:00
/*
* secids - do not pin labels with a refcount . They rely on the label
* properly updating / freeing them
*/
2018-05-24 23:27:45 +03:00
# define AA_FIRST_SECID 2
2018-06-05 05:44:59 +03:00
2018-05-22 12:32:59 +03:00
static DEFINE_IDR ( aa_secids ) ;
2017-01-16 11:42:17 +03:00
static DEFINE_SPINLOCK ( secid_lock ) ;
2017-08-01 03:36:45 +03:00
/*
* TODO : allow policy to reserve a secid range ?
* TODO : add secid pinning
* TODO : use secid_update in label replace
*/
/**
* aa_secid_update - update a secid mapping to a new label
* @ secid : secid to update
* @ label : label the secid will now map to
*/
void aa_secid_update ( u32 secid , struct aa_label * label )
{
unsigned long flags ;
spin_lock_irqsave ( & secid_lock , flags ) ;
2018-05-22 12:32:59 +03:00
idr_replace ( & aa_secids , label , secid ) ;
2017-08-01 03:36:45 +03:00
spin_unlock_irqrestore ( & secid_lock , flags ) ;
}
/**
*
* see label for inverse aa_label_to_secid
*/
struct aa_label * aa_secid_to_label ( u32 secid )
{
struct aa_label * label ;
rcu_read_lock ( ) ;
2018-05-22 12:32:59 +03:00
label = idr_find ( & aa_secids , secid ) ;
2017-08-01 03:36:45 +03:00
rcu_read_unlock ( ) ;
return label ;
}
int apparmor_secid_to_secctx ( u32 secid , char * * secdata , u32 * seclen )
{
/* TODO: cache secctx and ref count so we don't have to recreate */
struct aa_label * label = aa_secid_to_label ( secid ) ;
apparmor: fix '*seclen' is never less than zero
smatch warnings:
security/apparmor/secid.c:162 apparmor_secid_to_secctx() warn: unsigned '*seclen' is never less than zero.
vim +162 security/apparmor/secid.c
140
141 int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
142 {
143 /* TODO: cache secctx and ref count so we don't have to recreate */
144 struct aa_label *label = aa_secid_to_label(secid);
145
146 AA_BUG(!secdata);
147 AA_BUG(!seclen);
148
149 if (!label)
150 return -EINVAL;
151
152 if (secdata)
153 *seclen = aa_label_asxprint(secdata, root_ns, label,
154 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
155 FLAG_HIDDEN_UNCONFINED |
156 FLAG_ABS_ROOT, GFP_ATOMIC);
157 else
158 *seclen = aa_label_snxprint(NULL, 0, root_ns, label,
159 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
160 FLAG_HIDDEN_UNCONFINED |
161 FLAG_ABS_ROOT);
> 162 if (*seclen < 0)
163 return -ENOMEM;
164
165 return 0;
166 }
167
Fixes: c092921219d2 ("apparmor: add support for mapping secids and using secctxes")
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-05-04 11:57:47 +03:00
int len ;
2017-08-01 03:36:45 +03:00
AA_BUG ( ! seclen ) ;
if ( ! label )
return - EINVAL ;
if ( secdata )
apparmor: fix '*seclen' is never less than zero
smatch warnings:
security/apparmor/secid.c:162 apparmor_secid_to_secctx() warn: unsigned '*seclen' is never less than zero.
vim +162 security/apparmor/secid.c
140
141 int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
142 {
143 /* TODO: cache secctx and ref count so we don't have to recreate */
144 struct aa_label *label = aa_secid_to_label(secid);
145
146 AA_BUG(!secdata);
147 AA_BUG(!seclen);
148
149 if (!label)
150 return -EINVAL;
151
152 if (secdata)
153 *seclen = aa_label_asxprint(secdata, root_ns, label,
154 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
155 FLAG_HIDDEN_UNCONFINED |
156 FLAG_ABS_ROOT, GFP_ATOMIC);
157 else
158 *seclen = aa_label_snxprint(NULL, 0, root_ns, label,
159 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
160 FLAG_HIDDEN_UNCONFINED |
161 FLAG_ABS_ROOT);
> 162 if (*seclen < 0)
163 return -ENOMEM;
164
165 return 0;
166 }
167
Fixes: c092921219d2 ("apparmor: add support for mapping secids and using secctxes")
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-05-04 11:57:47 +03:00
len = aa_label_asxprint ( secdata , root_ns , label ,
FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT ,
GFP_ATOMIC ) ;
2017-08-01 03:36:45 +03:00
else
apparmor: fix '*seclen' is never less than zero
smatch warnings:
security/apparmor/secid.c:162 apparmor_secid_to_secctx() warn: unsigned '*seclen' is never less than zero.
vim +162 security/apparmor/secid.c
140
141 int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
142 {
143 /* TODO: cache secctx and ref count so we don't have to recreate */
144 struct aa_label *label = aa_secid_to_label(secid);
145
146 AA_BUG(!secdata);
147 AA_BUG(!seclen);
148
149 if (!label)
150 return -EINVAL;
151
152 if (secdata)
153 *seclen = aa_label_asxprint(secdata, root_ns, label,
154 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
155 FLAG_HIDDEN_UNCONFINED |
156 FLAG_ABS_ROOT, GFP_ATOMIC);
157 else
158 *seclen = aa_label_snxprint(NULL, 0, root_ns, label,
159 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
160 FLAG_HIDDEN_UNCONFINED |
161 FLAG_ABS_ROOT);
> 162 if (*seclen < 0)
163 return -ENOMEM;
164
165 return 0;
166 }
167
Fixes: c092921219d2 ("apparmor: add support for mapping secids and using secctxes")
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-05-04 11:57:47 +03:00
len = aa_label_snxprint ( NULL , 0 , root_ns , label ,
FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT ) ;
if ( len < 0 )
2017-08-01 03:36:45 +03:00
return - ENOMEM ;
apparmor: fix '*seclen' is never less than zero
smatch warnings:
security/apparmor/secid.c:162 apparmor_secid_to_secctx() warn: unsigned '*seclen' is never less than zero.
vim +162 security/apparmor/secid.c
140
141 int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
142 {
143 /* TODO: cache secctx and ref count so we don't have to recreate */
144 struct aa_label *label = aa_secid_to_label(secid);
145
146 AA_BUG(!secdata);
147 AA_BUG(!seclen);
148
149 if (!label)
150 return -EINVAL;
151
152 if (secdata)
153 *seclen = aa_label_asxprint(secdata, root_ns, label,
154 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
155 FLAG_HIDDEN_UNCONFINED |
156 FLAG_ABS_ROOT, GFP_ATOMIC);
157 else
158 *seclen = aa_label_snxprint(NULL, 0, root_ns, label,
159 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
160 FLAG_HIDDEN_UNCONFINED |
161 FLAG_ABS_ROOT);
> 162 if (*seclen < 0)
163 return -ENOMEM;
164
165 return 0;
166 }
167
Fixes: c092921219d2 ("apparmor: add support for mapping secids and using secctxes")
Signed-off-by: John Johansen <john.johansen@canonical.com>
2018-05-04 11:57:47 +03:00
* seclen = len ;
2017-08-01 03:36:45 +03:00
return 0 ;
}
int apparmor_secctx_to_secid ( const char * secdata , u32 seclen , u32 * secid )
{
struct aa_label * label ;
label = aa_label_strn_parse ( & root_ns - > unconfined - > label , secdata ,
seclen , GFP_KERNEL , false , false ) ;
if ( IS_ERR ( label ) )
return PTR_ERR ( label ) ;
* secid = label - > secid ;
return 0 ;
}
void apparmor_release_secctx ( char * secdata , u32 seclen )
{
kfree ( secdata ) ;
}
2017-01-16 11:42:17 +03:00
/**
* aa_alloc_secid - allocate a new secid for a profile
2018-06-05 05:44:59 +03:00
* @ label : the label to allocate a secid for
* @ gfp : memory allocation flags
*
* Returns : 0 with @ label - > secid initialized
* < 0 returns error with @ label - > secid set to AA_SECID_INVALID
2017-01-16 11:42:17 +03:00
*/
2018-06-05 05:44:59 +03:00
int aa_alloc_secid ( struct aa_label * label , gfp_t gfp )
2017-01-16 11:42:17 +03:00
{
2017-08-01 03:36:45 +03:00
unsigned long flags ;
2018-06-05 05:44:59 +03:00
int ret ;
2017-01-16 11:42:17 +03:00
2018-05-22 12:32:59 +03:00
idr_preload ( gfp ) ;
spin_lock_irqsave ( & secid_lock , flags ) ;
2018-06-05 05:44:59 +03:00
ret = idr_alloc ( & aa_secids , label , AA_FIRST_SECID , 0 , GFP_ATOMIC ) ;
2018-05-22 12:32:59 +03:00
spin_unlock_irqrestore ( & secid_lock , flags ) ;
idr_preload_end ( ) ;
2017-08-01 03:36:45 +03:00
2018-06-05 05:44:59 +03:00
if ( ret < 0 ) {
label - > secid = AA_SECID_INVALID ;
return ret ;
}
AA_BUG ( ret = = AA_SECID_INVALID ) ;
label - > secid = ret ;
return 0 ;
2017-01-16 11:42:17 +03:00
}
/**
* aa_free_secid - free a secid
* @ secid : secid to free
*/
void aa_free_secid ( u32 secid )
{
2017-08-01 03:36:45 +03:00
unsigned long flags ;
spin_lock_irqsave ( & secid_lock , flags ) ;
2018-05-22 12:32:59 +03:00
idr_remove ( & aa_secids , secid ) ;
2017-08-01 03:36:45 +03:00
spin_unlock_irqrestore ( & secid_lock , flags ) ;
2017-01-16 11:42:17 +03:00
}
2018-06-05 05:44:59 +03:00
void aa_secids_init ( void )
{
idr_init_base ( & aa_secids , AA_FIRST_SECID ) ;
}