Skip to content

Commit 1aea780

Browse files
cschauflerJames Morris
authored andcommitted
LSM: Infrastructure management of the superblock
Move management of the superblock->sb_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. Cc: John Johansen <[email protected]> Signed-off-by: Casey Schaufler <[email protected]> Signed-off-by: Mickaël Salaün <[email protected]> Reviewed-by: Stephen Smalley <[email protected]> Acked-by: Serge Hallyn <[email protected]> Reviewed-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: James Morris <[email protected]>
1 parent afe81f7 commit 1aea780

File tree

7 files changed

+85
-70
lines changed

7 files changed

+85
-70
lines changed

include/linux/lsm_hooks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,7 @@ struct lsm_blob_sizes {
15731573
int lbs_cred;
15741574
int lbs_file;
15751575
int lbs_inode;
1576+
int lbs_superblock;
15761577
int lbs_ipc;
15771578
int lbs_msg_msg;
15781579
int lbs_task;

security/security.c

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
203203
lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
204204
lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
205205
lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
206+
lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
206207
lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
207208
}
208209

@@ -333,12 +334,13 @@ static void __init ordered_lsm_init(void)
333334
for (lsm = ordered_lsms; *lsm; lsm++)
334335
prepare_lsm(*lsm);
335336

336-
init_debug("cred blob size = %d\n", blob_sizes.lbs_cred);
337-
init_debug("file blob size = %d\n", blob_sizes.lbs_file);
338-
init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
339-
init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc);
340-
init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg);
341-
init_debug("task blob size = %d\n", blob_sizes.lbs_task);
337+
init_debug("cred blob size = %d\n", blob_sizes.lbs_cred);
338+
init_debug("file blob size = %d\n", blob_sizes.lbs_file);
339+
init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
340+
init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc);
341+
init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg);
342+
init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
343+
init_debug("task blob size = %d\n", blob_sizes.lbs_task);
342344

343345
/*
344346
* Create any kmem_caches needed for blobs
@@ -670,6 +672,27 @@ static void __init lsm_early_task(struct task_struct *task)
670672
panic("%s: Early task alloc failed.\n", __func__);
671673
}
672674

675+
/**
676+
* lsm_superblock_alloc - allocate a composite superblock blob
677+
* @sb: the superblock that needs a blob
678+
*
679+
* Allocate the superblock blob for all the modules
680+
*
681+
* Returns 0, or -ENOMEM if memory can't be allocated.
682+
*/
683+
static int lsm_superblock_alloc(struct super_block *sb)
684+
{
685+
if (blob_sizes.lbs_superblock == 0) {
686+
sb->s_security = NULL;
687+
return 0;
688+
}
689+
690+
sb->s_security = kzalloc(blob_sizes.lbs_superblock, GFP_KERNEL);
691+
if (sb->s_security == NULL)
692+
return -ENOMEM;
693+
return 0;
694+
}
695+
673696
/*
674697
* The default value of the LSM hook is defined in linux/lsm_hook_defs.h and
675698
* can be accessed with:
@@ -867,12 +890,21 @@ int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *
867890

868891
int security_sb_alloc(struct super_block *sb)
869892
{
870-
return call_int_hook(sb_alloc_security, 0, sb);
893+
int rc = lsm_superblock_alloc(sb);
894+
895+
if (unlikely(rc))
896+
return rc;
897+
rc = call_int_hook(sb_alloc_security, 0, sb);
898+
if (unlikely(rc))
899+
security_sb_free(sb);
900+
return rc;
871901
}
872902

873903
void security_sb_free(struct super_block *sb)
874904
{
875905
call_void_hook(sb_free_security, sb);
906+
kfree(sb->s_security);
907+
sb->s_security = NULL;
876908
}
877909

878910
void security_free_mnt_opts(void **mnt_opts)

security/selinux/hooks.c

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static void inode_free_security(struct inode *inode)
322322

323323
if (!isec)
324324
return;
325-
sbsec = inode->i_sb->s_security;
325+
sbsec = selinux_superblock(inode->i_sb);
326326
/*
327327
* As not all inode security structures are in a list, we check for
328328
* empty list outside of the lock to make sure that we won't waste
@@ -340,13 +340,6 @@ static void inode_free_security(struct inode *inode)
340340
}
341341
}
342342

343-
static void superblock_free_security(struct super_block *sb)
344-
{
345-
struct superblock_security_struct *sbsec = sb->s_security;
346-
sb->s_security = NULL;
347-
kfree(sbsec);
348-
}
349-
350343
struct selinux_mnt_opts {
351344
const char *fscontext, *context, *rootcontext, *defcontext;
352345
};
@@ -458,7 +451,7 @@ static int selinux_is_genfs_special_handling(struct super_block *sb)
458451

459452
static int selinux_is_sblabel_mnt(struct super_block *sb)
460453
{
461-
struct superblock_security_struct *sbsec = sb->s_security;
454+
struct superblock_security_struct *sbsec = selinux_superblock(sb);
462455

463456
/*
464457
* IMPORTANT: Double-check logic in this function when adding a new
@@ -535,7 +528,7 @@ static int sb_check_xattr_support(struct super_block *sb)
535528

536529
static int sb_finish_set_opts(struct super_block *sb)
537530
{
538-
struct superblock_security_struct *sbsec = sb->s_security;
531+
struct superblock_security_struct *sbsec = selinux_superblock(sb);
539532
struct dentry *root = sb->s_root;
540533
struct inode *root_inode = d_backing_inode(root);
541534
int rc = 0;
@@ -626,7 +619,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
626619
unsigned long *set_kern_flags)
627620
{
628621
const struct cred *cred = current_cred();
629-
struct superblock_security_struct *sbsec = sb->s_security;
622+
struct superblock_security_struct *sbsec = selinux_superblock(sb);
630623
struct dentry *root = sb->s_root;
631624
struct selinux_mnt_opts *opts = mnt_opts;
632625
struct inode_security_struct *root_isec;
@@ -863,8 +856,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
863856
static int selinux_cmp_sb_context(const struct super_block *oldsb,
864857
const struct super_block *newsb)
865858
{
866-
struct superblock_security_struct *old = oldsb->s_security;
867-
struct superblock_security_struct *new = newsb->s_security;
859+
struct superblock_security_struct *old = selinux_superblock(oldsb);
860+
struct superblock_security_struct *new = selinux_superblock(newsb);
868861
char oldflags = old->flags & SE_MNTMASK;
869862
char newflags = new->flags & SE_MNTMASK;
870863

@@ -896,8 +889,9 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
896889
unsigned long *set_kern_flags)
897890
{
898891
int rc = 0;
899-
const struct superblock_security_struct *oldsbsec = oldsb->s_security;
900-
struct superblock_security_struct *newsbsec = newsb->s_security;
892+
const struct superblock_security_struct *oldsbsec =
893+
selinux_superblock(oldsb);
894+
struct superblock_security_struct *newsbsec = selinux_superblock(newsb);
901895

902896
int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
903897
int set_context = (oldsbsec->flags & CONTEXT_MNT);
@@ -1076,7 +1070,7 @@ static int show_sid(struct seq_file *m, u32 sid)
10761070

10771071
static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
10781072
{
1079-
struct superblock_security_struct *sbsec = sb->s_security;
1073+
struct superblock_security_struct *sbsec = selinux_superblock(sb);
10801074
int rc;
10811075

10821076
if (!(sbsec->flags & SE_SBINITIALIZED))
@@ -1427,7 +1421,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
14271421
if (isec->sclass == SECCLASS_FILE)
14281422
isec->sclass = inode_mode_to_security_class(inode->i_mode);
14291423

1430-
sbsec = inode->i_sb->s_security;
1424+
sbsec = selinux_superblock(inode->i_sb);
14311425
if (!(sbsec->flags & SE_SBINITIALIZED)) {
14321426
/* Defer initialization until selinux_complete_init,
14331427
after the initial policy is loaded and the security
@@ -1778,7 +1772,8 @@ selinux_determine_inode_label(const struct task_security_struct *tsec,
17781772
const struct qstr *name, u16 tclass,
17791773
u32 *_new_isid)
17801774
{
1781-
const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
1775+
const struct superblock_security_struct *sbsec =
1776+
selinux_superblock(dir->i_sb);
17821777

17831778
if ((sbsec->flags & SE_SBINITIALIZED) &&
17841779
(sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
@@ -1809,7 +1804,7 @@ static int may_create(struct inode *dir,
18091804
int rc;
18101805

18111806
dsec = inode_security(dir);
1812-
sbsec = dir->i_sb->s_security;
1807+
sbsec = selinux_superblock(dir->i_sb);
18131808

18141809
sid = tsec->sid;
18151810

@@ -1958,7 +1953,7 @@ static int superblock_has_perm(const struct cred *cred,
19581953
struct superblock_security_struct *sbsec;
19591954
u32 sid = cred_sid(cred);
19601955

1961-
sbsec = sb->s_security;
1956+
sbsec = selinux_superblock(sb);
19621957
return avc_has_perm(&selinux_state,
19631958
sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
19641959
}
@@ -2587,28 +2582,18 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
25872582

25882583
static int selinux_sb_alloc_security(struct super_block *sb)
25892584
{
2590-
struct superblock_security_struct *sbsec;
2591-
2592-
sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
2593-
if (!sbsec)
2594-
return -ENOMEM;
2585+
struct superblock_security_struct *sbsec = selinux_superblock(sb);
25952586

25962587
mutex_init(&sbsec->lock);
25972588
INIT_LIST_HEAD(&sbsec->isec_head);
25982589
spin_lock_init(&sbsec->isec_lock);
25992590
sbsec->sid = SECINITSID_UNLABELED;
26002591
sbsec->def_sid = SECINITSID_FILE;
26012592
sbsec->mntpoint_sid = SECINITSID_UNLABELED;
2602-
sb->s_security = sbsec;
26032593

26042594
return 0;
26052595
}
26062596

2607-
static void selinux_sb_free_security(struct super_block *sb)
2608-
{
2609-
superblock_free_security(sb);
2610-
}
2611-
26122597
static inline int opt_len(const char *s)
26132598
{
26142599
bool open_quote = false;
@@ -2687,7 +2672,7 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
26872672
static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
26882673
{
26892674
struct selinux_mnt_opts *opts = mnt_opts;
2690-
struct superblock_security_struct *sbsec = sb->s_security;
2675+
struct superblock_security_struct *sbsec = selinux_superblock(sb);
26912676
u32 sid;
26922677
int rc;
26932678

@@ -2925,7 +2910,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
29252910
int rc;
29262911
char *context;
29272912

2928-
sbsec = dir->i_sb->s_security;
2913+
sbsec = selinux_superblock(dir->i_sb);
29292914

29302915
newsid = tsec->create_sid;
29312916

@@ -3227,7 +3212,7 @@ static int selinux_inode_setxattr(struct user_namespace *mnt_userns,
32273212
if (!selinux_initialized(&selinux_state))
32283213
return (inode_owner_or_capable(mnt_userns, inode) ? 0 : -EPERM);
32293214

3230-
sbsec = inode->i_sb->s_security;
3215+
sbsec = selinux_superblock(inode->i_sb);
32313216
if (!(sbsec->flags & SBLABEL_MNT))
32323217
return -EOPNOTSUPP;
32333218

@@ -3472,13 +3457,14 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
34723457
const void *value, size_t size, int flags)
34733458
{
34743459
struct inode_security_struct *isec = inode_security_novalidate(inode);
3475-
struct superblock_security_struct *sbsec = inode->i_sb->s_security;
3460+
struct superblock_security_struct *sbsec;
34763461
u32 newsid;
34773462
int rc;
34783463

34793464
if (strcmp(name, XATTR_SELINUX_SUFFIX))
34803465
return -EOPNOTSUPP;
34813466

3467+
sbsec = selinux_superblock(inode->i_sb);
34823468
if (!(sbsec->flags & SBLABEL_MNT))
34833469
return -EOPNOTSUPP;
34843470

@@ -6975,6 +6961,7 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
69756961
.lbs_inode = sizeof(struct inode_security_struct),
69766962
.lbs_ipc = sizeof(struct ipc_security_struct),
69776963
.lbs_msg_msg = sizeof(struct msg_security_struct),
6964+
.lbs_superblock = sizeof(struct superblock_security_struct),
69786965
};
69796966

69806967
#ifdef CONFIG_PERF_EVENTS
@@ -7075,7 +7062,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
70757062
LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
70767063
LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
70777064

7078-
LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
70797065
LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
70807066
LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
70817067
LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),

security/selinux/include/objsec.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,10 @@ static inline u32 current_sid(void)
188188
return tsec->sid;
189189
}
190190

191+
static inline struct superblock_security_struct *selinux_superblock(
192+
const struct super_block *superblock)
193+
{
194+
return superblock->s_security + selinux_blob_sizes.lbs_superblock;
195+
}
196+
191197
#endif /* _SELINUX_OBJSEC_H_ */

security/selinux/ss/services.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <linux/sched.h>
4848
#include <linux/audit.h>
4949
#include <linux/vmalloc.h>
50+
#include <linux/lsm_hooks.h>
5051
#include <net/netlabel.h>
5152

5253
#include "flask.h"
@@ -2875,7 +2876,7 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
28752876
struct sidtab *sidtab;
28762877
int rc = 0;
28772878
struct ocontext *c;
2878-
struct superblock_security_struct *sbsec = sb->s_security;
2879+
struct superblock_security_struct *sbsec = selinux_superblock(sb);
28792880
const char *fstype = sb->s_type->name;
28802881

28812882
if (!selinux_initialized(state)) {

security/smack/smack.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,12 @@ static inline struct smack_known **smack_ipc(const struct kern_ipc_perm *ipc)
357357
return ipc->security + smack_blob_sizes.lbs_ipc;
358358
}
359359

360+
static inline struct superblock_smack *smack_superblock(
361+
const struct super_block *superblock)
362+
{
363+
return superblock->s_security + smack_blob_sizes.lbs_superblock;
364+
}
365+
360366
/*
361367
* Is the directory transmuting?
362368
*/

0 commit comments

Comments
 (0)