* Re: [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure. [not found] ` <20191123011454.3292-1-casey@schaufler-ca.com> @ 2019-11-23 5:21 ` Tetsuo Handa 0 siblings, 0 replies; 6+ messages in thread From: Tetsuo Handa @ 2019-11-23 5:21 UTC (permalink / raw) To: Casey Schaufler; +Cc: linux-security-module On 2019/11/23 10:14, Casey Schaufler wrote: > When more than one security module is exporting data to > audit and networking sub-systems a single 32 bit integer > is no longer sufficient to represent the data. Add a > structure to be used instead. > > The lsmblob structure is currently an array of > u32 "secids". There is an entry for each of the > security modules built into the system that would > use secids if active. The system assigns the module > a "slot" when it registers hooks. If modules are > compiled in but not registered there will be unused > slots. > > A new lsm_id structure, which contains the name > of the LSM and its slot number, is created. There > is an instance for each LSM, which assigns the name > and passes it to the infrastructure to set the slot. > > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> > --- > include/linux/lsm_hooks.h | 12 ++++++-- > include/linux/security.h | 58 ++++++++++++++++++++++++++++++++++++++ > security/apparmor/lsm.c | 7 ++++- > security/commoncap.c | 7 ++++- > security/loadpin/loadpin.c | 8 +++++- > security/safesetid/lsm.c | 8 +++++- > security/security.c | 28 ++++++++++++++---- > security/selinux/hooks.c | 8 +++++- > security/smack/smack_lsm.c | 7 ++++- > security/tomoyo/tomoyo.c | 8 +++++- > security/yama/yama_lsm.c | 7 ++++- > 11 files changed, 142 insertions(+), 16 deletions(-) > For TOMOYO part, Acked-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v11 00/25] LSM: Module stacking for AppArmor @ 2019-11-13 18:19 Casey Schaufler 2019-11-13 18:19 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Casey Schaufler 0 siblings, 1 reply; 6+ messages in thread From: Casey Schaufler @ 2019-11-13 18:19 UTC (permalink / raw) To: casey.schaufler, jmorris, linux-security-module, selinux Cc: keescook, john.johansen, penguin-kernel, paul, sds Apologies for the multiple copies. Issues on the ISP end. This patchset provides the changes required for the AppArmor security module to stack safely with any other. v11: Rebase to 5.4-rc6 Incorporate feedback from v10 - Disambiguate reading /proc/.../attr/display by restricting all use of the interface to the current process. - Fix a merge error in AppArmor's display attribute check v10: Ask the security modules if the display can be changed. v9: There is no version 9 v8: Incorporate feedback from v7 - Minor clean-up in display value management - refactor "compound" context creation to use a common append_ctx() function. v7: Incorporate feedback from v6 - Make setting the display a privileged operation. The availability of compound contexts reduces the need for setting the display. v6: Incorporate feedback from v5 - Add subj_<lsm>= and obj_<lsm>= fields to audit records - Add /proc/.../attr/context to get the full context in lsmname\0value\0... format as suggested by Simon McVittie - Add SO_PEERCONTEXT for getsockopt() to get the full context in the same format, also suggested by Simon McVittie. - Add /sys/kernel/security/lsm_display_default to provide the display default value. v5: Incorporate feedback from v4 - Initialize the lsmcontext in security_secid_to_secctx() - Clear the lsmcontext in all security_release_secctx() cases - Don't use the "display" on strictly internal context interfaces. - The SELinux binder hooks check for cases where the context "display" isn't compatible with SELinux. v4: Incorporate feedback from v3 - Mark new lsm_<blob>_alloc functions static - Replace the lsm and slot fields of the security_hook_list with a pointer to a LSM allocated lsm_id structure. The LSM identifies if it needs a slot explicitly. Use the lsm_id rather than make security_add_hooks return the slot value. - Validate slot values used in security.c - Reworked the "display" process attribute handling so that it works right and doesn't use goofy list processing. - fix display value check in dentry_init_security - Replace audit_log of secids with '?' instead of deleting the audit log v3: Incorporate feedback from v2 - Make lsmblob parameter and variable names more meaningful, changing "le" and "l" to "blob". - Improve consistency of constant naming. - Do more sanity checking during LSM initialization. - Be a bit clearer about what is temporary scaffolding. - Rather than clutter security_getpeersec_dgram with otherwise unnecessary checks remove the apparmor stub, which does nothing useful. Patche 0001 moves management of the sock security blob from the individual modules to the infrastructure. Patches 0002-0012 replace system use of a "secid" with a structure "lsmblob" containing information from the security modules to be held and reused later. At this point lsmblob contains an array of u32 secids, one "slot" for each of the security modules compiled into the kernel that used secids. A "slot" is allocated when a security module requests one. The infrastructure is changed to use the slot number to pass the correct secid to or from the security module hooks. It is important that the lsmblob be a fixed size entity that does not have to be allocated. Several of the places where it is used would have performance and/or locking issues with dynamic allocation. Patch 0013 provides a mechanism for a process to identify which security module's hooks should be used when displaying or converting a security context string. A new interface /proc/self/attr/display contains the name of the security module to show. Reading from this file will present the name of the module, while writing to it will set the value. Only names of active security modules are accepted. Internally, the name is translated to the appropriate "slot" number for the module which is then stored in the task security blob. Setting the display requires that all modules using the /proc interfaces allow the transition. The "display" of other processess can be neither read nor written. All suggested cases for reading the display of a different process have race conditions. Patch 0014 Starts the process of changing how a security context is represented. Since it is possible for a security context to have been generated by more than one security module it is now necessary to note which module created a security context so that the correct "release" hook can be called. There are several places where the module that created a security context cannot be inferred. This is achieved by introducing a "lsmcontext" structure which contains the context string, its length and the "slot" number of the security module that created it. The security_release_secctx() interface is changed, replacing the (string,len) pointer pair with a lsmcontext pointer. Patches 0015-0017 convert the security interfaces from (string,len) pointer pairs to a lsmcontext pointer. The slot number identifying the creating module is added by the infrastructure. Where the security context is stored for extended periods the data type is changed. The Netlabel code is converted to save lsmblob structures instead of secids in Patches 0018-0019. Patch 0020 adds checks to the binder hooks which verify that if both ends of a transaction use the same "display". Patches 0021-0022 add addition data to the audit records to identify the LSM specific data for all active modules. Patches 0023-0024 add new interfaces for getting the compound security contexts. Finally, with all interference on the AppArmor hooks removed, Patch 0025 removes the exclusive bit from AppArmor. An unnecessary stub hook was also removed. The Ubuntu project is using an earlier version of this patchset in their distribution to enable stacking for containers. Performance measurements to date have the change within the "noise". The sockperf and dbench results are on the order of 0.2% to 0.8% difference, with better performance being as common as worse. The benchmarks were run with AppArmor and Smack on Ubuntu. https://github.com/cschaufler/lsm-stacking.git#stack-5.4-rc6-v11-apparmor Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- arch/alpha/include/uapi/asm/socket.h | 1 + arch/mips/include/uapi/asm/socket.h | 1 + arch/parisc/include/uapi/asm/socket.h | 1 + arch/sparc/include/uapi/asm/socket.h | 1 + drivers/android/binder.c | 26 +- fs/ceph/xattr.c | 6 +- fs/nfs/nfs4proc.c | 22 +- fs/nfsd/nfs4xdr.c | 20 +- fs/proc/base.c | 2 + include/linux/audit.h | 1 + include/linux/cred.h | 3 +- include/linux/lsm_hooks.h | 37 +- include/linux/security.h | 175 ++++++++-- include/net/af_unix.h | 2 +- include/net/netlabel.h | 8 +- include/net/scm.h | 15 +- include/uapi/asm-generic/socket.h | 1 + kernel/audit.c | 72 +++- kernel/audit.h | 9 +- kernel/audit_fsnotify.c | 1 + kernel/auditfilter.c | 10 +- kernel/auditsc.c | 127 ++++--- kernel/cred.c | 12 +- net/core/sock.c | 7 +- net/ipv4/cipso_ipv4.c | 6 +- net/ipv4/ip_sockglue.c | 12 +- net/netfilter/nf_conntrack_netlink.c | 20 +- net/netfilter/nf_conntrack_standalone.c | 11 +- net/netfilter/nfnetlink_queue.c | 26 +- net/netfilter/nft_meta.c | 13 +- net/netfilter/xt_SECMARK.c | 5 +- net/netlabel/netlabel_kapi.c | 6 +- net/netlabel/netlabel_unlabeled.c | 97 +++--- net/netlabel/netlabel_unlabeled.h | 2 +- net/netlabel/netlabel_user.c | 13 +- net/netlabel/netlabel_user.h | 6 +- net/unix/af_unix.c | 6 +- net/xfrm/xfrm_policy.c | 2 + net/xfrm/xfrm_state.c | 2 + security/apparmor/include/apparmor.h | 3 +- security/apparmor/include/net.h | 6 +- security/apparmor/lsm.c | 117 +++---- security/commoncap.c | 7 +- security/integrity/ima/ima.h | 15 +- security/integrity/ima/ima_api.c | 11 +- security/integrity/ima/ima_appraise.c | 6 +- security/integrity/ima/ima_main.c | 49 +-- security/integrity/ima/ima_policy.c | 19 +- security/integrity/integrity_audit.c | 1 + security/loadpin/loadpin.c | 8 +- security/safesetid/lsm.c | 8 +- security/security.c | 593 +++++++++++++++++++++++++++++--- security/selinux/hooks.c | 109 +++--- security/selinux/include/classmap.h | 2 +- security/selinux/include/objsec.h | 5 + security/selinux/include/security.h | 1 + security/selinux/netlabel.c | 25 +- security/selinux/ss/services.c | 4 +- security/smack/smack.h | 6 + security/smack/smack_lsm.c | 124 ++++--- security/smack/smack_netfilter.c | 8 +- security/smack/smackfs.c | 10 +- security/tomoyo/tomoyo.c | 8 +- security/yama/yama_lsm.c | 7 +- 64 files changed, 1376 insertions(+), 563 deletions(-) ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure. 2019-11-13 18:19 [PATCH v11 00/25] LSM: Module stacking for AppArmor Casey Schaufler @ 2019-11-13 18:19 ` Casey Schaufler 2019-11-21 18:40 ` John Johansen 0 siblings, 1 reply; 6+ messages in thread From: Casey Schaufler @ 2019-11-13 18:19 UTC (permalink / raw) To: casey.schaufler, jmorris, linux-security-module, selinux Cc: keescook, john.johansen, penguin-kernel, paul, sds When more than one security module is exporting data to audit and networking sub-systems a single 32 bit integer is no longer sufficient to represent the data. Add a structure to be used instead. The lsmblob structure is currently an array of u32 "secids". There is an entry for each of the security modules built into the system that would use secids if active. The system assigns the module a "slot" when it registers hooks. If modules are compiled in but not registered there will be unused slots. A new lsm_id structure, which contains the name of the LSM and its slot number, is created. There is an instance for each LSM, which assigns the name and passes it to the infrastructure to set the slot. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/lsm_hooks.h | 12 ++++++-- include/linux/security.h | 58 ++++++++++++++++++++++++++++++++++++++ security/apparmor/lsm.c | 7 ++++- security/commoncap.c | 7 ++++- security/loadpin/loadpin.c | 8 +++++- security/safesetid/lsm.c | 8 +++++- security/security.c | 28 ++++++++++++++---- security/selinux/hooks.c | 8 +++++- security/smack/smack_lsm.c | 7 ++++- security/tomoyo/tomoyo.c | 8 +++++- security/yama/yama_lsm.c | 7 ++++- 11 files changed, 142 insertions(+), 16 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 13a67fd1a767..cfe5393840c7 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -2062,6 +2062,14 @@ struct security_hook_heads { struct hlist_head locked_down; } __randomize_layout; +/* + * Information that identifies a security module. + */ +struct lsm_id { + const char *lsm; /* Name of the LSM */ + int slot; /* Slot in lsmblob if one is allocated */ +}; + /* * Security module hook list structure. * For use with generic list macros for common operations. @@ -2070,7 +2078,7 @@ struct security_hook_list { struct hlist_node list; struct hlist_head *head; union security_list_options hook; - char *lsm; + struct lsm_id *lsmid; } __randomize_layout; /* @@ -2099,7 +2107,7 @@ extern struct security_hook_heads security_hook_heads; extern char *lsm_names; extern void security_add_hooks(struct security_hook_list *hooks, int count, - char *lsm); + struct lsm_id *lsmid); #define LSM_FLAG_LEGACY_MAJOR BIT(0) #define LSM_FLAG_EXCLUSIVE BIT(1) diff --git a/include/linux/security.h b/include/linux/security.h index 9df7547afc0c..5eced28fa0c9 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -126,6 +126,64 @@ enum lockdown_reason { LOCKDOWN_CONFIDENTIALITY_MAX, }; +/* + * Data exported by the security modules + * + * Any LSM that provides secid or secctx based hooks must be included. + */ +#define LSMBLOB_ENTRIES ( \ + (IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0)) + +struct lsmblob { + u32 secid[LSMBLOB_ENTRIES]; +}; + +#define LSMBLOB_INVALID -1 /* Not a valid LSM slot number */ +#define LSMBLOB_NEEDED -2 /* Slot requested on initialization */ +#define LSMBLOB_NOT_NEEDED -3 /* Slot not requested */ + +/** + * lsmblob_init - initialize an lsmblob structure. + * @blob: Pointer to the data to initialize + * @secid: The initial secid value + * + * Set all secid for all modules to the specified value. + */ +static inline void lsmblob_init(struct lsmblob *blob, u32 secid) +{ + int i; + + for (i = 0; i < LSMBLOB_ENTRIES; i++) + blob->secid[i] = secid; +} + +/** + * lsmblob_is_set - report if there is an value in the lsmblob + * @blob: Pointer to the exported LSM data + * + * Returns true if there is a secid set, false otherwise + */ +static inline bool lsmblob_is_set(struct lsmblob *blob) +{ + struct lsmblob empty = {}; + + return !!memcmp(blob, &empty, sizeof(*blob)); +} + +/** + * lsmblob_equal - report if the two lsmblob's are equal + * @bloba: Pointer to one LSM data + * @blobb: Pointer to the other LSM data + * + * Returns true if all entries in the two are equal, false otherwise + */ +static inline bool lsmblob_equal(struct lsmblob *bloba, struct lsmblob *blobb) +{ + return !memcmp(bloba, blobb, sizeof(*bloba)); +} + /* These functions are in security/commoncap.c */ extern int cap_capable(const struct cred *cred, struct user_namespace *ns, int cap, unsigned int opts); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 4093fa231671..11845348eefb 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1134,6 +1134,11 @@ struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct aa_sk_ctx), }; +static struct lsm_id apparmor_lsmid __lsm_ro_after_init = { + .lsm = "apparmor", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), @@ -1722,7 +1727,7 @@ static int __init apparmor_init(void) goto buffers_out; } security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks), - "apparmor"); + &apparmor_lsmid); /* Report that AppArmor successfully initialized */ apparmor_initialized = 1; diff --git a/security/commoncap.c b/security/commoncap.c index f4ee0ae106b2..9dcfd2a0e891 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -1339,6 +1339,11 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, #ifdef CONFIG_SECURITY +static struct lsm_id capability_lsmid __lsm_ro_after_init = { + .lsm = "capability", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list capability_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(capable, cap_capable), LSM_HOOK_INIT(settime, cap_settime), @@ -1363,7 +1368,7 @@ static struct security_hook_list capability_hooks[] __lsm_ro_after_init = { static int __init capability_init(void) { security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks), - "capability"); + &capability_lsmid); return 0; } diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index ee5cb944f4ad..86317e78899f 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c @@ -180,6 +180,11 @@ static int loadpin_load_data(enum kernel_load_data_id id) return loadpin_read_file(NULL, (enum kernel_read_file_id) id); } +static struct lsm_id loadpin_lsmid __lsm_ro_after_init = { + .lsm = "loadpin", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), @@ -227,7 +232,8 @@ static int __init loadpin_init(void) pr_info("ready to pin (currently %senforcing)\n", enforce ? "" : "not "); parse_exclude(); - security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); + security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), + &loadpin_lsmid); return 0; } diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c index 7760019ad35d..950dfb7f931e 100644 --- a/security/safesetid/lsm.c +++ b/security/safesetid/lsm.c @@ -149,6 +149,11 @@ static int safesetid_task_fix_setuid(struct cred *new, return -EACCES; } +static struct lsm_id safesetid_lsmid __lsm_ro_after_init = { + .lsm = "safesetid", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list safesetid_security_hooks[] = { LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid), LSM_HOOK_INIT(capable, safesetid_security_capable) @@ -157,7 +162,8 @@ static struct security_hook_list safesetid_security_hooks[] = { static int __init safesetid_security_init(void) { security_add_hooks(safesetid_security_hooks, - ARRAY_SIZE(safesetid_security_hooks), "safesetid"); + ARRAY_SIZE(safesetid_security_hooks), + &safesetid_lsmid); /* Report that SafeSetID successfully initialized */ safesetid_initialized = 1; diff --git a/security/security.c b/security/security.c index 5e43d3f64c1f..5f503cadf7f3 100644 --- a/security/security.c +++ b/security/security.c @@ -308,6 +308,7 @@ static void __init ordered_lsm_init(void) init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); init_debug("task blob size = %d\n", blob_sizes.lbs_task); + init_debug("lsmblob size = %lu\n", sizeof(struct lsmblob)); /* * Create any kmem_caches needed for blobs @@ -435,21 +436,36 @@ static int lsm_append(const char *new, char **result) return 0; } +/* + * Current index to use while initializing the lsmblob secid list. + */ +static int lsm_slot __initdata; + /** * security_add_hooks - Add a modules hooks to the hook lists. * @hooks: the hooks to add * @count: the number of hooks to add - * @lsm: the name of the security module + * @lsmid: the the identification information for the security module * * Each LSM has to register its hooks with the infrastructure. + * If the LSM is using hooks that export secids allocate a slot + * for it in the lsmblob. */ void __init security_add_hooks(struct security_hook_list *hooks, int count, - char *lsm) + struct lsm_id *lsmid) { int i; + if (lsmid->slot == LSMBLOB_NEEDED) { + if (lsm_slot >= LSMBLOB_ENTRIES) + panic("%s Too many LSMs registered.\n", __func__); + lsmid->slot = lsm_slot++; + init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm, + lsmid->slot); + } + for (i = 0; i < count; i++) { - hooks[i].lsm = lsm; + hooks[i].lsmid = lsmid; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); } @@ -458,7 +474,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, * and fix this up afterwards. */ if (slab_is_available()) { - if (lsm_append(lsm, &lsm_names) < 0) + if (lsm_append(lsmid->lsm, &lsm_names) < 0) panic("%s - Cannot get early memory.\n", __func__); } } @@ -1906,7 +1922,7 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name, struct security_hook_list *hp; hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { - if (lsm != NULL && strcmp(lsm, hp->lsm)) + if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; return hp->hook.getprocattr(p, name, value); } @@ -1919,7 +1935,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value, struct security_hook_list *hp; hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { - if (lsm != NULL && strcmp(lsm, hp->lsm)) + if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; return hp->hook.setprocattr(name, value, size); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3feb971068e2..5570a6ed49d5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6791,6 +6791,11 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct sk_security_struct), }; +static struct lsm_id selinux_lsmid __lsm_ro_after_init = { + .lsm = "selinux", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), @@ -7051,7 +7056,8 @@ static __init int selinux_init(void) hashtab_cache_init(); - security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); + security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), + &selinux_lsmid); if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) panic("SELinux: Unable to register AVC netcache callback\n"); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 796f78580c17..e42336328446 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4586,6 +4586,11 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct socket_smack), }; +static struct lsm_id smack_lsmid __lsm_ro_after_init = { + .lsm = "smack", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), @@ -4784,7 +4789,7 @@ static __init int smack_init(void) /* * Register with LSM */ - security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); + security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), &smack_lsmid); smack_enabled = 1; pr_info("Smack: Initializing.\n"); diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 716c92ec941a..f1968e80f06d 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -529,6 +529,11 @@ static void tomoyo_task_free(struct task_struct *task) } } +static struct lsm_id tomoyo_lsmid __lsm_ro_after_init = { + .lsm = "tomoyo", + .slot = LSMBLOB_NOT_NEEDED +}; + /* * tomoyo_security_ops is a "struct security_operations" which is used for * registering TOMOYO. @@ -581,7 +586,8 @@ static int __init tomoyo_init(void) struct tomoyo_task *s = tomoyo_task(current); /* register ourselves with the security framework */ - security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); + security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), + &tomoyo_lsmid); pr_info("TOMOYO Linux initialized\n"); s->domain_info = &tomoyo_kernel_domain; atomic_inc(&tomoyo_kernel_domain.users); diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 94dc346370b1..0f0cf7136929 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -421,6 +421,11 @@ static int yama_ptrace_traceme(struct task_struct *parent) return rc; } +static struct lsm_id yama_lsmid __lsm_ro_after_init = { + .lsm = "yama", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list yama_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), @@ -477,7 +482,7 @@ static inline void yama_init_sysctl(void) { } static int __init yama_init(void) { pr_info("Yama: becoming mindful.\n"); - security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama"); + security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), &yama_lsmid); yama_init_sysctl(); return 0; } -- 2.20.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure. 2019-11-13 18:19 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Casey Schaufler @ 2019-11-21 18:40 ` John Johansen 0 siblings, 0 replies; 6+ messages in thread From: John Johansen @ 2019-11-21 18:40 UTC (permalink / raw) To: Casey Schaufler, casey.schaufler, jmorris, linux-security-module, selinux Cc: keescook, penguin-kernel, paul, sds On 11/13/19 10:19 AM, Casey Schaufler wrote: > When more than one security module is exporting data to > audit and networking sub-systems a single 32 bit integer > is no longer sufficient to represent the data. Add a > structure to be used instead. > > The lsmblob structure is currently an array of > u32 "secids". There is an entry for each of the > security modules built into the system that would > use secids if active. The system assigns the module > a "slot" when it registers hooks. If modules are > compiled in but not registered there will be unused > slots. > > A new lsm_id structure, which contains the name > of the LSM and its slot number, is created. There > is an instance for each LSM, which assigns the name > and passes it to the infrastructure to set the slot. > > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> reviewed and Acked-by: John Johansen <john.johansen@canonical.com> > --- > include/linux/lsm_hooks.h | 12 ++++++-- > include/linux/security.h | 58 ++++++++++++++++++++++++++++++++++++++ > security/apparmor/lsm.c | 7 ++++- > security/commoncap.c | 7 ++++- > security/loadpin/loadpin.c | 8 +++++- > security/safesetid/lsm.c | 8 +++++- > security/security.c | 28 ++++++++++++++---- > security/selinux/hooks.c | 8 +++++- > security/smack/smack_lsm.c | 7 ++++- > security/tomoyo/tomoyo.c | 8 +++++- > security/yama/yama_lsm.c | 7 ++++- > 11 files changed, 142 insertions(+), 16 deletions(-) > > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h > index 13a67fd1a767..cfe5393840c7 100644 > --- a/include/linux/lsm_hooks.h > +++ b/include/linux/lsm_hooks.h > @@ -2062,6 +2062,14 @@ struct security_hook_heads { > struct hlist_head locked_down; > } __randomize_layout; > > +/* > + * Information that identifies a security module. > + */ > +struct lsm_id { > + const char *lsm; /* Name of the LSM */ > + int slot; /* Slot in lsmblob if one is allocated */ > +}; > + > /* > * Security module hook list structure. > * For use with generic list macros for common operations. > @@ -2070,7 +2078,7 @@ struct security_hook_list { > struct hlist_node list; > struct hlist_head *head; > union security_list_options hook; > - char *lsm; > + struct lsm_id *lsmid; > } __randomize_layout; > > /* > @@ -2099,7 +2107,7 @@ extern struct security_hook_heads security_hook_heads; > extern char *lsm_names; > > extern void security_add_hooks(struct security_hook_list *hooks, int count, > - char *lsm); > + struct lsm_id *lsmid); > > #define LSM_FLAG_LEGACY_MAJOR BIT(0) > #define LSM_FLAG_EXCLUSIVE BIT(1) > diff --git a/include/linux/security.h b/include/linux/security.h > index 9df7547afc0c..5eced28fa0c9 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -126,6 +126,64 @@ enum lockdown_reason { > LOCKDOWN_CONFIDENTIALITY_MAX, > }; > > +/* > + * Data exported by the security modules > + * > + * Any LSM that provides secid or secctx based hooks must be included. > + */ > +#define LSMBLOB_ENTRIES ( \ > + (IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \ > + (IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \ > + (IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0)) > + > +struct lsmblob { > + u32 secid[LSMBLOB_ENTRIES]; > +}; > + > +#define LSMBLOB_INVALID -1 /* Not a valid LSM slot number */ > +#define LSMBLOB_NEEDED -2 /* Slot requested on initialization */ > +#define LSMBLOB_NOT_NEEDED -3 /* Slot not requested */ > + > +/** > + * lsmblob_init - initialize an lsmblob structure. > + * @blob: Pointer to the data to initialize > + * @secid: The initial secid value > + * > + * Set all secid for all modules to the specified value. > + */ > +static inline void lsmblob_init(struct lsmblob *blob, u32 secid) > +{ > + int i; > + > + for (i = 0; i < LSMBLOB_ENTRIES; i++) > + blob->secid[i] = secid; > +} > + > +/** > + * lsmblob_is_set - report if there is an value in the lsmblob > + * @blob: Pointer to the exported LSM data > + * > + * Returns true if there is a secid set, false otherwise > + */ > +static inline bool lsmblob_is_set(struct lsmblob *blob) > +{ > + struct lsmblob empty = {}; > + > + return !!memcmp(blob, &empty, sizeof(*blob)); > +} > + > +/** > + * lsmblob_equal - report if the two lsmblob's are equal > + * @bloba: Pointer to one LSM data > + * @blobb: Pointer to the other LSM data > + * > + * Returns true if all entries in the two are equal, false otherwise > + */ > +static inline bool lsmblob_equal(struct lsmblob *bloba, struct lsmblob *blobb) > +{ > + return !memcmp(bloba, blobb, sizeof(*bloba)); > +} > + > /* These functions are in security/commoncap.c */ > extern int cap_capable(const struct cred *cred, struct user_namespace *ns, > int cap, unsigned int opts); > diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c > index 4093fa231671..11845348eefb 100644 > --- a/security/apparmor/lsm.c > +++ b/security/apparmor/lsm.c > @@ -1134,6 +1134,11 @@ struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { > .lbs_sock = sizeof(struct aa_sk_ctx), > }; > > +static struct lsm_id apparmor_lsmid __lsm_ro_after_init = { > + .lsm = "apparmor", > + .slot = LSMBLOB_NEEDED > +}; > + > static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { > LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), > LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), > @@ -1722,7 +1727,7 @@ static int __init apparmor_init(void) > goto buffers_out; > } > security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks), > - "apparmor"); > + &apparmor_lsmid); > > /* Report that AppArmor successfully initialized */ > apparmor_initialized = 1; > diff --git a/security/commoncap.c b/security/commoncap.c > index f4ee0ae106b2..9dcfd2a0e891 100644 > --- a/security/commoncap.c > +++ b/security/commoncap.c > @@ -1339,6 +1339,11 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, > > #ifdef CONFIG_SECURITY > > +static struct lsm_id capability_lsmid __lsm_ro_after_init = { > + .lsm = "capability", > + .slot = LSMBLOB_NOT_NEEDED > +}; > + > static struct security_hook_list capability_hooks[] __lsm_ro_after_init = { > LSM_HOOK_INIT(capable, cap_capable), > LSM_HOOK_INIT(settime, cap_settime), > @@ -1363,7 +1368,7 @@ static struct security_hook_list capability_hooks[] __lsm_ro_after_init = { > static int __init capability_init(void) > { > security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks), > - "capability"); > + &capability_lsmid); > return 0; > } > > diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c > index ee5cb944f4ad..86317e78899f 100644 > --- a/security/loadpin/loadpin.c > +++ b/security/loadpin/loadpin.c > @@ -180,6 +180,11 @@ static int loadpin_load_data(enum kernel_load_data_id id) > return loadpin_read_file(NULL, (enum kernel_read_file_id) id); > } > > +static struct lsm_id loadpin_lsmid __lsm_ro_after_init = { > + .lsm = "loadpin", > + .slot = LSMBLOB_NOT_NEEDED > +}; > + > static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { > LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), > LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), > @@ -227,7 +232,8 @@ static int __init loadpin_init(void) > pr_info("ready to pin (currently %senforcing)\n", > enforce ? "" : "not "); > parse_exclude(); > - security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); > + security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), > + &loadpin_lsmid); > return 0; > } > > diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c > index 7760019ad35d..950dfb7f931e 100644 > --- a/security/safesetid/lsm.c > +++ b/security/safesetid/lsm.c > @@ -149,6 +149,11 @@ static int safesetid_task_fix_setuid(struct cred *new, > return -EACCES; > } > > +static struct lsm_id safesetid_lsmid __lsm_ro_after_init = { > + .lsm = "safesetid", > + .slot = LSMBLOB_NOT_NEEDED > +}; > + > static struct security_hook_list safesetid_security_hooks[] = { > LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid), > LSM_HOOK_INIT(capable, safesetid_security_capable) > @@ -157,7 +162,8 @@ static struct security_hook_list safesetid_security_hooks[] = { > static int __init safesetid_security_init(void) > { > security_add_hooks(safesetid_security_hooks, > - ARRAY_SIZE(safesetid_security_hooks), "safesetid"); > + ARRAY_SIZE(safesetid_security_hooks), > + &safesetid_lsmid); > > /* Report that SafeSetID successfully initialized */ > safesetid_initialized = 1; > diff --git a/security/security.c b/security/security.c > index 5e43d3f64c1f..5f503cadf7f3 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -308,6 +308,7 @@ static void __init ordered_lsm_init(void) > init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); > init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); > init_debug("task blob size = %d\n", blob_sizes.lbs_task); > + init_debug("lsmblob size = %lu\n", sizeof(struct lsmblob)); > > /* > * Create any kmem_caches needed for blobs > @@ -435,21 +436,36 @@ static int lsm_append(const char *new, char **result) > return 0; > } > > +/* > + * Current index to use while initializing the lsmblob secid list. > + */ > +static int lsm_slot __initdata; > + > /** > * security_add_hooks - Add a modules hooks to the hook lists. > * @hooks: the hooks to add > * @count: the number of hooks to add > - * @lsm: the name of the security module > + * @lsmid: the the identification information for the security module > * > * Each LSM has to register its hooks with the infrastructure. > + * If the LSM is using hooks that export secids allocate a slot > + * for it in the lsmblob. > */ > void __init security_add_hooks(struct security_hook_list *hooks, int count, > - char *lsm) > + struct lsm_id *lsmid) > { > int i; > > + if (lsmid->slot == LSMBLOB_NEEDED) { > + if (lsm_slot >= LSMBLOB_ENTRIES) > + panic("%s Too many LSMs registered.\n", __func__); > + lsmid->slot = lsm_slot++; > + init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm, > + lsmid->slot); > + } > + > for (i = 0; i < count; i++) { > - hooks[i].lsm = lsm; > + hooks[i].lsmid = lsmid; > hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); > } > > @@ -458,7 +474,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, > * and fix this up afterwards. > */ > if (slab_is_available()) { > - if (lsm_append(lsm, &lsm_names) < 0) > + if (lsm_append(lsmid->lsm, &lsm_names) < 0) > panic("%s - Cannot get early memory.\n", __func__); > } > } > @@ -1906,7 +1922,7 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name, > struct security_hook_list *hp; > > hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { > - if (lsm != NULL && strcmp(lsm, hp->lsm)) > + if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) > continue; > return hp->hook.getprocattr(p, name, value); > } > @@ -1919,7 +1935,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value, > struct security_hook_list *hp; > > hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { > - if (lsm != NULL && strcmp(lsm, hp->lsm)) > + if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) > continue; > return hp->hook.setprocattr(name, value, size); > } > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c > index 3feb971068e2..5570a6ed49d5 100644 > --- a/security/selinux/hooks.c > +++ b/security/selinux/hooks.c > @@ -6791,6 +6791,11 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = { > .lbs_sock = sizeof(struct sk_security_struct), > }; > > +static struct lsm_id selinux_lsmid __lsm_ro_after_init = { > + .lsm = "selinux", > + .slot = LSMBLOB_NEEDED > +}; > + > static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { > LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), > LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), > @@ -7051,7 +7056,8 @@ static __init int selinux_init(void) > > hashtab_cache_init(); > > - security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); > + security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), > + &selinux_lsmid); > > if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) > panic("SELinux: Unable to register AVC netcache callback\n"); > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c > index 796f78580c17..e42336328446 100644 > --- a/security/smack/smack_lsm.c > +++ b/security/smack/smack_lsm.c > @@ -4586,6 +4586,11 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { > .lbs_sock = sizeof(struct socket_smack), > }; > > +static struct lsm_id smack_lsmid __lsm_ro_after_init = { > + .lsm = "smack", > + .slot = LSMBLOB_NEEDED > +}; > + > static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { > LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), > LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), > @@ -4784,7 +4789,7 @@ static __init int smack_init(void) > /* > * Register with LSM > */ > - security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); > + security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), &smack_lsmid); > smack_enabled = 1; > > pr_info("Smack: Initializing.\n"); > diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c > index 716c92ec941a..f1968e80f06d 100644 > --- a/security/tomoyo/tomoyo.c > +++ b/security/tomoyo/tomoyo.c > @@ -529,6 +529,11 @@ static void tomoyo_task_free(struct task_struct *task) > } > } > > +static struct lsm_id tomoyo_lsmid __lsm_ro_after_init = { > + .lsm = "tomoyo", > + .slot = LSMBLOB_NOT_NEEDED > +}; > + > /* > * tomoyo_security_ops is a "struct security_operations" which is used for > * registering TOMOYO. > @@ -581,7 +586,8 @@ static int __init tomoyo_init(void) > struct tomoyo_task *s = tomoyo_task(current); > > /* register ourselves with the security framework */ > - security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); > + security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), > + &tomoyo_lsmid); > pr_info("TOMOYO Linux initialized\n"); > s->domain_info = &tomoyo_kernel_domain; > atomic_inc(&tomoyo_kernel_domain.users); > diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c > index 94dc346370b1..0f0cf7136929 100644 > --- a/security/yama/yama_lsm.c > +++ b/security/yama/yama_lsm.c > @@ -421,6 +421,11 @@ static int yama_ptrace_traceme(struct task_struct *parent) > return rc; > } > > +static struct lsm_id yama_lsmid __lsm_ro_after_init = { > + .lsm = "yama", > + .slot = LSMBLOB_NOT_NEEDED > +}; > + > static struct security_hook_list yama_hooks[] __lsm_ro_after_init = { > LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), > LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), > @@ -477,7 +482,7 @@ static inline void yama_init_sysctl(void) { } > static int __init yama_init(void) > { > pr_info("Yama: becoming mindful.\n"); > - security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama"); > + security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), &yama_lsmid); > yama_init_sysctl(); > return 0; > } > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v11 00/25] LSM: Module stacking for AppArmor @ 2019-11-13 17:56 Casey Schaufler 2019-11-13 17:56 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Casey Schaufler 0 siblings, 1 reply; 6+ messages in thread From: Casey Schaufler @ 2019-11-13 17:56 UTC (permalink / raw) To: casey.schaufler, jmorris, linux-security-module, selinux Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds Apologies for the multiple copies. Issues on the ISP end. This patchset provides the changes required for the AppArmor security module to stack safely with any other. v11: Rebase to 5.4-rc6 Incorporate feedback from v10 - Disambiguate reading /proc/.../attr/display by restricting all use of the interface to the current process. - Fix a merge error in AppArmor's display attribute check v10: Ask the security modules if the display can be changed. v9: There is no version 9 v8: Incorporate feedback from v7 - Minor clean-up in display value management - refactor "compound" context creation to use a common append_ctx() function. v7: Incorporate feedback from v6 - Make setting the display a privileged operation. The availability of compound contexts reduces the need for setting the display. v6: Incorporate feedback from v5 - Add subj_<lsm>= and obj_<lsm>= fields to audit records - Add /proc/.../attr/context to get the full context in lsmname\0value\0... format as suggested by Simon McVittie - Add SO_PEERCONTEXT for getsockopt() to get the full context in the same format, also suggested by Simon McVittie. - Add /sys/kernel/security/lsm_display_default to provide the display default value. v5: Incorporate feedback from v4 - Initialize the lsmcontext in security_secid_to_secctx() - Clear the lsmcontext in all security_release_secctx() cases - Don't use the "display" on strictly internal context interfaces. - The SELinux binder hooks check for cases where the context "display" isn't compatible with SELinux. v4: Incorporate feedback from v3 - Mark new lsm_<blob>_alloc functions static - Replace the lsm and slot fields of the security_hook_list with a pointer to a LSM allocated lsm_id structure. The LSM identifies if it needs a slot explicitly. Use the lsm_id rather than make security_add_hooks return the slot value. - Validate slot values used in security.c - Reworked the "display" process attribute handling so that it works right and doesn't use goofy list processing. - fix display value check in dentry_init_security - Replace audit_log of secids with '?' instead of deleting the audit log v3: Incorporate feedback from v2 - Make lsmblob parameter and variable names more meaningful, changing "le" and "l" to "blob". - Improve consistency of constant naming. - Do more sanity checking during LSM initialization. - Be a bit clearer about what is temporary scaffolding. - Rather than clutter security_getpeersec_dgram with otherwise unnecessary checks remove the apparmor stub, which does nothing useful. Patche 0001 moves management of the sock security blob from the individual modules to the infrastructure. Patches 0002-0012 replace system use of a "secid" with a structure "lsmblob" containing information from the security modules to be held and reused later. At this point lsmblob contains an array of u32 secids, one "slot" for each of the security modules compiled into the kernel that used secids. A "slot" is allocated when a security module requests one. The infrastructure is changed to use the slot number to pass the correct secid to or from the security module hooks. It is important that the lsmblob be a fixed size entity that does not have to be allocated. Several of the places where it is used would have performance and/or locking issues with dynamic allocation. Patch 0013 provides a mechanism for a process to identify which security module's hooks should be used when displaying or converting a security context string. A new interface /proc/self/attr/display contains the name of the security module to show. Reading from this file will present the name of the module, while writing to it will set the value. Only names of active security modules are accepted. Internally, the name is translated to the appropriate "slot" number for the module which is then stored in the task security blob. Setting the display requires that all modules using the /proc interfaces allow the transition. The "display" of other processess can be neither read nor written. All suggested cases for reading the display of a different process have race conditions. Patch 0014 Starts the process of changing how a security context is represented. Since it is possible for a security context to have been generated by more than one security module it is now necessary to note which module created a security context so that the correct "release" hook can be called. There are several places where the module that created a security context cannot be inferred. This is achieved by introducing a "lsmcontext" structure which contains the context string, its length and the "slot" number of the security module that created it. The security_release_secctx() interface is changed, replacing the (string,len) pointer pair with a lsmcontext pointer. Patches 0015-0017 convert the security interfaces from (string,len) pointer pairs to a lsmcontext pointer. The slot number identifying the creating module is added by the infrastructure. Where the security context is stored for extended periods the data type is changed. The Netlabel code is converted to save lsmblob structures instead of secids in Patches 0018-0019. Patch 0020 adds checks to the binder hooks which verify that if both ends of a transaction use the same "display". Patches 0021-0022 add addition data to the audit records to identify the LSM specific data for all active modules. Patches 0023-0024 add new interfaces for getting the compound security contexts. Finally, with all interference on the AppArmor hooks removed, Patch 0025 removes the exclusive bit from AppArmor. An unnecessary stub hook was also removed. The Ubuntu project is using an earlier version of this patchset in their distribution to enable stacking for containers. Performance measurements to date have the change within the "noise". The sockperf and dbench results are on the order of 0.2% to 0.8% difference, with better performance being as common as worse. The benchmarks were run with AppArmor and Smack on Ubuntu. https://github.com/cschaufler/lsm-stacking.git#stack-5.4-rc6-v11-apparmor Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- arch/alpha/include/uapi/asm/socket.h | 1 + arch/mips/include/uapi/asm/socket.h | 1 + arch/parisc/include/uapi/asm/socket.h | 1 + arch/sparc/include/uapi/asm/socket.h | 1 + drivers/android/binder.c | 26 +- fs/ceph/xattr.c | 6 +- fs/nfs/nfs4proc.c | 22 +- fs/nfsd/nfs4xdr.c | 20 +- fs/proc/base.c | 2 + include/linux/audit.h | 1 + include/linux/cred.h | 3 +- include/linux/lsm_hooks.h | 37 +- include/linux/security.h | 175 ++++++++-- include/net/af_unix.h | 2 +- include/net/netlabel.h | 8 +- include/net/scm.h | 15 +- include/uapi/asm-generic/socket.h | 1 + kernel/audit.c | 72 +++- kernel/audit.h | 9 +- kernel/audit_fsnotify.c | 1 + kernel/auditfilter.c | 10 +- kernel/auditsc.c | 127 ++++--- kernel/cred.c | 12 +- net/core/sock.c | 7 +- net/ipv4/cipso_ipv4.c | 6 +- net/ipv4/ip_sockglue.c | 12 +- net/netfilter/nf_conntrack_netlink.c | 20 +- net/netfilter/nf_conntrack_standalone.c | 11 +- net/netfilter/nfnetlink_queue.c | 26 +- net/netfilter/nft_meta.c | 13 +- net/netfilter/xt_SECMARK.c | 5 +- net/netlabel/netlabel_kapi.c | 6 +- net/netlabel/netlabel_unlabeled.c | 97 +++--- net/netlabel/netlabel_unlabeled.h | 2 +- net/netlabel/netlabel_user.c | 13 +- net/netlabel/netlabel_user.h | 6 +- net/unix/af_unix.c | 6 +- net/xfrm/xfrm_policy.c | 2 + net/xfrm/xfrm_state.c | 2 + security/apparmor/include/apparmor.h | 3 +- security/apparmor/include/net.h | 6 +- security/apparmor/lsm.c | 117 +++---- security/commoncap.c | 7 +- security/integrity/ima/ima.h | 15 +- security/integrity/ima/ima_api.c | 11 +- security/integrity/ima/ima_appraise.c | 6 +- security/integrity/ima/ima_main.c | 49 +-- security/integrity/ima/ima_policy.c | 19 +- security/integrity/integrity_audit.c | 1 + security/loadpin/loadpin.c | 8 +- security/safesetid/lsm.c | 8 +- security/security.c | 593 +++++++++++++++++++++++++++++--- security/selinux/hooks.c | 109 +++--- security/selinux/include/classmap.h | 2 +- security/selinux/include/objsec.h | 5 + security/selinux/include/security.h | 1 + security/selinux/netlabel.c | 25 +- security/selinux/ss/services.c | 4 +- security/smack/smack.h | 6 + security/smack/smack_lsm.c | 124 ++++--- security/smack/smack_netfilter.c | 8 +- security/smack/smackfs.c | 10 +- security/tomoyo/tomoyo.c | 8 +- security/yama/yama_lsm.c | 7 +- 64 files changed, 1376 insertions(+), 563 deletions(-) ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure. 2019-11-13 17:56 [PATCH v11 00/25] LSM: Module stacking for AppArmor Casey Schaufler @ 2019-11-13 17:56 ` Casey Schaufler 2019-11-21 5:36 ` James Morris 0 siblings, 1 reply; 6+ messages in thread From: Casey Schaufler @ 2019-11-13 17:56 UTC (permalink / raw) To: casey.schaufler, jmorris, linux-security-module, selinux Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds When more than one security module is exporting data to audit and networking sub-systems a single 32 bit integer is no longer sufficient to represent the data. Add a structure to be used instead. The lsmblob structure is currently an array of u32 "secids". There is an entry for each of the security modules built into the system that would use secids if active. The system assigns the module a "slot" when it registers hooks. If modules are compiled in but not registered there will be unused slots. A new lsm_id structure, which contains the name of the LSM and its slot number, is created. There is an instance for each LSM, which assigns the name and passes it to the infrastructure to set the slot. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/lsm_hooks.h | 12 ++++++-- include/linux/security.h | 58 ++++++++++++++++++++++++++++++++++++++ security/apparmor/lsm.c | 7 ++++- security/commoncap.c | 7 ++++- security/loadpin/loadpin.c | 8 +++++- security/safesetid/lsm.c | 8 +++++- security/security.c | 28 ++++++++++++++---- security/selinux/hooks.c | 8 +++++- security/smack/smack_lsm.c | 7 ++++- security/tomoyo/tomoyo.c | 8 +++++- security/yama/yama_lsm.c | 7 ++++- 11 files changed, 142 insertions(+), 16 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 13a67fd1a767..cfe5393840c7 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -2062,6 +2062,14 @@ struct security_hook_heads { struct hlist_head locked_down; } __randomize_layout; +/* + * Information that identifies a security module. + */ +struct lsm_id { + const char *lsm; /* Name of the LSM */ + int slot; /* Slot in lsmblob if one is allocated */ +}; + /* * Security module hook list structure. * For use with generic list macros for common operations. @@ -2070,7 +2078,7 @@ struct security_hook_list { struct hlist_node list; struct hlist_head *head; union security_list_options hook; - char *lsm; + struct lsm_id *lsmid; } __randomize_layout; /* @@ -2099,7 +2107,7 @@ extern struct security_hook_heads security_hook_heads; extern char *lsm_names; extern void security_add_hooks(struct security_hook_list *hooks, int count, - char *lsm); + struct lsm_id *lsmid); #define LSM_FLAG_LEGACY_MAJOR BIT(0) #define LSM_FLAG_EXCLUSIVE BIT(1) diff --git a/include/linux/security.h b/include/linux/security.h index 9df7547afc0c..5eced28fa0c9 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -126,6 +126,64 @@ enum lockdown_reason { LOCKDOWN_CONFIDENTIALITY_MAX, }; +/* + * Data exported by the security modules + * + * Any LSM that provides secid or secctx based hooks must be included. + */ +#define LSMBLOB_ENTRIES ( \ + (IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0)) + +struct lsmblob { + u32 secid[LSMBLOB_ENTRIES]; +}; + +#define LSMBLOB_INVALID -1 /* Not a valid LSM slot number */ +#define LSMBLOB_NEEDED -2 /* Slot requested on initialization */ +#define LSMBLOB_NOT_NEEDED -3 /* Slot not requested */ + +/** + * lsmblob_init - initialize an lsmblob structure. + * @blob: Pointer to the data to initialize + * @secid: The initial secid value + * + * Set all secid for all modules to the specified value. + */ +static inline void lsmblob_init(struct lsmblob *blob, u32 secid) +{ + int i; + + for (i = 0; i < LSMBLOB_ENTRIES; i++) + blob->secid[i] = secid; +} + +/** + * lsmblob_is_set - report if there is an value in the lsmblob + * @blob: Pointer to the exported LSM data + * + * Returns true if there is a secid set, false otherwise + */ +static inline bool lsmblob_is_set(struct lsmblob *blob) +{ + struct lsmblob empty = {}; + + return !!memcmp(blob, &empty, sizeof(*blob)); +} + +/** + * lsmblob_equal - report if the two lsmblob's are equal + * @bloba: Pointer to one LSM data + * @blobb: Pointer to the other LSM data + * + * Returns true if all entries in the two are equal, false otherwise + */ +static inline bool lsmblob_equal(struct lsmblob *bloba, struct lsmblob *blobb) +{ + return !memcmp(bloba, blobb, sizeof(*bloba)); +} + /* These functions are in security/commoncap.c */ extern int cap_capable(const struct cred *cred, struct user_namespace *ns, int cap, unsigned int opts); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 4093fa231671..11845348eefb 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1134,6 +1134,11 @@ struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct aa_sk_ctx), }; +static struct lsm_id apparmor_lsmid __lsm_ro_after_init = { + .lsm = "apparmor", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), @@ -1722,7 +1727,7 @@ static int __init apparmor_init(void) goto buffers_out; } security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks), - "apparmor"); + &apparmor_lsmid); /* Report that AppArmor successfully initialized */ apparmor_initialized = 1; diff --git a/security/commoncap.c b/security/commoncap.c index f4ee0ae106b2..9dcfd2a0e891 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -1339,6 +1339,11 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, #ifdef CONFIG_SECURITY +static struct lsm_id capability_lsmid __lsm_ro_after_init = { + .lsm = "capability", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list capability_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(capable, cap_capable), LSM_HOOK_INIT(settime, cap_settime), @@ -1363,7 +1368,7 @@ static struct security_hook_list capability_hooks[] __lsm_ro_after_init = { static int __init capability_init(void) { security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks), - "capability"); + &capability_lsmid); return 0; } diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index ee5cb944f4ad..86317e78899f 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c @@ -180,6 +180,11 @@ static int loadpin_load_data(enum kernel_load_data_id id) return loadpin_read_file(NULL, (enum kernel_read_file_id) id); } +static struct lsm_id loadpin_lsmid __lsm_ro_after_init = { + .lsm = "loadpin", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), @@ -227,7 +232,8 @@ static int __init loadpin_init(void) pr_info("ready to pin (currently %senforcing)\n", enforce ? "" : "not "); parse_exclude(); - security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); + security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), + &loadpin_lsmid); return 0; } diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c index 7760019ad35d..950dfb7f931e 100644 --- a/security/safesetid/lsm.c +++ b/security/safesetid/lsm.c @@ -149,6 +149,11 @@ static int safesetid_task_fix_setuid(struct cred *new, return -EACCES; } +static struct lsm_id safesetid_lsmid __lsm_ro_after_init = { + .lsm = "safesetid", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list safesetid_security_hooks[] = { LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid), LSM_HOOK_INIT(capable, safesetid_security_capable) @@ -157,7 +162,8 @@ static struct security_hook_list safesetid_security_hooks[] = { static int __init safesetid_security_init(void) { security_add_hooks(safesetid_security_hooks, - ARRAY_SIZE(safesetid_security_hooks), "safesetid"); + ARRAY_SIZE(safesetid_security_hooks), + &safesetid_lsmid); /* Report that SafeSetID successfully initialized */ safesetid_initialized = 1; diff --git a/security/security.c b/security/security.c index 5e43d3f64c1f..5f503cadf7f3 100644 --- a/security/security.c +++ b/security/security.c @@ -308,6 +308,7 @@ static void __init ordered_lsm_init(void) init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); init_debug("task blob size = %d\n", blob_sizes.lbs_task); + init_debug("lsmblob size = %lu\n", sizeof(struct lsmblob)); /* * Create any kmem_caches needed for blobs @@ -435,21 +436,36 @@ static int lsm_append(const char *new, char **result) return 0; } +/* + * Current index to use while initializing the lsmblob secid list. + */ +static int lsm_slot __initdata; + /** * security_add_hooks - Add a modules hooks to the hook lists. * @hooks: the hooks to add * @count: the number of hooks to add - * @lsm: the name of the security module + * @lsmid: the the identification information for the security module * * Each LSM has to register its hooks with the infrastructure. + * If the LSM is using hooks that export secids allocate a slot + * for it in the lsmblob. */ void __init security_add_hooks(struct security_hook_list *hooks, int count, - char *lsm) + struct lsm_id *lsmid) { int i; + if (lsmid->slot == LSMBLOB_NEEDED) { + if (lsm_slot >= LSMBLOB_ENTRIES) + panic("%s Too many LSMs registered.\n", __func__); + lsmid->slot = lsm_slot++; + init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm, + lsmid->slot); + } + for (i = 0; i < count; i++) { - hooks[i].lsm = lsm; + hooks[i].lsmid = lsmid; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); } @@ -458,7 +474,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, * and fix this up afterwards. */ if (slab_is_available()) { - if (lsm_append(lsm, &lsm_names) < 0) + if (lsm_append(lsmid->lsm, &lsm_names) < 0) panic("%s - Cannot get early memory.\n", __func__); } } @@ -1906,7 +1922,7 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name, struct security_hook_list *hp; hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { - if (lsm != NULL && strcmp(lsm, hp->lsm)) + if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; return hp->hook.getprocattr(p, name, value); } @@ -1919,7 +1935,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value, struct security_hook_list *hp; hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { - if (lsm != NULL && strcmp(lsm, hp->lsm)) + if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; return hp->hook.setprocattr(name, value, size); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3feb971068e2..5570a6ed49d5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6791,6 +6791,11 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct sk_security_struct), }; +static struct lsm_id selinux_lsmid __lsm_ro_after_init = { + .lsm = "selinux", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), @@ -7051,7 +7056,8 @@ static __init int selinux_init(void) hashtab_cache_init(); - security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); + security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), + &selinux_lsmid); if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) panic("SELinux: Unable to register AVC netcache callback\n"); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 796f78580c17..e42336328446 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4586,6 +4586,11 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct socket_smack), }; +static struct lsm_id smack_lsmid __lsm_ro_after_init = { + .lsm = "smack", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), @@ -4784,7 +4789,7 @@ static __init int smack_init(void) /* * Register with LSM */ - security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); + security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), &smack_lsmid); smack_enabled = 1; pr_info("Smack: Initializing.\n"); diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 716c92ec941a..f1968e80f06d 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -529,6 +529,11 @@ static void tomoyo_task_free(struct task_struct *task) } } +static struct lsm_id tomoyo_lsmid __lsm_ro_after_init = { + .lsm = "tomoyo", + .slot = LSMBLOB_NOT_NEEDED +}; + /* * tomoyo_security_ops is a "struct security_operations" which is used for * registering TOMOYO. @@ -581,7 +586,8 @@ static int __init tomoyo_init(void) struct tomoyo_task *s = tomoyo_task(current); /* register ourselves with the security framework */ - security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); + security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), + &tomoyo_lsmid); pr_info("TOMOYO Linux initialized\n"); s->domain_info = &tomoyo_kernel_domain; atomic_inc(&tomoyo_kernel_domain.users); diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 94dc346370b1..0f0cf7136929 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -421,6 +421,11 @@ static int yama_ptrace_traceme(struct task_struct *parent) return rc; } +static struct lsm_id yama_lsmid __lsm_ro_after_init = { + .lsm = "yama", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list yama_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), @@ -477,7 +482,7 @@ static inline void yama_init_sysctl(void) { } static int __init yama_init(void) { pr_info("Yama: becoming mindful.\n"); - security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama"); + security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), &yama_lsmid); yama_init_sysctl(); return 0; } -- 2.20.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure. 2019-11-13 17:56 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Casey Schaufler @ 2019-11-21 5:36 ` James Morris 0 siblings, 0 replies; 6+ messages in thread From: James Morris @ 2019-11-21 5:36 UTC (permalink / raw) To: Casey Schaufler Cc: casey.schaufler, linux-security-module, selinux, keescook, john.johansen, penguin-kernel, paul, sds On Wed, 13 Nov 2019, Casey Schaufler wrote: > A new lsm_id structure, which contains the name > of the LSM and its slot number, is created. There > is an instance for each LSM, which assigns the name > and passes it to the infrastructure to set the slot. > > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Hi Casey, Note that LSM infrastructure changes will need signoffs from the maintainers of all major LSMs. See https://lore.kernel.org/linux-security-module/alpine.LRH.2.21.1909060644570.1710@namei.org/ I've set aside some time at the end of this week to take a close look. -- James Morris <jmorris@namei.org> ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v11 00/25] LSM: Module stacking for AppArmor @ 2019-11-13 16:50 Casey Schaufler 2019-11-13 16:50 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Casey Schaufler 0 siblings, 1 reply; 6+ messages in thread From: Casey Schaufler @ 2019-11-13 16:50 UTC (permalink / raw) To: casey.schaufler, jmorris, linux-security-module, selinux Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds This patchset provides the changes required for the AppArmor security module to stack safely with any other. v11: Rebase to 5.4-rc6 Incorporate feedback from v10 - Disambiguate reading /proc/.../attr/display by restricting all use of the interface to the current process. - Fix a merge error in AppArmor's display attribute check v10: Ask the security modules if the display can be changed. v9: There is no version 9 v8: Incorporate feedback from v7 - Minor clean-up in display value management - refactor "compound" context creation to use a common append_ctx() function. v7: Incorporate feedback from v6 - Make setting the display a privileged operation. The availability of compound contexts reduces the need for setting the display. v6: Incorporate feedback from v5 - Add subj_<lsm>= and obj_<lsm>= fields to audit records - Add /proc/.../attr/context to get the full context in lsmname\0value\0... format as suggested by Simon McVittie - Add SO_PEERCONTEXT for getsockopt() to get the full context in the same format, also suggested by Simon McVittie. - Add /sys/kernel/security/lsm_display_default to provide the display default value. v5: Incorporate feedback from v4 - Initialize the lsmcontext in security_secid_to_secctx() - Clear the lsmcontext in all security_release_secctx() cases - Don't use the "display" on strictly internal context interfaces. - The SELinux binder hooks check for cases where the context "display" isn't compatible with SELinux. v4: Incorporate feedback from v3 - Mark new lsm_<blob>_alloc functions static - Replace the lsm and slot fields of the security_hook_list with a pointer to a LSM allocated lsm_id structure. The LSM identifies if it needs a slot explicitly. Use the lsm_id rather than make security_add_hooks return the slot value. - Validate slot values used in security.c - Reworked the "display" process attribute handling so that it works right and doesn't use goofy list processing. - fix display value check in dentry_init_security - Replace audit_log of secids with '?' instead of deleting the audit log v3: Incorporate feedback from v2 - Make lsmblob parameter and variable names more meaningful, changing "le" and "l" to "blob". - Improve consistency of constant naming. - Do more sanity checking during LSM initialization. - Be a bit clearer about what is temporary scaffolding. - Rather than clutter security_getpeersec_dgram with otherwise unnecessary checks remove the apparmor stub, which does nothing useful. Patche 0001 moves management of the sock security blob from the individual modules to the infrastructure. Patches 0002-0012 replace system use of a "secid" with a structure "lsmblob" containing information from the security modules to be held and reused later. At this point lsmblob contains an array of u32 secids, one "slot" for each of the security modules compiled into the kernel that used secids. A "slot" is allocated when a security module requests one. The infrastructure is changed to use the slot number to pass the correct secid to or from the security module hooks. It is important that the lsmblob be a fixed size entity that does not have to be allocated. Several of the places where it is used would have performance and/or locking issues with dynamic allocation. Patch 0013 provides a mechanism for a process to identify which security module's hooks should be used when displaying or converting a security context string. A new interface /proc/self/attr/display contains the name of the security module to show. Reading from this file will present the name of the module, while writing to it will set the value. Only names of active security modules are accepted. Internally, the name is translated to the appropriate "slot" number for the module which is then stored in the task security blob. Setting the display requires that all modules using the /proc interfaces allow the transition. The "display" of other processess can be neither read nor written. All suggested cases for reading the display of a different process have race conditions. Patch 0014 Starts the process of changing how a security context is represented. Since it is possible for a security context to have been generated by more than one security module it is now necessary to note which module created a security context so that the correct "release" hook can be called. There are several places where the module that created a security context cannot be inferred. This is achieved by introducing a "lsmcontext" structure which contains the context string, its length and the "slot" number of the security module that created it. The security_release_secctx() interface is changed, replacing the (string,len) pointer pair with a lsmcontext pointer. Patches 0015-0017 convert the security interfaces from (string,len) pointer pairs to a lsmcontext pointer. The slot number identifying the creating module is added by the infrastructure. Where the security context is stored for extended periods the data type is changed. The Netlabel code is converted to save lsmblob structures instead of secids in Patches 0018-0019. Patch 0020 adds checks to the binder hooks which verify that if both ends of a transaction use the same "display". Patches 0021-0022 add addition data to the audit records to identify the LSM specific data for all active modules. Patches 0023-0024 add new interfaces for getting the compound security contexts. Finally, with all interference on the AppArmor hooks removed, Patch 0025 removes the exclusive bit from AppArmor. An unnecessary stub hook was also removed. The Ubuntu project is using an earlier version of this patchset in their distribution to enable stacking for containers. Performance measurements to date have the change within the "noise". The sockperf and dbench results are on the order of 0.2% to 0.8% difference, with better performance being as common as worse. The benchmarks were run with AppArmor and Smack on Ubuntu. https://github.com/cschaufler/lsm-stacking.git#stack-5.4-rc6-v11-apparmor Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- arch/alpha/include/uapi/asm/socket.h | 1 + arch/mips/include/uapi/asm/socket.h | 1 + arch/parisc/include/uapi/asm/socket.h | 1 + arch/sparc/include/uapi/asm/socket.h | 1 + drivers/android/binder.c | 26 +- fs/ceph/xattr.c | 6 +- fs/nfs/nfs4proc.c | 22 +- fs/nfsd/nfs4xdr.c | 20 +- fs/proc/base.c | 2 + include/linux/audit.h | 1 + include/linux/cred.h | 3 +- include/linux/lsm_hooks.h | 37 +- include/linux/security.h | 175 ++++++++-- include/net/af_unix.h | 2 +- include/net/netlabel.h | 8 +- include/net/scm.h | 15 +- include/uapi/asm-generic/socket.h | 1 + kernel/audit.c | 72 +++- kernel/audit.h | 9 +- kernel/audit_fsnotify.c | 1 + kernel/auditfilter.c | 10 +- kernel/auditsc.c | 127 ++++--- kernel/cred.c | 12 +- net/core/sock.c | 7 +- net/ipv4/cipso_ipv4.c | 6 +- net/ipv4/ip_sockglue.c | 12 +- net/netfilter/nf_conntrack_netlink.c | 20 +- net/netfilter/nf_conntrack_standalone.c | 11 +- net/netfilter/nfnetlink_queue.c | 26 +- net/netfilter/nft_meta.c | 13 +- net/netfilter/xt_SECMARK.c | 5 +- net/netlabel/netlabel_kapi.c | 6 +- net/netlabel/netlabel_unlabeled.c | 97 +++--- net/netlabel/netlabel_unlabeled.h | 2 +- net/netlabel/netlabel_user.c | 13 +- net/netlabel/netlabel_user.h | 6 +- net/unix/af_unix.c | 6 +- net/xfrm/xfrm_policy.c | 2 + net/xfrm/xfrm_state.c | 2 + security/apparmor/include/apparmor.h | 3 +- security/apparmor/include/net.h | 6 +- security/apparmor/lsm.c | 117 +++---- security/commoncap.c | 7 +- security/integrity/ima/ima.h | 15 +- security/integrity/ima/ima_api.c | 11 +- security/integrity/ima/ima_appraise.c | 6 +- security/integrity/ima/ima_main.c | 49 +-- security/integrity/ima/ima_policy.c | 19 +- security/integrity/integrity_audit.c | 1 + security/loadpin/loadpin.c | 8 +- security/safesetid/lsm.c | 8 +- security/security.c | 593 +++++++++++++++++++++++++++++--- security/selinux/hooks.c | 109 +++--- security/selinux/include/classmap.h | 2 +- security/selinux/include/objsec.h | 5 + security/selinux/include/security.h | 1 + security/selinux/netlabel.c | 25 +- security/selinux/ss/services.c | 4 +- security/smack/smack.h | 6 + security/smack/smack_lsm.c | 124 ++++--- security/smack/smack_netfilter.c | 8 +- security/smack/smackfs.c | 10 +- security/tomoyo/tomoyo.c | 8 +- security/yama/yama_lsm.c | 7 +- 64 files changed, 1376 insertions(+), 563 deletions(-) ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure. 2019-11-13 16:50 [PATCH v11 00/25] LSM: Module stacking for AppArmor Casey Schaufler @ 2019-11-13 16:50 ` Casey Schaufler 0 siblings, 0 replies; 6+ messages in thread From: Casey Schaufler @ 2019-11-13 16:50 UTC (permalink / raw) To: casey.schaufler, jmorris, linux-security-module, selinux Cc: casey, keescook, john.johansen, penguin-kernel, paul, sds When more than one security module is exporting data to audit and networking sub-systems a single 32 bit integer is no longer sufficient to represent the data. Add a structure to be used instead. The lsmblob structure is currently an array of u32 "secids". There is an entry for each of the security modules built into the system that would use secids if active. The system assigns the module a "slot" when it registers hooks. If modules are compiled in but not registered there will be unused slots. A new lsm_id structure, which contains the name of the LSM and its slot number, is created. There is an instance for each LSM, which assigns the name and passes it to the infrastructure to set the slot. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/lsm_hooks.h | 12 ++++++-- include/linux/security.h | 58 ++++++++++++++++++++++++++++++++++++++ security/apparmor/lsm.c | 7 ++++- security/commoncap.c | 7 ++++- security/loadpin/loadpin.c | 8 +++++- security/safesetid/lsm.c | 8 +++++- security/security.c | 28 ++++++++++++++---- security/selinux/hooks.c | 8 +++++- security/smack/smack_lsm.c | 7 ++++- security/tomoyo/tomoyo.c | 8 +++++- security/yama/yama_lsm.c | 7 ++++- 11 files changed, 142 insertions(+), 16 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 13a67fd1a767..cfe5393840c7 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -2062,6 +2062,14 @@ struct security_hook_heads { struct hlist_head locked_down; } __randomize_layout; +/* + * Information that identifies a security module. + */ +struct lsm_id { + const char *lsm; /* Name of the LSM */ + int slot; /* Slot in lsmblob if one is allocated */ +}; + /* * Security module hook list structure. * For use with generic list macros for common operations. @@ -2070,7 +2078,7 @@ struct security_hook_list { struct hlist_node list; struct hlist_head *head; union security_list_options hook; - char *lsm; + struct lsm_id *lsmid; } __randomize_layout; /* @@ -2099,7 +2107,7 @@ extern struct security_hook_heads security_hook_heads; extern char *lsm_names; extern void security_add_hooks(struct security_hook_list *hooks, int count, - char *lsm); + struct lsm_id *lsmid); #define LSM_FLAG_LEGACY_MAJOR BIT(0) #define LSM_FLAG_EXCLUSIVE BIT(1) diff --git a/include/linux/security.h b/include/linux/security.h index 9df7547afc0c..5eced28fa0c9 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -126,6 +126,64 @@ enum lockdown_reason { LOCKDOWN_CONFIDENTIALITY_MAX, }; +/* + * Data exported by the security modules + * + * Any LSM that provides secid or secctx based hooks must be included. + */ +#define LSMBLOB_ENTRIES ( \ + (IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \ + (IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0)) + +struct lsmblob { + u32 secid[LSMBLOB_ENTRIES]; +}; + +#define LSMBLOB_INVALID -1 /* Not a valid LSM slot number */ +#define LSMBLOB_NEEDED -2 /* Slot requested on initialization */ +#define LSMBLOB_NOT_NEEDED -3 /* Slot not requested */ + +/** + * lsmblob_init - initialize an lsmblob structure. + * @blob: Pointer to the data to initialize + * @secid: The initial secid value + * + * Set all secid for all modules to the specified value. + */ +static inline void lsmblob_init(struct lsmblob *blob, u32 secid) +{ + int i; + + for (i = 0; i < LSMBLOB_ENTRIES; i++) + blob->secid[i] = secid; +} + +/** + * lsmblob_is_set - report if there is an value in the lsmblob + * @blob: Pointer to the exported LSM data + * + * Returns true if there is a secid set, false otherwise + */ +static inline bool lsmblob_is_set(struct lsmblob *blob) +{ + struct lsmblob empty = {}; + + return !!memcmp(blob, &empty, sizeof(*blob)); +} + +/** + * lsmblob_equal - report if the two lsmblob's are equal + * @bloba: Pointer to one LSM data + * @blobb: Pointer to the other LSM data + * + * Returns true if all entries in the two are equal, false otherwise + */ +static inline bool lsmblob_equal(struct lsmblob *bloba, struct lsmblob *blobb) +{ + return !memcmp(bloba, blobb, sizeof(*bloba)); +} + /* These functions are in security/commoncap.c */ extern int cap_capable(const struct cred *cred, struct user_namespace *ns, int cap, unsigned int opts); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 4093fa231671..11845348eefb 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1134,6 +1134,11 @@ struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct aa_sk_ctx), }; +static struct lsm_id apparmor_lsmid __lsm_ro_after_init = { + .lsm = "apparmor", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), @@ -1722,7 +1727,7 @@ static int __init apparmor_init(void) goto buffers_out; } security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks), - "apparmor"); + &apparmor_lsmid); /* Report that AppArmor successfully initialized */ apparmor_initialized = 1; diff --git a/security/commoncap.c b/security/commoncap.c index f4ee0ae106b2..9dcfd2a0e891 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -1339,6 +1339,11 @@ int cap_mmap_file(struct file *file, unsigned long reqprot, #ifdef CONFIG_SECURITY +static struct lsm_id capability_lsmid __lsm_ro_after_init = { + .lsm = "capability", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list capability_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(capable, cap_capable), LSM_HOOK_INIT(settime, cap_settime), @@ -1363,7 +1368,7 @@ static struct security_hook_list capability_hooks[] __lsm_ro_after_init = { static int __init capability_init(void) { security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks), - "capability"); + &capability_lsmid); return 0; } diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index ee5cb944f4ad..86317e78899f 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c @@ -180,6 +180,11 @@ static int loadpin_load_data(enum kernel_load_data_id id) return loadpin_read_file(NULL, (enum kernel_read_file_id) id); } +static struct lsm_id loadpin_lsmid __lsm_ro_after_init = { + .lsm = "loadpin", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security), LSM_HOOK_INIT(kernel_read_file, loadpin_read_file), @@ -227,7 +232,8 @@ static int __init loadpin_init(void) pr_info("ready to pin (currently %senforcing)\n", enforce ? "" : "not "); parse_exclude(); - security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); + security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), + &loadpin_lsmid); return 0; } diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c index 7760019ad35d..950dfb7f931e 100644 --- a/security/safesetid/lsm.c +++ b/security/safesetid/lsm.c @@ -149,6 +149,11 @@ static int safesetid_task_fix_setuid(struct cred *new, return -EACCES; } +static struct lsm_id safesetid_lsmid __lsm_ro_after_init = { + .lsm = "safesetid", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list safesetid_security_hooks[] = { LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid), LSM_HOOK_INIT(capable, safesetid_security_capable) @@ -157,7 +162,8 @@ static struct security_hook_list safesetid_security_hooks[] = { static int __init safesetid_security_init(void) { security_add_hooks(safesetid_security_hooks, - ARRAY_SIZE(safesetid_security_hooks), "safesetid"); + ARRAY_SIZE(safesetid_security_hooks), + &safesetid_lsmid); /* Report that SafeSetID successfully initialized */ safesetid_initialized = 1; diff --git a/security/security.c b/security/security.c index 5e43d3f64c1f..5f503cadf7f3 100644 --- a/security/security.c +++ b/security/security.c @@ -308,6 +308,7 @@ static void __init ordered_lsm_init(void) init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); init_debug("task blob size = %d\n", blob_sizes.lbs_task); + init_debug("lsmblob size = %lu\n", sizeof(struct lsmblob)); /* * Create any kmem_caches needed for blobs @@ -435,21 +436,36 @@ static int lsm_append(const char *new, char **result) return 0; } +/* + * Current index to use while initializing the lsmblob secid list. + */ +static int lsm_slot __initdata; + /** * security_add_hooks - Add a modules hooks to the hook lists. * @hooks: the hooks to add * @count: the number of hooks to add - * @lsm: the name of the security module + * @lsmid: the the identification information for the security module * * Each LSM has to register its hooks with the infrastructure. + * If the LSM is using hooks that export secids allocate a slot + * for it in the lsmblob. */ void __init security_add_hooks(struct security_hook_list *hooks, int count, - char *lsm) + struct lsm_id *lsmid) { int i; + if (lsmid->slot == LSMBLOB_NEEDED) { + if (lsm_slot >= LSMBLOB_ENTRIES) + panic("%s Too many LSMs registered.\n", __func__); + lsmid->slot = lsm_slot++; + init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm, + lsmid->slot); + } + for (i = 0; i < count; i++) { - hooks[i].lsm = lsm; + hooks[i].lsmid = lsmid; hlist_add_tail_rcu(&hooks[i].list, hooks[i].head); } @@ -458,7 +474,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, * and fix this up afterwards. */ if (slab_is_available()) { - if (lsm_append(lsm, &lsm_names) < 0) + if (lsm_append(lsmid->lsm, &lsm_names) < 0) panic("%s - Cannot get early memory.\n", __func__); } } @@ -1906,7 +1922,7 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name, struct security_hook_list *hp; hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { - if (lsm != NULL && strcmp(lsm, hp->lsm)) + if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; return hp->hook.getprocattr(p, name, value); } @@ -1919,7 +1935,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value, struct security_hook_list *hp; hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { - if (lsm != NULL && strcmp(lsm, hp->lsm)) + if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; return hp->hook.setprocattr(name, value, size); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3feb971068e2..5570a6ed49d5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6791,6 +6791,11 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct sk_security_struct), }; +static struct lsm_id selinux_lsmid __lsm_ro_after_init = { + .lsm = "selinux", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), @@ -7051,7 +7056,8 @@ static __init int selinux_init(void) hashtab_cache_init(); - security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux"); + security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), + &selinux_lsmid); if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) panic("SELinux: Unable to register AVC netcache callback\n"); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 796f78580c17..e42336328446 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4586,6 +4586,11 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { .lbs_sock = sizeof(struct socket_smack), }; +static struct lsm_id smack_lsmid __lsm_ro_after_init = { + .lsm = "smack", + .slot = LSMBLOB_NEEDED +}; + static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), @@ -4784,7 +4789,7 @@ static __init int smack_init(void) /* * Register with LSM */ - security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); + security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), &smack_lsmid); smack_enabled = 1; pr_info("Smack: Initializing.\n"); diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 716c92ec941a..f1968e80f06d 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -529,6 +529,11 @@ static void tomoyo_task_free(struct task_struct *task) } } +static struct lsm_id tomoyo_lsmid __lsm_ro_after_init = { + .lsm = "tomoyo", + .slot = LSMBLOB_NOT_NEEDED +}; + /* * tomoyo_security_ops is a "struct security_operations" which is used for * registering TOMOYO. @@ -581,7 +586,8 @@ static int __init tomoyo_init(void) struct tomoyo_task *s = tomoyo_task(current); /* register ourselves with the security framework */ - security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); + security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), + &tomoyo_lsmid); pr_info("TOMOYO Linux initialized\n"); s->domain_info = &tomoyo_kernel_domain; atomic_inc(&tomoyo_kernel_domain.users); diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 94dc346370b1..0f0cf7136929 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -421,6 +421,11 @@ static int yama_ptrace_traceme(struct task_struct *parent) return rc; } +static struct lsm_id yama_lsmid __lsm_ro_after_init = { + .lsm = "yama", + .slot = LSMBLOB_NOT_NEEDED +}; + static struct security_hook_list yama_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme), @@ -477,7 +482,7 @@ static inline void yama_init_sysctl(void) { } static int __init yama_init(void) { pr_info("Yama: becoming mindful.\n"); - security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama"); + security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), &yama_lsmid); yama_init_sysctl(); return 0; } -- 2.20.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2019-11-23 5:21 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <20191123011454.3292-1-casey.ref@schaufler-ca.com> [not found] ` <20191123011454.3292-1-casey@schaufler-ca.com> 2019-11-23 5:21 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Tetsuo Handa 2019-11-13 18:19 [PATCH v11 00/25] LSM: Module stacking for AppArmor Casey Schaufler 2019-11-13 18:19 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Casey Schaufler 2019-11-21 18:40 ` John Johansen -- strict thread matches above, loose matches on Subject: below -- 2019-11-13 17:56 [PATCH v11 00/25] LSM: Module stacking for AppArmor Casey Schaufler 2019-11-13 17:56 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Casey Schaufler 2019-11-21 5:36 ` James Morris 2019-11-13 16:50 [PATCH v11 00/25] LSM: Module stacking for AppArmor Casey Schaufler 2019-11-13 16:50 ` [PATCH v11 02/25] LSM: Create and manage the lsmblob data structure Casey Schaufler
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).