2019-06-01 10:08:55 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2017-01-16 00:42:17 -08:00
/*
* AppArmor security module
*
* This file contains AppArmor security identifier ( secid ) manipulation fns
*
2017-07-31 17:36:45 -07:00
* Copyright 2009 - 2017 Canonical Ltd .
2017-01-16 00:42:17 -08:00
*
2017-07-31 17:36:45 -07: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 00:42:17 -08:00
*/
# include <linux/errno.h>
# include <linux/err.h>
2017-07-31 17:36:45 -07:00
# include <linux/gfp.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
2022-06-06 21:23:22 +01:00
# include <linux/xarray.h>
2017-01-16 00:42:17 -08:00
2017-07-31 17:36:45 -07:00
# include "include/cred.h"
# include "include/lib.h"
2017-01-16 00:42:17 -08:00
# include "include/secid.h"
2017-07-31 17:36:45 -07:00
# include "include/label.h"
# include "include/policy_ns.h"
2017-01-16 00:42:17 -08:00
2017-07-31 17:36:45 -07:00
/*
* secids - do not pin labels with a refcount . They rely on the label
* properly updating / freeing them
*/
2018-05-24 13:27:45 -07:00
# define AA_FIRST_SECID 2
2018-06-04 19:44:59 -07:00
2022-06-06 21:23:22 +01:00
static DEFINE_XARRAY_FLAGS ( aa_secids , XA_FLAGS_LOCK_IRQ | XA_FLAGS_TRACK_FREE ) ;
2017-07-31 17:36:45 -07:00
2020-10-06 14:43:16 -07:00
int apparmor_display_secid_mode ;
2017-07-31 17:36:45 -07: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 ;
2022-06-06 21:23:22 +01:00
xa_lock_irqsave ( & aa_secids , flags ) ;
__xa_store ( & aa_secids , secid , label , 0 ) ;
xa_unlock_irqrestore ( & aa_secids , flags ) ;
2017-07-31 17:36:45 -07:00
}
/**
*
* see label for inverse aa_label_to_secid
*/
struct aa_label * aa_secid_to_label ( u32 secid )
{
2022-06-06 21:23:22 +01:00
return xa_load ( & aa_secids , secid ) ;
2017-07-31 17:36:45 -07:00
}
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 ) ;
2020-10-06 14:43:16 -07:00
int flags = FLAG_VIEW_SUBNS | FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT ;
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 01:57:47 -07:00
int len ;
2017-07-31 17:36:45 -07:00
AA_BUG ( ! seclen ) ;
if ( ! label )
return - EINVAL ;
2020-10-06 14:43:16 -07:00
if ( apparmor_display_secid_mode )
flags | = FLAG_SHOW_MODE ;
2017-07-31 17:36:45 -07:00
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 01:57:47 -07:00
len = aa_label_asxprint ( secdata , root_ns , label ,
2020-10-06 14:43:16 -07:00
flags , GFP_ATOMIC ) ;
2017-07-31 17:36:45 -07:00
else
2020-10-06 14:43:16 -07:00
len = aa_label_snxprint ( NULL , 0 , root_ns , label , flags ) ;
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 01:57:47 -07:00
if ( len < 0 )
2017-07-31 17:36:45 -07: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 01:57:47 -07:00
* seclen = len ;
2017-07-31 17:36:45 -07: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 00:42:17 -08:00
/**
* aa_alloc_secid - allocate a new secid for a profile
2018-06-04 19:44:59 -07: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 00:42:17 -08:00
*/
2018-06-04 19:44:59 -07:00
int aa_alloc_secid ( struct aa_label * label , gfp_t gfp )
2017-01-16 00:42:17 -08:00
{
2017-07-31 17:36:45 -07:00
unsigned long flags ;
2018-06-04 19:44:59 -07:00
int ret ;
2017-01-16 00:42:17 -08:00
2022-06-06 21:23:22 +01:00
xa_lock_irqsave ( & aa_secids , flags ) ;
ret = __xa_alloc ( & aa_secids , & label - > secid , label ,
XA_LIMIT ( AA_FIRST_SECID , INT_MAX ) , gfp ) ;
xa_unlock_irqrestore ( & aa_secids , flags ) ;
2017-07-31 17:36:45 -07:00
2018-06-04 19:44:59 -07:00
if ( ret < 0 ) {
label - > secid = AA_SECID_INVALID ;
return ret ;
}
return 0 ;
2017-01-16 00:42:17 -08:00
}
/**
* aa_free_secid - free a secid
* @ secid : secid to free
*/
void aa_free_secid ( u32 secid )
{
2017-07-31 17:36:45 -07:00
unsigned long flags ;
2022-06-06 21:23:22 +01:00
xa_lock_irqsave ( & aa_secids , flags ) ;
__xa_erase ( & aa_secids , secid ) ;
xa_unlock_irqrestore ( & aa_secids , flags ) ;
2018-06-04 19:44:59 -07:00
}