Skip to content

Commit afb1cbe

Browse files
cschauflerkees
authored andcommitted
LSM: Infrastructure management of the inode security
Move management of the inode->i_security blob out of the individual security modules and into the security infrastructure. Instead of allocating the blobs from within the modules the modules tell the infrastructure how much space is required, and the space is allocated there. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Reviewed-by: Kees Cook <keescook@chromium.org> [kees: adjusted for ordered init series] Signed-off-by: Kees Cook <keescook@chromium.org>
1 parent fb4021b commit afb1cbe

File tree

6 files changed

+93
-98
lines changed

6 files changed

+93
-98
lines changed

include/linux/lsm_hooks.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2033,6 +2033,7 @@ struct security_hook_list {
20332033
struct lsm_blob_sizes {
20342034
int lbs_cred;
20352035
int lbs_file;
2036+
int lbs_inode;
20362037
};
20372038

20382039
/*
@@ -2104,6 +2105,8 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
21042105
#define __lsm_ro_after_init __ro_after_init
21052106
#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
21062107

2108+
extern int lsm_inode_alloc(struct inode *inode);
2109+
21072110
#ifdef CONFIG_SECURITY
21082111
void __init lsm_early_cred(struct cred *cred);
21092112
#endif

security/security.c

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct security_hook_heads security_hook_heads __lsm_ro_after_init;
4141
static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
4242

4343
static struct kmem_cache *lsm_file_cache;
44+
static struct kmem_cache *lsm_inode_cache;
4445

4546
char *lsm_names;
4647
static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
@@ -161,6 +162,13 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
161162

162163
lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred);
163164
lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file);
165+
/*
166+
* The inode blob gets an rcu_head in addition to
167+
* what the modules might need.
168+
*/
169+
if (needed->lbs_inode && blob_sizes.lbs_inode == 0)
170+
blob_sizes.lbs_inode = sizeof(struct rcu_head);
171+
lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
164172
}
165173

166174
/* Prepare LSM for initialization. */
@@ -283,6 +291,7 @@ static void __init ordered_lsm_init(void)
283291

284292
init_debug("cred blob size = %d\n", blob_sizes.lbs_cred);
285293
init_debug("file blob size = %d\n", blob_sizes.lbs_file);
294+
init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
286295

287296
/*
288297
* Create any kmem_caches needed for blobs
@@ -291,6 +300,10 @@ static void __init ordered_lsm_init(void)
291300
lsm_file_cache = kmem_cache_create("lsm_file_cache",
292301
blob_sizes.lbs_file, 0,
293302
SLAB_PANIC, NULL);
303+
if (blob_sizes.lbs_inode)
304+
lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
305+
blob_sizes.lbs_inode, 0,
306+
SLAB_PANIC, NULL);
294307

295308
for (lsm = ordered_lsms; *lsm; lsm++)
296309
initialize_lsm(*lsm);
@@ -481,6 +494,27 @@ static int lsm_file_alloc(struct file *file)
481494
return 0;
482495
}
483496

497+
/**
498+
* lsm_inode_alloc - allocate a composite inode blob
499+
* @inode: the inode that needs a blob
500+
*
501+
* Allocate the inode blob for all the modules
502+
*
503+
* Returns 0, or -ENOMEM if memory can't be allocated.
504+
*/
505+
int lsm_inode_alloc(struct inode *inode)
506+
{
507+
if (!lsm_inode_cache) {
508+
inode->i_security = NULL;
509+
return 0;
510+
}
511+
512+
inode->i_security = kmem_cache_zalloc(lsm_inode_cache, GFP_NOFS);
513+
if (inode->i_security == NULL)
514+
return -ENOMEM;
515+
return 0;
516+
}
517+
484518
/*
485519
* Hook list operation macros.
486520
*
@@ -740,14 +774,40 @@ EXPORT_SYMBOL(security_add_mnt_opt);
740774

741775
int security_inode_alloc(struct inode *inode)
742776
{
743-
inode->i_security = NULL;
744-
return call_int_hook(inode_alloc_security, 0, inode);
777+
int rc = lsm_inode_alloc(inode);
778+
779+
if (unlikely(rc))
780+
return rc;
781+
rc = call_int_hook(inode_alloc_security, 0, inode);
782+
if (unlikely(rc))
783+
security_inode_free(inode);
784+
return rc;
785+
}
786+
787+
static void inode_free_by_rcu(struct rcu_head *head)
788+
{
789+
/*
790+
* The rcu head is at the start of the inode blob
791+
*/
792+
kmem_cache_free(lsm_inode_cache, head);
745793
}
746794

747795
void security_inode_free(struct inode *inode)
748796
{
749797
integrity_inode_free(inode);
750798
call_void_hook(inode_free_security, inode);
799+
/*
800+
* The inode may still be referenced in a path walk and
801+
* a call to security_inode_permission() can be made
802+
* after inode_free_security() is called. Ideally, the VFS
803+
* wouldn't do this, but fixing that is a much harder
804+
* job. For now, simply free the i_security via RCU, and
805+
* leave the current inode->i_security pointer intact.
806+
* The inode will be freed after the RCU grace period too.
807+
*/
808+
if (inode->i_security)
809+
call_rcu((struct rcu_head *)inode->i_security,
810+
inode_free_by_rcu);
751811
}
752812

753813
int security_dentry_init_security(struct dentry *dentry, int mode,

security/selinux/hooks.c

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ static int __init checkreqprot_setup(char *str)
145145
}
146146
__setup("checkreqprot=", checkreqprot_setup);
147147

148-
static struct kmem_cache *sel_inode_cache;
149-
150148
/**
151149
* selinux_secmark_enabled - Check to see if SECMARK is currently enabled
152150
*
@@ -242,21 +240,16 @@ static inline u32 task_sid(const struct task_struct *task)
242240

243241
static int inode_alloc_security(struct inode *inode)
244242
{
245-
struct inode_security_struct *isec;
243+
struct inode_security_struct *isec = selinux_inode(inode);
246244
u32 sid = current_sid();
247245

248-
isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
249-
if (!isec)
250-
return -ENOMEM;
251-
252246
spin_lock_init(&isec->lock);
253247
INIT_LIST_HEAD(&isec->list);
254248
isec->inode = inode;
255249
isec->sid = SECINITSID_UNLABELED;
256250
isec->sclass = SECCLASS_FILE;
257251
isec->task_sid = sid;
258252
isec->initialized = LABEL_INVALID;
259-
inode->i_security = isec;
260253

261254
return 0;
262255
}
@@ -334,19 +327,14 @@ static struct inode_security_struct *backing_inode_security(struct dentry *dentr
334327
return selinux_inode(inode);
335328
}
336329

337-
static void inode_free_rcu(struct rcu_head *head)
338-
{
339-
struct inode_security_struct *isec;
340-
341-
isec = container_of(head, struct inode_security_struct, rcu);
342-
kmem_cache_free(sel_inode_cache, isec);
343-
}
344-
345330
static void inode_free_security(struct inode *inode)
346331
{
347332
struct inode_security_struct *isec = selinux_inode(inode);
348-
struct superblock_security_struct *sbsec = inode->i_sb->s_security;
333+
struct superblock_security_struct *sbsec;
349334

335+
if (!isec)
336+
return;
337+
sbsec = inode->i_sb->s_security;
350338
/*
351339
* As not all inode security structures are in a list, we check for
352340
* empty list outside of the lock to make sure that we won't waste
@@ -362,17 +350,6 @@ static void inode_free_security(struct inode *inode)
362350
list_del_init(&isec->list);
363351
spin_unlock(&sbsec->isec_lock);
364352
}
365-
366-
/*
367-
* The inode may still be referenced in a path walk and
368-
* a call to selinux_inode_permission() can be made
369-
* after inode_free_security() is called. Ideally, the VFS
370-
* wouldn't do this, but fixing that is a much harder
371-
* job. For now, simply free the i_security via RCU, and
372-
* leave the current inode->i_security pointer intact.
373-
* The inode will be freed after the RCU grace period too.
374-
*/
375-
call_rcu(&isec->rcu, inode_free_rcu);
376353
}
377354

378355
static int file_alloc_security(struct file *file)
@@ -6629,6 +6606,7 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
66296606
struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
66306607
.lbs_cred = sizeof(struct task_security_struct),
66316608
.lbs_file = sizeof(struct file_security_struct),
6609+
.lbs_inode = sizeof(struct inode_security_struct),
66326610
};
66336611

66346612
static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
@@ -6881,9 +6859,6 @@ static __init int selinux_init(void)
68816859

68826860
default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
68836861

6884-
sel_inode_cache = kmem_cache_create("selinux_inode_security",
6885-
sizeof(struct inode_security_struct),
6886-
0, SLAB_PANIC, NULL);
68876862
avc_init();
68886863

68896864
avtab_cache_init();

security/selinux/include/objsec.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,7 @@ enum label_initialized {
5757

5858
struct inode_security_struct {
5959
struct inode *inode; /* back pointer to inode object */
60-
union {
61-
struct list_head list; /* list of inode_security_struct */
62-
struct rcu_head rcu; /* for freeing the inode_security_struct */
63-
};
60+
struct list_head list; /* list of inode_security_struct */
6461
u32 task_sid; /* SID of creating task */
6562
u32 sid; /* SID of this object */
6663
u16 sclass; /* security class of this object */
@@ -173,7 +170,9 @@ static inline struct file_security_struct *selinux_file(const struct file *file)
173170
static inline struct inode_security_struct *selinux_inode(
174171
const struct inode *inode)
175172
{
176-
return inode->i_security;
173+
if (unlikely(!inode->i_security))
174+
return NULL;
175+
return inode->i_security + selinux_blob_sizes.lbs_inode;
177176
}
178177

179178
#endif /* _SELINUX_OBJSEC_H_ */

security/smack/smack.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ static inline struct smack_known **smack_file(const struct file *file)
370370

371371
static inline struct inode_smack *smack_inode(const struct inode *inode)
372372
{
373-
return inode->i_security;
373+
return inode->i_security + smack_blob_sizes.lbs_inode;
374374
}
375375

376376
/*

security/smack/smack_lsm.c

Lines changed: 17 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -305,24 +305,18 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
305305
}
306306

307307
/**
308-
* new_inode_smack - allocate an inode security blob
308+
* init_inode_smack - initialize an inode security blob
309+
* @isp: the blob to initialize
309310
* @skp: a pointer to the Smack label entry to use in the blob
310311
*
311-
* Returns the new blob or NULL if there's no memory available
312312
*/
313-
static struct inode_smack *new_inode_smack(struct smack_known *skp)
313+
static void init_inode_smack(struct inode *inode, struct smack_known *skp)
314314
{
315-
struct inode_smack *isp;
316-
317-
isp = kmem_cache_zalloc(smack_inode_cache, GFP_NOFS);
318-
if (isp == NULL)
319-
return NULL;
315+
struct inode_smack *isp = smack_inode(inode);
320316

321317
isp->smk_inode = skp;
322318
isp->smk_flags = 0;
323319
mutex_init(&isp->smk_lock);
324-
325-
return isp;
326320
}
327321

328322
/**
@@ -709,6 +703,13 @@ static int smack_set_mnt_opts(struct super_block *sb,
709703
if (sp->smk_flags & SMK_SB_INITIALIZED)
710704
return 0;
711705

706+
if (inode->i_security == NULL) {
707+
int rc = lsm_inode_alloc(inode);
708+
709+
if (rc)
710+
return rc;
711+
}
712+
712713
if (!smack_privileged(CAP_MAC_ADMIN)) {
713714
/*
714715
* Unprivileged mounts don't get to specify Smack values.
@@ -773,17 +774,12 @@ static int smack_set_mnt_opts(struct super_block *sb,
773774
/*
774775
* Initialize the root inode.
775776
*/
776-
isp = smack_inode(inode);
777-
if (isp == NULL) {
778-
isp = new_inode_smack(sp->smk_root);
779-
if (isp == NULL)
780-
return -ENOMEM;
781-
inode->i_security = isp;
782-
} else
783-
isp->smk_inode = sp->smk_root;
777+
init_inode_smack(inode, sp->smk_root);
784778

785-
if (transmute)
779+
if (transmute) {
780+
isp = smack_inode(inode);
786781
isp->smk_flags |= SMK_INODE_TRANSMUTE;
782+
}
787783

788784
return 0;
789785
}
@@ -881,48 +877,10 @@ static int smack_inode_alloc_security(struct inode *inode)
881877
{
882878
struct smack_known *skp = smk_of_current();
883879

884-
inode->i_security = new_inode_smack(skp);
885-
if (inode->i_security == NULL)
886-
return -ENOMEM;
880+
init_inode_smack(inode, skp);
887881
return 0;
888882
}
889883

890-
/**
891-
* smack_inode_free_rcu - Free inode_smack blob from cache
892-
* @head: the rcu_head for getting inode_smack pointer
893-
*
894-
* Call back function called from call_rcu() to free
895-
* the i_security blob pointer in inode
896-
*/
897-
static void smack_inode_free_rcu(struct rcu_head *head)
898-
{
899-
struct inode_smack *issp;
900-
901-
issp = container_of(head, struct inode_smack, smk_rcu);
902-
kmem_cache_free(smack_inode_cache, issp);
903-
}
904-
905-
/**
906-
* smack_inode_free_security - free an inode blob using call_rcu()
907-
* @inode: the inode with a blob
908-
*
909-
* Clears the blob pointer in inode using RCU
910-
*/
911-
static void smack_inode_free_security(struct inode *inode)
912-
{
913-
struct inode_smack *issp = smack_inode(inode);
914-
915-
/*
916-
* The inode may still be referenced in a path walk and
917-
* a call to smack_inode_permission() can be made
918-
* after smack_inode_free_security() is called.
919-
* To avoid race condition free the i_security via RCU
920-
* and leave the current inode->i_security pointer intact.
921-
* The inode will be freed after the RCU grace period too.
922-
*/
923-
call_rcu(&issp->smk_rcu, smack_inode_free_rcu);
924-
}
925-
926884
/**
927885
* smack_inode_init_security - copy out the smack from an inode
928886
* @inode: the newly created inode
@@ -4548,6 +4506,7 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
45484506
struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
45494507
.lbs_cred = sizeof(struct task_smack),
45504508
.lbs_file = sizeof(struct smack_known *),
4509+
.lbs_inode = sizeof(struct inode_smack),
45514510
};
45524511

45534512
static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
@@ -4565,7 +4524,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
45654524
LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
45664525

45674526
LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security),
4568-
LSM_HOOK_INIT(inode_free_security, smack_inode_free_security),
45694527
LSM_HOOK_INIT(inode_init_security, smack_inode_init_security),
45704528
LSM_HOOK_INIT(inode_link, smack_inode_link),
45714529
LSM_HOOK_INIT(inode_unlink, smack_inode_unlink),

0 commit comments

Comments
 (0)