[PATCH v19 23/23] AppArmor: Remove the exclusive flag

2020-07-24 Thread Casey Schaufler
With the inclusion of the "display" process attribute
mechanism AppArmor no longer needs to be treated as an
"exclusive" security module. Remove the flag that indicates
it is exclusive. Remove the stub getpeersec_dgram AppArmor
hook as it has no effect in the single LSM case and
interferes in the multiple LSM case.

Acked-by: Stephen Smalley 
Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Signed-off-by: Casey Schaufler 
---
 security/apparmor/lsm.c | 20 +---
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 7ce570b0f491..4b7cbe9bb1be 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1129,22 +1129,6 @@ static int apparmor_socket_getpeersec_stream(struct 
socket *sock,
return error;
 }
 
-/**
- * apparmor_socket_getpeersec_dgram - get security label of packet
- * @sock: the peer socket
- * @skb: packet data
- * @secid: pointer to where to put the secid of the packet
- *
- * Sets the netlabel socket state on sk from parent
- */
-static int apparmor_socket_getpeersec_dgram(struct socket *sock,
-   struct sk_buff *skb, u32 *secid)
-
-{
-   /* TODO: requires secid support */
-   return -ENOPROTOOPT;
-}
-
 /**
  * apparmor_sock_graft - Initialize newly created socket
  * @sk: child sock
@@ -1248,8 +1232,6 @@ static struct security_hook_list apparmor_hooks[] 
__lsm_ro_after_init = {
 #endif
LSM_HOOK_INIT(socket_getpeersec_stream,
  apparmor_socket_getpeersec_stream),
-   LSM_HOOK_INIT(socket_getpeersec_dgram,
- apparmor_socket_getpeersec_dgram),
LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
 #ifdef CONFIG_NETWORK_SECMARK
LSM_HOOK_INIT(inet_conn_request, apparmor_inet_conn_request),
@@ -1918,7 +1900,7 @@ static int __init apparmor_init(void)
 
 DEFINE_LSM(apparmor) = {
.name = "apparmor",
-   .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
+   .flags = LSM_FLAG_LEGACY_MAJOR,
.enabled = &apparmor_enabled,
.blobs = &apparmor_blob_sizes,
.init = apparmor_init,
-- 
2.24.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit



[PATCH v19 22/23] LSM: Add /proc attr entry for full LSM context

2020-07-24 Thread Casey Schaufler
Add an entry /proc/.../attr/context which displays the full
process security "context" in compound format:
lsm1\0value\0lsm2\0value\0...
This entry is not writable.

A security module may decide that its policy does not allow
this information to be displayed. In this case none of the
information will be displayed.

Reviewed-by: Kees Cook 
Signed-off-by: Casey Schaufler 
Cc: linux-...@vger.kernel.org
---
 Documentation/security/lsm.rst   | 28 +++
 fs/proc/base.c   |  1 +
 include/linux/lsm_hooks.h|  6 +++
 security/apparmor/include/procattr.h |  2 +-
 security/apparmor/lsm.c  |  8 +++-
 security/apparmor/procattr.c | 22 +
 security/security.c  | 70 
 security/selinux/hooks.c |  2 +-
 security/smack/smack_lsm.c   |  2 +-
 9 files changed, 126 insertions(+), 15 deletions(-)

diff --git a/Documentation/security/lsm.rst b/Documentation/security/lsm.rst
index 6a2a2e973080..fd4c87358d54 100644
--- a/Documentation/security/lsm.rst
+++ b/Documentation/security/lsm.rst
@@ -129,3 +129,31 @@ to identify it as the first security module to be 
registered.
 The capabilities security module does not use the general security
 blobs, unlike other modules. The reasons are historical and are
 based on overhead, complexity and performance concerns.
+
+LSM External Interfaces
+===
+
+The LSM infrastructure does not generally provide external interfaces.
+The individual security modules provide what external interfaces they
+require.
+
+The file ``/sys/kernel/security/lsm`` provides a comma
+separated list of the active security modules.
+
+The file ``/proc/pid/attr/display`` contains the name of the security
+module for which the ``/proc/pid/attr/current`` interface will
+apply. This interface can be written to.
+
+The infrastructure does provide an interface for the special
+case where multiple security modules provide a process context.
+This is provided in compound context format.
+
+-  `lsm\0value\0lsm\0value\0`
+
+The `lsm` and `value` fields are nul terminated bytestrings.
+Each field may contain whitespace or non-printable characters.
+The nul bytes are included in the size of a compound context.
+The context ``Bell\0Secret\0Biba\0Loose\0`` has a size of 23.
+
+The file ``/proc/pid/attr/context`` provides the security
+context of the identified process.
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 40471a12ced2..ba8b0316e999 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2795,6 +2795,7 @@ static const struct pid_entry attr_dir_stuff[] = {
ATTR(NULL, "keycreate", 0666),
ATTR(NULL, "sockcreate",0666),
ATTR(NULL, "display",   0666),
+   ATTR(NULL, "context",   0444),
 #ifdef CONFIG_SECURITY_SMACK
DIR("smack",0555,
proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 6908fa03cf31..5be04dacc17a 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1359,6 +1359,12 @@
  * @pages contains the number of pages.
  * Return 0 if permission is granted.
  *
+ * @getprocattr:
+ * Provide the named process attribute for display in special files in
+ * the /proc/.../attr directory.  Attribute naming and the data displayed
+ * is at the discretion of the security modules.  The exception is the
+ * "context" attribute, which will contain the security context of the
+ * task as a nul terminated text string without trailing whitespace.
  * @ismaclabel:
  * Check if the extended attribute specified by @name
  * represents a MAC label. Returns 1 if name is a MAC
diff --git a/security/apparmor/include/procattr.h 
b/security/apparmor/include/procattr.h
index 31689437e0e1..03dbfdb2f2c0 100644
--- a/security/apparmor/include/procattr.h
+++ b/security/apparmor/include/procattr.h
@@ -11,7 +11,7 @@
 #ifndef __AA_PROCATTR_H
 #define __AA_PROCATTR_H
 
-int aa_getprocattr(struct aa_label *label, char **string);
+int aa_getprocattr(struct aa_label *label, char **string, bool newline);
 int aa_setprocattr_changehat(char *args, size_t size, int flags);
 
 #endif /* __AA_PROCATTR_H */
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 31a6f11890f1..7ce570b0f491 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -593,6 +593,7 @@ static int apparmor_getprocattr(struct task_struct *task, 
char *name,
const struct cred *cred = get_task_cred(task);
struct aa_task_ctx *ctx = task_ctx(current);
struct aa_label *label = NULL;
+   bool newline = true;
 
if (strcmp(name, "current") == 0)
label = aa_get_newest_label(cred_label(cred));
@@ -600,11 +601,14 @@ static int apparmor_getprocattr(struct task_struct *task, 
char *name,
label = aa_get_newest_label(ctx->previ

[PATCH v19 21/23] Audit: Add a new record for multiple object LSM attributes

2020-07-24 Thread Casey Schaufler
Create a new audit record type to contain the object information
when there are multiple security modules that require such data.
This record is emitted before the other records for the event, but
is linked with the same timestamp and serial number.

Signed-off-by: Casey Schaufler 
Cc: linux-audit@redhat.com
---
 include/linux/audit.h  |  2 ++
 include/uapi/linux/audit.h |  1 +
 kernel/audit.c | 53 +
 kernel/audit.h |  4 +--
 kernel/auditsc.c   | 70 +-
 5 files changed, 67 insertions(+), 63 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 4693febcf41f..3cc02ddd7779 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -171,6 +171,8 @@ extern void audit_log_lost(const char *message);
 extern void audit_log_lsm(struct lsmblob *blob, bool exiting);
 extern int audit_log_task_context(struct audit_buffer *ab,
  struct lsmblob *blob);
+extern int audit_log_object_context(struct audit_buffer *ab,
+   struct lsmblob *blob);
 extern void audit_log_task_info(struct audit_buffer *ab);
 
 extern int audit_update_lsm_rules(void);
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index a5403efc2fdf..753a69c6bbbe 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -140,6 +140,7 @@
 #define AUDIT_MAC_CALIPSO_ADD  1418/* NetLabel: add CALIPSO DOI entry */
 #define AUDIT_MAC_CALIPSO_DEL  1419/* NetLabel: del CALIPSO DOI entry */
 #define AUDIT_MAC_TASK_CONTEXTS1420/* Multiple LSM contexts */
+#define AUDIT_MAC_OBJ_CONTEXTS 1421/* Multiple LSM object contexts */
 
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG1799
diff --git a/kernel/audit.c b/kernel/audit.c
index 777d8da41082..5d49dfed7674 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2177,6 +2177,59 @@ int audit_log_task_context(struct audit_buffer *ab, 
struct lsmblob *blob)
 }
 EXPORT_SYMBOL(audit_log_task_context);
 
+int audit_log_object_context(struct audit_buffer *ab,
+   struct lsmblob *blob)
+{
+   int i;
+   int error;
+   bool sep = false;
+   struct lsmcontext lsmdata;
+   struct audit_buffer *lsmab = NULL;
+   struct audit_context *context = NULL;
+
+   /*
+* If there is more than one security module that has a
+* object "context" it's necessary to put the object data
+* into a separate record to maintain compatibility.
+*/
+   if (lsm_multiple_contexts()) {
+   audit_log_format(ab, " obj=?");
+   context = ab->ctx;
+   if (context)
+   lsmab = audit_log_start(context, GFP_KERNEL,
+   AUDIT_MAC_OBJ_CONTEXTS);
+   }
+
+   for (i = 0; i < LSMBLOB_ENTRIES; i++) {
+   if (blob->secid[i] == 0)
+   continue;
+   error = security_secid_to_secctx(blob, &lsmdata, i);
+   if (error && error != -EINVAL) {
+   audit_panic("error in audit_log_object_context");
+   return error;
+   }
+
+   if (context) {
+   audit_log_format(lsmab, "%sobj_%s=%s",
+sep ? " " : "",
+security_lsm_slot_name(i),
+lsmdata.context);
+   sep = true;
+   } else
+   audit_log_format(ab, " obj=%s", lsmdata.context);
+
+   security_release_secctx(&lsmdata);
+   if (!context)
+   break;
+   }
+
+   if (context)
+   audit_log_end(lsmab);
+
+   return 0;
+}
+EXPORT_SYMBOL(audit_log_object_context);
+
 void audit_log_d_path_exe(struct audit_buffer *ab,
  struct mm_struct *mm)
 {
diff --git a/kernel/audit.h b/kernel/audit.h
index 6ab012e5fe98..78bc11bfeba6 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -78,7 +78,7 @@ struct audit_names {
kuid_t  uid;
kgid_t  gid;
dev_t   rdev;
-   u32 osid;
+   struct lsmblob  oblob;
struct audit_cap_data   fcap;
unsigned intfcap_ver;
unsigned char   type;   /* record type */
@@ -152,7 +152,7 @@ struct audit_context {
kuid_t  uid;
kgid_t  gid;
umode_t mode;
-   u32 osid;
+   struct lsmblob  oblob;
int has_perm;
uid_t  

[PATCH v19 20/23] Audit: Add new record for multiple process LSM attributes

2020-07-24 Thread Casey Schaufler
Create a new audit record type to contain the subject information
when there are multiple security modules that require such data.
This record is linked with the same timestamp and serial number.
The record is produced only in cases where there is more than one
security module with a process "context".

Before this change the only audit events that required multiple
records were syscall events. Several non-syscall events include
subject contexts, so the use of audit_context data has been expanded
as necessary.

Signed-off-by: Casey Schaufler 
Cc: linux-audit@redhat.com
---
 drivers/android/binder.c|  2 +-
 include/linux/audit.h   | 13 +++-
 include/linux/security.h| 18 -
 include/net/netlabel.h  |  2 +-
 include/net/scm.h   |  3 +-
 include/net/xfrm.h  |  4 +-
 include/uapi/linux/audit.h  |  1 +
 kernel/audit.c  | 90 ++---
 kernel/auditfilter.c|  2 +-
 kernel/auditsc.c| 87 ++--
 net/ipv4/ip_sockglue.c  |  2 +-
 net/netfilter/nf_conntrack_netlink.c|  4 +-
 net/netfilter/nf_conntrack_standalone.c |  2 +-
 net/netfilter/nfnetlink_queue.c |  2 +-
 net/netlabel/netlabel_unlabeled.c   | 16 ++---
 net/netlabel/netlabel_user.c| 12 ++--
 net/netlabel/netlabel_user.h|  6 +-
 security/integrity/integrity_audit.c|  2 +-
 security/security.c | 71 ++-
 security/smack/smackfs.c|  3 +-
 20 files changed, 259 insertions(+), 83 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index ceb5987c7d76..99b1e65b193c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3109,7 +3109,7 @@ static void binder_transaction(struct binder_proc *proc,
size_t added_size;
 
security_task_getsecid(proc->tsk, &blob);
-   ret = security_secid_to_secctx(&blob, &lsmctx);
+   ret = security_secid_to_secctx(&blob, &lsmctx, LSMBLOB_DISPLAY);
if (ret) {
return_error = BR_FAILED_REPLY;
return_error_param = ret;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index aabbbe6d9296..4693febcf41f 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -168,7 +168,9 @@ extern void audit_log_path_denied(int type,
  const char *operation);
 extern voidaudit_log_lost(const char *message);
 
-extern int audit_log_task_context(struct audit_buffer *ab);
+extern void audit_log_lsm(struct lsmblob *blob, bool exiting);
+extern int audit_log_task_context(struct audit_buffer *ab,
+ struct lsmblob *blob);
 extern void audit_log_task_info(struct audit_buffer *ab);
 
 extern int audit_update_lsm_rules(void);
@@ -228,7 +230,10 @@ static inline void audit_log_key(struct audit_buffer *ab, 
char *key)
 { }
 static inline void audit_log_path_denied(int type, const char *operation)
 { }
-static inline int audit_log_task_context(struct audit_buffer *ab)
+static inline void audit_log_lsm(struct lsmblob *blob, bool exiting)
+{ }
+static inline int audit_log_task_context(struct audit_buffer *ab,
+struct lsmblob *blob);
 {
return 0;
 }
@@ -287,6 +292,7 @@ extern void audit_seccomp(unsigned long syscall, long 
signr, int code);
 extern void audit_seccomp_actions_logged(const char *names,
 const char *old_names, int res);
 extern void __audit_ptrace(struct task_struct *t);
+extern void audit_stamp_context(struct audit_context *ctx);
 
 static inline void audit_set_context(struct task_struct *task, struct 
audit_context *ctx)
 {
@@ -665,6 +671,9 @@ static inline void audit_ntp_log(const struct 
audit_ntp_data *ad)
 static inline void audit_ptrace(struct task_struct *t)
 { }
 
+static inline void audit_stamp_context(struct audit_context *ctx)
+{ }
+
 static inline void audit_log_nfcfg(const char *name, u8 af,
   unsigned int nentries,
   enum audit_nfcfgop op)
diff --git a/include/linux/security.h b/include/linux/security.h
index 02dc3b5ef57b..b046494ba66e 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -179,6 +179,8 @@ struct lsmblob {
 #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 */
+#define LSMBLOB_DISPLAY-4  /* Use the "display" slot */
+#define LSMBLOB_FIRST  -5  /* Use the default "display" slot */
 
 /**
  * lsmblob_init - initialize an lsmblob structure.
@@ -2

[PATCH v19 19/23] LSM: Verify LSM display sanity in binder

2020-07-24 Thread Casey Schaufler
Verify that the tasks on the ends of a binder transaction
use the same "display" security module. This prevents confusion
of security "contexts".

Reviewed-by: Kees Cook 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
---
 security/security.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/security/security.c b/security/security.c
index ddbaf2073b02..95b48721fb17 100644
--- a/security/security.c
+++ b/security/security.c
@@ -788,9 +788,38 @@ int security_binder_set_context_mgr(struct task_struct 
*mgr)
return call_int_hook(binder_set_context_mgr, 0, mgr);
 }
 
+/**
+ * security_binder_transaction - Binder driver transaction check
+ * @from: source of the transaction
+ * @to: destination of the transaction
+ *
+ * Verify that the tasks have the same LSM "display", then
+ * call the security module hooks.
+ *
+ * Returns -EINVAL if the displays don't match, or the
+ * result of the security module checks.
+ */
 int security_binder_transaction(struct task_struct *from,
struct task_struct *to)
 {
+   int from_display = lsm_task_display(from);
+   int to_display = lsm_task_display(to);
+
+   /*
+* If the display is LSMBLOB_INVALID the first module that has
+* an entry is used. This will be in the 0 slot.
+*
+* This is currently only required if the server has requested
+* peer contexts, but it would be unwieldly to have too much of
+* the binder driver detail here.
+*/
+   if (from_display == LSMBLOB_INVALID)
+   from_display = 0;
+   if (to_display == LSMBLOB_INVALID)
+   to_display = 0;
+   if (from_display != to_display)
+   return -EINVAL;
+
return call_int_hook(binder_transaction, 0, from, to);
 }
 
-- 
2.24.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit



[PATCH v19 18/23] NET: Store LSM netlabel data in a lsmblob

2020-07-24 Thread Casey Schaufler
Netlabel uses LSM interfaces requiring an lsmblob and
the internal storage is used to pass information between
these interfaces, so change the internal data from a secid
to a lsmblob. Update the netlabel interfaces and their
callers to accommodate the change. This requires that the
modules using netlabel use the lsm_id.slot to access the
correct secid when using netlabel.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
Cc: net...@vger.kernel.org
---
 include/net/netlabel.h  |  8 +--
 net/ipv4/cipso_ipv4.c   | 27 ++
 net/netlabel/netlabel_kapi.c|  6 +--
 net/netlabel/netlabel_unlabeled.c   | 79 +
 net/netlabel/netlabel_unlabeled.h   |  2 +-
 security/selinux/hooks.c|  2 +-
 security/selinux/include/security.h |  1 +
 security/selinux/netlabel.c |  2 +-
 security/selinux/ss/services.c  |  4 +-
 security/smack/smack.h  |  1 +
 security/smack/smack_lsm.c  |  5 +-
 security/smack/smackfs.c| 10 ++--
 12 files changed, 65 insertions(+), 82 deletions(-)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 43ae50337685..73fc25b4042b 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -166,7 +166,7 @@ struct netlbl_lsm_catmap {
  * @attr.mls: MLS sensitivity label
  * @attr.mls.cat: MLS category bitmap
  * @attr.mls.lvl: MLS sensitivity level
- * @attr.secid: LSM specific secid token
+ * @attr.lsmblob: LSM specific data
  *
  * Description:
  * This structure is used to pass security attributes between NetLabel and the
@@ -201,7 +201,7 @@ struct netlbl_lsm_secattr {
struct netlbl_lsm_catmap *cat;
u32 lvl;
} mls;
-   u32 secid;
+   struct lsmblob lsmblob;
} attr;
 };
 
@@ -415,7 +415,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
const void *addr,
const void *mask,
u16 family,
-   u32 secid,
+   struct lsmblob *lsmblob,
struct netlbl_audit *audit_info);
 int netlbl_cfg_unlbl_static_del(struct net *net,
const char *dev_name,
@@ -523,7 +523,7 @@ static inline int netlbl_cfg_unlbl_static_add(struct net 
*net,
  const void *addr,
  const void *mask,
  u16 family,
- u32 secid,
+ struct lsmblob *lsmblob,
  struct netlbl_audit *audit_info)
 {
return -ENOSYS;
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index a23094b050f8..469baf6704f5 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -106,15 +106,17 @@ int cipso_v4_rbm_strictvalid = 1;
 /* Base length of the local tag (non-standard tag).
  *  Tag definition (may change between kernel versions)
  *
- * 0  8  16 24 32
- * +--+--+--+--+
- * | 1000 | 0110 | 32-bit secid value  |
- * +--+--+--+--+
- * | in (host byte order)|
- * +--+--+
- *
+ * 0  8  1616 + sizeof(struct lsmblob)
+ * +--+--+-+
+ * | 1000 | 0110 | LSM blob data   |
+ * +--+--+-+
+ *
+ * All secid and flag fields are in host byte order.
+ * The lsmblob structure size varies depending on which
+ * Linux security modules are built in the kernel.
+ * The data is opaque.
  */
-#define CIPSO_V4_TAG_LOC_BLEN 6
+#define CIPSO_V4_TAG_LOC_BLEN (2 + sizeof(struct lsmblob))
 
 /*
  * Helper Functions
@@ -1469,7 +1471,12 @@ static int cipso_v4_gentag_loc(const struct cipso_v4_doi 
*doi_def,
 
buffer[0] = CIPSO_V4_TAG_LOCAL;
buffer[1] = CIPSO_V4_TAG_LOC_BLEN;
-   *(u32 *)&buffer[2] = secattr->attr.secid;
+   /* Ensure that there is sufficient space in the CIPSO header
+* for the LSM data. This should never become an issue.
+* The check is made from an abundance of caution. */
+   BUILD_BUG_ON(CIPSO_V4_TAG_LOC_BLEN > CIPSO_V4_OPT_LEN_MAX);
+   memcpy(&buffer[2], &secattr->attr.lsmblob,
+  sizeof(secattr->attr.lsmblob));
 
return CIPSO_V4_TAG_LOC_BLEN;
 }
@@ -1489,7 +1496,7 @@ static int cipso_v4_parsetag_loc(const struct 
cipso_v4_doi *doi_def,
 const unsigned char *tag,
 struct netlbl_lsm_secattr *secattr)
 {
-   secattr->attr.secid = *(u32 *)&tag[2];
+   memcpy(&secattr->attr.lsmblob, &tag[2], sizeof(secattr->attr

[PATCH v19 17/23] LSM: security_secid_to_secctx in netlink netfilter

2020-07-24 Thread Casey Schaufler
Change netlink netfilter interfaces to use lsmcontext
pointers, and remove scaffolding.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
cc: net...@vger.kernel.org
---
 net/netfilter/nfnetlink_queue.c | 31 ---
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index fe19ae7216db..a4d4602ab9b7 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -301,12 +301,10 @@ static int nfqnl_put_sk_uidgid(struct sk_buff *skb, 
struct sock *sk)
return -1;
 }
 
-static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
+static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, struct lsmcontext *context)
 {
-   u32 seclen = 0;
 #if IS_ENABLED(CONFIG_NETWORK_SECMARK)
struct lsmblob blob;
-   struct lsmcontext context = { };
 
if (!skb || !sk_fullsock(skb->sk))
return 0;
@@ -318,14 +316,14 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char 
**secdata)
 * blob. security_secid_to_secctx() will know which security
 * module to use to create the secctx.  */
lsmblob_init(&blob, skb->secmark);
-   security_secid_to_secctx(&blob, &context);
-   *secdata = context.context;
+   security_secid_to_secctx(&blob, context);
}
 
read_unlock_bh(&skb->sk->sk_callback_lock);
-   seclen = context.len;
+   return context->len;
+#else
+   return 0;
 #endif
-   return seclen;
 }
 
 static u32 nfqnl_get_bridge_size(struct nf_queue_entry *entry)
@@ -401,8 +399,7 @@ nfqnl_build_packet_message(struct net *net, struct 
nfqnl_instance *queue,
enum ip_conntrack_info uninitialized_var(ctinfo);
struct nfnl_ct_hook *nfnl_ct;
bool csum_verify;
-   struct lsmcontext scaff; /* scaffolding */
-   char *secdata = NULL;
+   struct lsmcontext context = { };
u32 seclen = 0;
 
size = nlmsg_total_size(sizeof(struct nfgenmsg))
@@ -469,7 +466,7 @@ nfqnl_build_packet_message(struct net *net, struct 
nfqnl_instance *queue,
}
 
if ((queue->flags & NFQA_CFG_F_SECCTX) && entskb->sk) {
-   seclen = nfqnl_get_sk_secctx(entskb, &secdata);
+   seclen = nfqnl_get_sk_secctx(entskb, &context);
if (seclen)
size += nla_total_size(seclen);
}
@@ -604,7 +601,7 @@ nfqnl_build_packet_message(struct net *net, struct 
nfqnl_instance *queue,
nfqnl_put_sk_uidgid(skb, entskb->sk) < 0)
goto nla_put_failure;
 
-   if (seclen && nla_put(skb, NFQA_SECCTX, seclen, secdata))
+   if (seclen && nla_put(skb, NFQA_SECCTX, context.len, context.context))
goto nla_put_failure;
 
if (ct && nfnl_ct->build(skb, ct, ctinfo, NFQA_CT, NFQA_CT_INFO) < 0)
@@ -632,10 +629,8 @@ nfqnl_build_packet_message(struct net *net, struct 
nfqnl_instance *queue,
}
 
nlh->nlmsg_len = skb->len;
-   if (seclen) {
-   lsmcontext_init(&scaff, secdata, seclen, 0);
-   security_release_secctx(&scaff);
-   }
+   if (seclen)
+   security_release_secctx(&context);
return skb;
 
 nla_put_failure:
@@ -643,10 +638,8 @@ nfqnl_build_packet_message(struct net *net, struct 
nfqnl_instance *queue,
kfree_skb(skb);
net_err_ratelimited("nf_queue: error creating packet message\n");
 nlmsg_failure:
-   if (seclen) {
-   lsmcontext_init(&scaff, secdata, seclen, 0);
-   security_release_secctx(&scaff);
-   }
+   if (seclen)
+   security_release_secctx(&context);
return NULL;
 }
 
-- 
2.24.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit



[PATCH v19 16/23] LSM: Use lsmcontext in security_inode_getsecctx

2020-07-24 Thread Casey Schaufler
Change the security_inode_getsecctx() interface to fill
a lsmcontext structure instead of data and length pointers.
This provides the information about which LSM created the
context so that security_release_secctx() can use the
correct hook.

Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
---
 fs/nfsd/nfs4xdr.c| 23 +--
 include/linux/security.h |  5 +++--
 security/security.c  | 13 +++--
 3 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 61d6b8a0e8f0..6673221d5606 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2379,11 +2379,11 @@ nfsd4_encode_layout_types(struct xdr_stream *xdr, u32 
layout_types)
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
 static inline __be32
 nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
-   void *context, int len)
+   struct lsmcontext *context)
 {
__be32 *p;
 
-   p = xdr_reserve_space(xdr, len + 4 + 4 + 4);
+   p = xdr_reserve_space(xdr, context->len + 4 + 4 + 4);
if (!p)
return nfserr_resource;
 
@@ -2393,13 +2393,13 @@ nfsd4_encode_security_label(struct xdr_stream *xdr, 
struct svc_rqst *rqstp,
 */
*p++ = cpu_to_be32(0); /* lfs */
*p++ = cpu_to_be32(0); /* pi */
-   p = xdr_encode_opaque(p, context, len);
+   p = xdr_encode_opaque(p, context->context, context->len);
return 0;
 }
 #else
 static inline __be32
 nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
-   void *context, int len)
+   struct lsmcontext *context)
 { return 0; }
 #endif
 
@@ -2496,9 +2496,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh 
*fhp,
int err;
struct nfs4_acl *acl = NULL;
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
-   struct lsmcontext scaff; /* scaffolding */
-   void *context = NULL;
-   int contextlen;
+   struct lsmcontext context = { };
 #endif
bool contextsupport = false;
struct nfsd4_compoundres *resp = rqstp->rq_resp;
@@ -2556,7 +2554,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh 
*fhp,
 bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
err = security_inode_getsecctx(d_inode(dentry),
-   &context, &contextlen);
+  &context);
else
err = -EOPNOTSUPP;
contextsupport = (err == 0);
@@ -2986,8 +2984,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh 
*fhp,
 
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
-   status = nfsd4_encode_security_label(xdr, rqstp, context,
-   contextlen);
+   status = nfsd4_encode_security_label(xdr, rqstp, &context);
if (status)
goto out;
}
@@ -2999,10 +2996,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh 
*fhp,
 
 out:
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
-   if (context) {
-   lsmcontext_init(&scaff, context, contextlen, 0); /*scaffolding*/
-   security_release_secctx(&scaff);
-   }
+   if (context.context)
+   security_release_secctx(&context);
 #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
kfree(acl);
if (tempfh) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 43f8a2660d37..02dc3b5ef57b 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -560,7 +560,7 @@ void security_release_secctx(struct lsmcontext *cp);
 void security_inode_invalidate_secctx(struct inode *inode);
 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
-int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
+int security_inode_getsecctx(struct inode *inode, struct lsmcontext *cp);
 int security_locked_down(enum lockdown_reason what);
 #else /* CONFIG_SECURITY */
 
@@ -1399,7 +1399,8 @@ static inline int security_inode_setsecctx(struct dentry 
*dentry, void *ctx, u32
 {
return -EOPNOTSUPP;
 }
-static inline int security_inode_getsecctx(struct inode *inode, void **ctx, 
u32 *ctxlen)
+static inline int security_inode_getsecctx(struct inode *inode,
+  struct lsmcontext *cp)
 {
return -EOPNOTSUPP;
 }
diff --git a/security/security.c b/security/security.c
index 862f0bc2f114..ddbaf2073b02 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2263,9 +2263,18 @@ int security_inode_setsecctx(struct dentry *dentry, void 
*ctx, u32 ctxlen)
 }
 EXPORT_SYMBOL(security_inode_setsecctx);

[PATCH v19 15/23] LSM: Use lsmcontext in security_secid_to_secctx

2020-07-24 Thread Casey Schaufler
Replace the (secctx,seclen) pointer pair with a single
lsmcontext pointer to allow return of the LSM identifier
along with the context and context length. This allows
security_release_secctx() to know how to release the
context. Callers have been modified to use or save the
returned data from the new structure.

Reviewed-by: Kees Cook 
Acked-by: Stephen Smalley 
Acked-by: Paul Moore 
Signed-off-by: Casey Schaufler 
Cc: net...@vger.kernel.org
---
 drivers/android/binder.c| 26 +++-
 include/linux/security.h|  4 +--
 include/net/scm.h   | 10 ++-
 kernel/audit.c  | 35 --
 kernel/auditsc.c| 31 +++
 net/ipv4/ip_sockglue.c  |  7 ++---
 net/netfilter/nf_conntrack_netlink.c| 18 +--
 net/netfilter/nf_conntrack_standalone.c |  7 ++---
 net/netfilter/nfnetlink_queue.c |  5 +++-
 net/netlabel/netlabel_unlabeled.c   | 40 -
 net/netlabel/netlabel_user.c|  7 ++---
 security/security.c | 10 +--
 12 files changed, 76 insertions(+), 124 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index b7ab206f8bb3..ceb5987c7d76 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2861,9 +2861,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_size_t last_fixup_min_off = 0;
struct binder_context *context = proc->context;
int t_debug_id = atomic_inc_return(&binder_last_id);
-   char *secctx = NULL;
-   u32 secctx_sz = 0;
-   struct lsmcontext scaff; /* scaffolding */
+   struct lsmcontext lsmctx = { };
 
e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@@ -3111,14 +3109,14 @@ static void binder_transaction(struct binder_proc *proc,
size_t added_size;
 
security_task_getsecid(proc->tsk, &blob);
-   ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
+   ret = security_secid_to_secctx(&blob, &lsmctx);
if (ret) {
return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_line = __LINE__;
goto err_get_secctx_failed;
}
-   added_size = ALIGN(secctx_sz, sizeof(u64));
+   added_size = ALIGN(lsmctx.len, sizeof(u64));
extra_buffers_size += added_size;
if (extra_buffers_size < added_size) {
/* integer overflow of extra_buffers_size */
@@ -3145,24 +3143,22 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer = NULL;
goto err_binder_alloc_buf_failed;
}
-   if (secctx) {
+   if (lsmctx.context) {
int err;
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
ALIGN(tr->offsets_size, sizeof(void *)) +
ALIGN(extra_buffers_size, sizeof(void *)) -
-   ALIGN(secctx_sz, sizeof(u64));
+   ALIGN(lsmctx.len, sizeof(u64));
 
t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset;
err = binder_alloc_copy_to_buffer(&target_proc->alloc,
  t->buffer, buf_offset,
- secctx, secctx_sz);
+ lsmctx.context, lsmctx.len);
if (err) {
t->security_ctx = 0;
WARN_ON(1);
}
-   lsmcontext_init(&scaff, secctx, secctx_sz, 0);
-   security_release_secctx(&scaff);
-   secctx = NULL;
+   security_release_secctx(&lsmctx);
}
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
@@ -3218,7 +3214,7 @@ static void binder_transaction(struct binder_proc *proc,
off_end_offset = off_start_offset + tr->offsets_size;
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
-   ALIGN(secctx_sz, sizeof(u64));
+   ALIGN(lsmctx.len, sizeof(u64));
off_min = 0;
for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
 buffer_offset += sizeof(binder_size_t)) {
@@ -3494,10 +3490,8 @@ static void binder_transaction(struct binder_proc *proc,
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
 err_binder_alloc_buf_failed:
 err_bad_extra_size:
-   if (secctx) {
-   lsmcontext_init(&scaff, secctx, secctx_sz, 0);
-   security_release_secctx(&scaff);
-   }
+   if (lsmc

[PATCH v19 14/23] LSM: Ensure the correct LSM context releaser

2020-07-24 Thread Casey Schaufler
Add a new lsmcontext data structure to hold all the information
about a "security context", including the string, its size and
which LSM allocated the string. The allocation information is
necessary because LSMs have different policies regarding the
lifecycle of these strings. SELinux allocates and destroys
them on each use, whereas Smack provides a pointer to an entry
in a list that never goes away.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
Cc: linux-integr...@vger.kernel.org
Cc: net...@vger.kernel.org
---
 drivers/android/binder.c| 10 ---
 fs/ceph/xattr.c |  6 -
 fs/nfs/nfs4proc.c   |  8 --
 fs/nfsd/nfs4xdr.c   |  7 +++--
 include/linux/security.h| 35 +++--
 include/net/scm.h   |  5 +++-
 kernel/audit.c  | 14 +++---
 kernel/auditsc.c| 12 ++---
 net/ipv4/ip_sockglue.c  |  4 ++-
 net/netfilter/nf_conntrack_netlink.c|  4 ++-
 net/netfilter/nf_conntrack_standalone.c |  4 ++-
 net/netfilter/nfnetlink_queue.c | 13 ++---
 net/netlabel/netlabel_unlabeled.c   | 19 +++---
 net/netlabel/netlabel_user.c|  4 ++-
 security/security.c | 11 
 15 files changed, 121 insertions(+), 35 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 46e2a26089cc..b7ab206f8bb3 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2863,6 +2863,7 @@ static void binder_transaction(struct binder_proc *proc,
int t_debug_id = atomic_inc_return(&binder_last_id);
char *secctx = NULL;
u32 secctx_sz = 0;
+   struct lsmcontext scaff; /* scaffolding */
 
e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@@ -3159,7 +3160,8 @@ static void binder_transaction(struct binder_proc *proc,
t->security_ctx = 0;
WARN_ON(1);
}
-   security_release_secctx(secctx, secctx_sz);
+   lsmcontext_init(&scaff, secctx, secctx_sz, 0);
+   security_release_secctx(&scaff);
secctx = NULL;
}
t->buffer->debug_id = t->debug_id;
@@ -3492,8 +3494,10 @@ static void binder_transaction(struct binder_proc *proc,
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
 err_binder_alloc_buf_failed:
 err_bad_extra_size:
-   if (secctx)
-   security_release_secctx(secctx, secctx_sz);
+   if (secctx) {
+   lsmcontext_init(&scaff, secctx, secctx_sz, 0);
+   security_release_secctx(&scaff);
+   }
 err_get_secctx_failed:
kfree(tcomplete);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 71ee34d160c3..ad36d5fd7a84 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -1272,12 +1272,16 @@ int ceph_security_init_secctx(struct dentry *dentry, 
umode_t mode,
 
 void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
 {
+#ifdef CONFIG_CEPH_FS_SECURITY_LABEL
+   struct lsmcontext scaff; /* scaffolding */
+#endif
 #ifdef CONFIG_CEPH_FS_POSIX_ACL
posix_acl_release(as_ctx->acl);
posix_acl_release(as_ctx->default_acl);
 #endif
 #ifdef CONFIG_CEPH_FS_SECURITY_LABEL
-   security_release_secctx(as_ctx->sec_ctx, as_ctx->sec_ctxlen);
+   lsmcontext_init(&scaff, as_ctx->sec_ctx, as_ctx->sec_ctxlen, 0);
+   security_release_secctx(&scaff);
 #endif
if (as_ctx->pagelist)
ceph_pagelist_release(as_ctx->pagelist);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2e2dac29a9e9..8fe09ce2eff7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -130,8 +130,12 @@ nfs4_label_init_security(struct inode *dir, struct dentry 
*dentry,
 static inline void
 nfs4_label_release_security(struct nfs4_label *label)
 {
-   if (label)
-   security_release_secctx(label->label, label->len);
+   struct lsmcontext scaff; /* scaffolding */
+
+   if (label) {
+   lsmcontext_init(&scaff, label->label, label->len, 0);
+   security_release_secctx(&scaff);
+   }
 }
 static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label 
*label)
 {
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 996ac01ee977..61d6b8a0e8f0 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2496,6 +2496,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh 
*fhp,
int err;
struct nfs4_acl *acl = NULL;
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+   struct lsmcontext scaff; /* scaffolding */
void *context = NULL;
int contextlen;
 #endif
@@ -2998,8 +2999,10 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh 
*fhp,
 
 out:
 #ifdef CONFI

[PATCH v19 13/23] LSM: Specify which LSM to display

2020-07-24 Thread Casey Schaufler
Create a new entry "display" in the procfs attr directory for
controlling which LSM security information is displayed for a
process. A process can only read or write its own display value.

The name of an active LSM that supplies hooks for
human readable data may be written to "display" to set the
value. The name of the LSM currently in use can be read from
"display". At this point there can only be one LSM capable
of display active. A helper function lsm_task_display() is
provided to get the display slot for a task_struct.

Setting the "display" requires that all security modules using
setprocattr hooks allow the action. Each security module is
responsible for defining its policy.

AppArmor hook provided by John Johansen 
SELinux hook provided by Stephen Smalley 

Reviewed-by: Kees Cook 
Acked-by: Stephen Smalley 
Acked-by: Paul Moore 
Signed-off-by: Casey Schaufler 
---
 fs/proc/base.c   |   1 +
 include/linux/lsm_hooks.h|  17 +++
 security/apparmor/include/apparmor.h |   3 +-
 security/apparmor/lsm.c  |  32 +
 security/security.c  | 167 ---
 security/selinux/hooks.c |  11 ++
 security/selinux/include/classmap.h  |   2 +-
 security/smack/smack_lsm.c   |   7 ++
 8 files changed, 221 insertions(+), 19 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index d86c0afc8a85..40471a12ced2 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2794,6 +2794,7 @@ static const struct pid_entry attr_dir_stuff[] = {
ATTR(NULL, "fscreate",  0666),
ATTR(NULL, "keycreate", 0666),
ATTR(NULL, "sockcreate",0666),
+   ATTR(NULL, "display",   0666),
 #ifdef CONFIG_SECURITY_SMACK
DIR("smack",0555,
proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index c9f792066d86..6908fa03cf31 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1647,4 +1647,21 @@ static inline void security_delete_hooks(struct 
security_hook_list *hooks,
 
 extern int lsm_inode_alloc(struct inode *inode);
 
+/**
+ * lsm_task_display - the "display" LSM for this task
+ * @task: The task to report on
+ *
+ * Returns the task's display LSM slot.
+ */
+static inline int lsm_task_display(struct task_struct *task)
+{
+#ifdef CONFIG_SECURITY
+   int *display = task->security;
+
+   if (display)
+   return *display;
+#endif
+   return LSMBLOB_INVALID;
+}
+
 #endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/apparmor/include/apparmor.h 
b/security/apparmor/include/apparmor.h
index 1fbabdb565a8..b1622fcb4394 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -28,8 +28,9 @@
 #define AA_CLASS_SIGNAL10
 #define AA_CLASS_NET   14
 #define AA_CLASS_LABEL 16
+#define AA_CLASS_DISPLAY_LSM   17
 
-#define AA_CLASS_LAST  AA_CLASS_LABEL
+#define AA_CLASS_LAST  AA_CLASS_DISPLAY_LSM
 
 /* Control parameters settable through module/boot flags */
 extern enum audit_mode aa_g_audit;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 432915c1d427..31a6f11890f1 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -612,6 +612,25 @@ static int apparmor_getprocattr(struct task_struct *task, 
char *name,
return error;
 }
 
+
+static int profile_display_lsm(struct aa_profile *profile,
+  struct common_audit_data *sa)
+{
+   struct aa_perms perms = { };
+   unsigned int state;
+
+   state = PROFILE_MEDIATES(profile, AA_CLASS_DISPLAY_LSM);
+   if (state) {
+   aa_compute_perms(profile->policy.dfa, state, &perms);
+   aa_apply_modes_to_perms(profile, &perms);
+   aad(sa)->label = &profile->label;
+
+   return aa_check_perms(profile, &perms, AA_MAY_WRITE, sa, NULL);
+   }
+
+   return 0;
+}
+
 static int apparmor_setprocattr(const char *name, void *value,
size_t size)
 {
@@ -623,6 +642,19 @@ static int apparmor_setprocattr(const char *name, void 
*value,
if (size == 0)
return -EINVAL;
 
+   /* LSM infrastructure does actual setting of display if allowed */
+   if (!strcmp(name, "display")) {
+   struct aa_profile *profile;
+   struct aa_label *label;
+
+   aad(&sa)->info = "set display lsm";
+   label = begin_current_label_crit_section();
+   error = fn_for_each_confined(label, profile,
+profile_display_lsm(profile, &sa));
+   end_current_label_crit_section(label);
+   return error;
+   }
+
/* AppArmor requires that the buffer must be null terminated atm */
if (args[size - 1] != '\0') {
/* null terminat

[PATCH v19 12/23] IMA: Change internal interfaces to use lsmblobs

2020-07-24 Thread Casey Schaufler
The IMA interfaces ima_get_action() and ima_match_policy()
call LSM functions that use lsmblobs. Change the IMA functions
to pass the lsmblob to be compatible with the LSM functions.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
cc: linux-integr...@vger.kernel.org
---
 security/integrity/ima/ima.h  | 11 +
 security/integrity/ima/ima_api.c  | 10 
 security/integrity/ima/ima_appraise.c |  6 ++---
 security/integrity/ima/ima_main.c | 35 +++
 security/integrity/ima/ima_policy.c   | 14 +--
 5 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index d72af93f8d6f..0c4787c71162 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -236,9 +236,9 @@ static inline void ima_process_queued_keys(void) {}
 #endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
 
 /* LIM API function definitions */
-int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
-  int mask, enum ima_hooks func, int *pcr,
-  struct ima_template_desc **template_desc,
+int ima_get_action(struct inode *inode, const struct cred *cred,
+  struct lsmblob *blob, int mask, enum ima_hooks func,
+  int *pcr, struct ima_template_desc **template_desc,
   const char *keyring);
 int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
@@ -264,8 +264,9 @@ void ima_free_template_entry(struct ima_template_entry 
*entry);
 const char *ima_d_path(const struct path *path, char **pathbuf, char 
*filename);
 
 /* IMA policy related functions */
-int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
-enum ima_hooks func, int mask, int flags, int *pcr,
+int ima_match_policy(struct inode *inode, const struct cred *cred,
+struct lsmblob *blob, enum ima_hooks func, int mask,
+int flags, int *pcr,
 struct ima_template_desc **template_desc,
 const char *keyring);
 void ima_init_policy(void);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index bf22de8b7ce0..ea78825e0033 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -164,7 +164,7 @@ void ima_add_violation(struct file *file, const unsigned 
char *filename,
  * ima_get_action - appraise & measure decision based on policy.
  * @inode: pointer to inode to measure
  * @cred: pointer to credentials structure to validate
- * @secid: secid of the task being validated
+ * @blob: LSM data of the task being validated
  * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXEC,
  *MAY_APPEND)
  * @func: caller identifier
@@ -183,16 +183,16 @@ void ima_add_violation(struct file *file, const unsigned 
char *filename,
  * Returns IMA_MEASURE, IMA_APPRAISE mask.
  *
  */
-int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
-  int mask, enum ima_hooks func, int *pcr,
-  struct ima_template_desc **template_desc,
+int ima_get_action(struct inode *inode, const struct cred *cred,
+  struct lsmblob *blob, int mask, enum ima_hooks func,
+  int *pcr, struct ima_template_desc **template_desc,
   const char *keyring)
 {
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
 
flags &= ima_policy_flag;
 
-   return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
+   return ima_match_policy(inode, cred, blob, func, mask, flags, pcr,
template_desc, keyring);
 }
 
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 3dfb573c7171..bf66e3e6f398 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -54,10 +54,8 @@ int ima_must_appraise(struct inode *inode, int mask, enum 
ima_hooks func)
return 0;
 
security_task_getsecid(current, &blob);
-   /* scaffolding the .secid[0] */
-   return ima_match_policy(inode, current_cred(), blob.secid[0], func,
-   mask, IMA_APPRAISE | IMA_HASH, NULL, NULL,
-   NULL);
+   return ima_match_policy(inode, current_cred(), &blob, func, mask,
+   IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
 }
 
 static int ima_fix_xattr(struct dentry *dentry,
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index e70d8626208c..5093f9b4db8b 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -188,8 +188,8 @@ void ima_file_free(struct file *file)
 }
 
 static int process_measurement(struc

[PATCH v19 11/23] LSM: Use lsmblob in security_cred_getsecid

2020-07-24 Thread Casey Schaufler
Change the security_cred_getsecid() interface to fill in a
lsmblob instead of a u32 secid. The associated data elements
in the audit sub-system are changed from a secid to a lsmblob
to accommodate multiple possible LSM audit users.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Acked-by: Paul Moore 
Signed-off-by: Casey Schaufler 
cc: linux-integr...@vger.kernel.org
---
 include/linux/security.h  |  2 +-
 kernel/audit.c| 25 +++
 kernel/audit.h|  5 +++--
 kernel/auditsc.c  | 33 +++
 security/integrity/ima/ima_main.c |  8 
 security/security.c   | 12 ---
 6 files changed, 36 insertions(+), 49 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index b804bf896552..84ad4404f7c1 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -461,7 +461,7 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
 void security_cred_free(struct cred *cred);
 int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t 
gfp);
 void security_transfer_creds(struct cred *new, const struct cred *old);
-void security_cred_getsecid(const struct cred *c, u32 *secid);
+void security_cred_getsecid(const struct cred *c, struct lsmblob *blob);
 int security_kernel_act_as(struct cred *new, struct lsmblob *blob);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
 int security_kernel_module_request(char *kmod_name);
diff --git a/kernel/audit.c b/kernel/audit.c
index 9861e1e11a4d..ff381344f950 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -125,7 +125,7 @@ static u32  audit_backlog_wait_time = 
AUDIT_BACKLOG_WAIT_TIME;
 /* The identity of the user shutting down the audit system. */
 kuid_t audit_sig_uid = INVALID_UID;
 pid_t  audit_sig_pid = -1;
-u32audit_sig_sid = 0;
+struct lsmblob audit_sig_lsm;
 
 /* Records can be lost in several ways:
0) [suppressed in audit_alloc]
@@ -1430,29 +1430,21 @@ static int audit_receive_msg(struct sk_buff *skb, 
struct nlmsghdr *nlh)
}
case AUDIT_SIGNAL_INFO:
len = 0;
-   if (audit_sig_sid) {
-   struct lsmblob blob;
-
-   /*
-* lsmblob_init sets all values in the lsmblob
-* to audit_sig_sid. This is temporary until
-* audit_sig_sid is converted to a lsmblob, which
-* happens later in this patch set.
-*/
-   lsmblob_init(&blob, audit_sig_sid);
-   err = security_secid_to_secctx(&blob, &ctx, &len);
+   if (lsmblob_is_set(&audit_sig_lsm)) {
+   err = security_secid_to_secctx(&audit_sig_lsm, &ctx,
+  &len);
if (err)
return err;
}
sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
if (!sig_data) {
-   if (audit_sig_sid)
+   if (lsmblob_is_set(&audit_sig_lsm))
security_release_secctx(ctx, len);
return -ENOMEM;
}
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
sig_data->pid = audit_sig_pid;
-   if (audit_sig_sid) {
+   if (lsmblob_is_set(&audit_sig_lsm)) {
memcpy(sig_data->ctx, ctx, len);
security_release_secctx(ctx, len);
}
@@ -2336,7 +2328,6 @@ int audit_set_loginuid(kuid_t loginuid)
 int audit_signal_info(int sig, struct task_struct *t)
 {
kuid_t uid = current_uid(), auid;
-   struct lsmblob blob;
 
if (auditd_test_task(t) &&
(sig == SIGTERM || sig == SIGHUP ||
@@ -2347,9 +2338,7 @@ int audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = auid;
else
audit_sig_uid = uid;
-   security_task_getsecid(current, &blob);
-   /* scaffolding until audit_sig_sid is converted */
-   audit_sig_sid = blob.secid[0];
+   security_task_getsecid(current, &audit_sig_lsm);
}
 
return audit_signal_info_syscall(t);
diff --git a/kernel/audit.h b/kernel/audit.h
index f0233dc40b17..6ab012e5fe98 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -134,7 +135,7 @@ struct audit_context {
kuid_t  target_auid;
kuid_t  target_uid;
unsigned inttarget_sessionid;
-   u32 target_sid;
+   struct lsmblob  target_lsm;
chartar

[PATCH v19 10/23] LSM: Use lsmblob in security_inode_getsecid

2020-07-24 Thread Casey Schaufler
Change the security_inode_getsecid() interface to fill in a
lsmblob structure instead of a u32 secid. This allows for its
callers to gather data from all registered LSMs. Data is provided
for IMA and audit.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Signed-off-by: Casey Schaufler 
Acked-by: Stephen Smalley 
cc: linux-integr...@vger.kernel.org
---
 include/linux/security.h|  7 ---
 kernel/auditsc.c|  6 +-
 security/integrity/ima/ima_policy.c |  4 +---
 security/security.c | 11 +--
 4 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 4037391a29b8..b804bf896552 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -434,7 +434,7 @@ int security_inode_killpriv(struct dentry *dentry);
 int security_inode_getsecurity(struct inode *inode, const char *name, void 
**buffer, bool alloc);
 int security_inode_setsecurity(struct inode *inode, const char *name, const 
void *value, size_t size, int flags);
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t 
buffer_size);
-void security_inode_getsecid(struct inode *inode, u32 *secid);
+void security_inode_getsecid(struct inode *inode, struct lsmblob *blob);
 int security_inode_copy_up(struct dentry *src, struct cred **new);
 int security_inode_copy_up_xattr(const char *name);
 int security_kernfs_init_security(struct kernfs_node *kn_dir,
@@ -957,9 +957,10 @@ static inline int security_inode_listsecurity(struct inode 
*inode, char *buffer,
return 0;
 }
 
-static inline void security_inode_getsecid(struct inode *inode, u32 *secid)
+static inline void security_inode_getsecid(struct inode *inode,
+  struct lsmblob *blob)
 {
-   *secid = 0;
+   lsmblob_init(blob, 0);
 }
 
 static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 4928159d1ce2..d3e1bea08da0 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1946,13 +1946,17 @@ static void audit_copy_inode(struct audit_names *name,
 const struct dentry *dentry,
 struct inode *inode, unsigned int flags)
 {
+   struct lsmblob blob;
+
name->ino   = inode->i_ino;
name->dev   = inode->i_sb->s_dev;
name->mode  = inode->i_mode;
name->uid   = inode->i_uid;
name->gid   = inode->i_gid;
name->rdev  = inode->i_rdev;
-   security_inode_getsecid(inode, &name->osid);
+   security_inode_getsecid(inode, &blob);
+   /* scaffolding until osid is updated */
+   name->osid = blob.secid[0];
if (flags & AUDIT_INODE_NOEVAL) {
name->fcap_ver = -1;
return;
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 9a0f462e8891..8f9c66a0a612 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -479,7 +479,6 @@ static bool ima_match_rules(struct ima_rule_entry *rule, 
struct inode *inode,
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0;
-   u32 osid;
struct lsmblob lsmdata;
 
if (!ima_lsm_isset(rule->lsm[i].rules)) {
@@ -492,8 +491,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, 
struct inode *inode,
case LSM_OBJ_USER:
case LSM_OBJ_ROLE:
case LSM_OBJ_TYPE:
-   security_inode_getsecid(inode, &osid);
-   lsmblob_init(&lsmdata, osid);
+   security_inode_getsecid(inode, &lsmdata);
rc = security_filter_rule_match(&lsmdata,
rule->lsm[i].type,
Audit_equal,
diff --git a/security/security.c b/security/security.c
index 01c1561901fa..d641c6dc5933 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1442,9 +1442,16 @@ int security_inode_listsecurity(struct inode *inode, 
char *buffer, size_t buffer
 }
 EXPORT_SYMBOL(security_inode_listsecurity);
 
-void security_inode_getsecid(struct inode *inode, u32 *secid)
+void security_inode_getsecid(struct inode *inode, struct lsmblob *blob)
 {
-   call_void_hook(inode_getsecid, inode, secid);
+   struct security_hook_list *hp;
+
+   lsmblob_init(blob, 0);
+   hlist_for_each_entry(hp, &security_hook_heads.inode_getsecid, list) {
+   if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+   continue;
+   hp->hook.inode_getsecid(inode, &blob->secid[hp->lsmid->slot]);
+   }
 }
 
 int security_inode_copy_up(struct dentry *src, struct cred **new)
-- 
2.24.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo

[PATCH v19 09/23] LSM: Use lsmblob in security_task_getsecid

2020-07-24 Thread Casey Schaufler
Change the security_task_getsecid() interface to fill in
a lsmblob structure instead of a u32 secid in support of
LSM stacking. Audit interfaces will need to collect all
possible secids for possible reporting.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
cc: linux-integr...@vger.kernel.org
---
 drivers/android/binder.c  | 12 +--
 include/linux/security.h  |  7 ++--
 kernel/audit.c| 16 -
 kernel/auditfilter.c  |  4 +--
 kernel/auditsc.c  | 25 +++---
 net/netlabel/netlabel_unlabeled.c |  5 ++-
 net/netlabel/netlabel_user.h  |  6 +++-
 security/integrity/ima/ima_appraise.c | 10 +++---
 security/integrity/ima/ima_main.c | 49 +++
 security/security.c   | 12 +--
 10 files changed, 76 insertions(+), 70 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 41f89bb3c7f1..46e2a26089cc 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3106,20 +3106,10 @@ static void binder_transaction(struct binder_proc *proc,
t->priority = task_nice(current);
 
if (target_node && target_node->txn_security_ctx) {
-   u32 secid;
struct lsmblob blob;
size_t added_size;
 
-   security_task_getsecid(proc->tsk, &secid);
-   /*
-* Later in this patch set security_task_getsecid() will
-* provide a lsmblob instead of a secid. lsmblob_init
-* is used to ensure that all the secids in the lsmblob
-* get the value returned from security_task_getsecid(),
-* which means that the one expected by
-* security_secid_to_secctx() will be set.
-*/
-   lsmblob_init(&blob, secid);
+   security_task_getsecid(proc->tsk, &blob);
ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
if (ret) {
return_error = BR_FAILED_REPLY;
diff --git a/include/linux/security.h b/include/linux/security.h
index 7883975ea6b0..4037391a29b8 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -476,7 +476,7 @@ int security_task_fix_setgid(struct cred *new, const struct 
cred *old,
 int security_task_setpgid(struct task_struct *p, pid_t pgid);
 int security_task_getpgid(struct task_struct *p);
 int security_task_getsid(struct task_struct *p);
-void security_task_getsecid(struct task_struct *p, u32 *secid);
+void security_task_getsecid(struct task_struct *p, struct lsmblob *blob);
 int security_task_setnice(struct task_struct *p, int nice);
 int security_task_setioprio(struct task_struct *p, int ioprio);
 int security_task_getioprio(struct task_struct *p);
@@ -1141,9 +1141,10 @@ static inline int security_task_getsid(struct 
task_struct *p)
return 0;
 }
 
-static inline void security_task_getsecid(struct task_struct *p, u32 *secid)
+static inline void security_task_getsecid(struct task_struct *p,
+ struct lsmblob *blob)
 {
-   *secid = 0;
+   lsmblob_init(blob, 0);
 }
 
 static inline int security_task_setnice(struct task_struct *p, int nice)
diff --git a/kernel/audit.c b/kernel/audit.c
index 70f331825401..9861e1e11a4d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2123,19 +2123,12 @@ int audit_log_task_context(struct audit_buffer *ab)
char *ctx = NULL;
unsigned len;
int error;
-   u32 sid;
struct lsmblob blob;
 
-   security_task_getsecid(current, &sid);
-   if (!sid)
+   security_task_getsecid(current, &blob);
+   if (!lsmblob_is_set(&blob))
return 0;
 
-   /*
-* lsmblob_init sets all values in the lsmblob to sid.
-* This is temporary until security_task_getsecid is converted
-* to use a lsmblob, which happens later in this patch set.
-*/
-   lsmblob_init(&blob, sid);
error = security_secid_to_secctx(&blob, &ctx, &len);
if (error) {
if (error != -EINVAL)
@@ -2343,6 +2336,7 @@ int audit_set_loginuid(kuid_t loginuid)
 int audit_signal_info(int sig, struct task_struct *t)
 {
kuid_t uid = current_uid(), auid;
+   struct lsmblob blob;
 
if (auditd_test_task(t) &&
(sig == SIGTERM || sig == SIGHUP ||
@@ -2353,7 +2347,9 @@ int audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = auid;
else
audit_sig_uid = uid;
-   security_task_getsecid(current, &audit_sig_sid);
+   security_task_getsecid(current, &blob);
+   /* scaffolding until audit_sig_sid is converted */
+   audit_sig_sid = blob.secid[0];
}
 
return audit_signal_info_syscall(t);
diff --git a

[PATCH v19 08/23] LSM: Use lsmblob in security_ipc_getsecid

2020-07-24 Thread Casey Schaufler
There may be more than one LSM that provides IPC data
for auditing. Change security_ipc_getsecid() to fill in
a lsmblob structure instead of the u32 secid. The
audit data structure containing the secid will be updated
later, so there is a bit of scaffolding here.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
---
 include/linux/security.h |  7 ---
 kernel/auditsc.c |  7 ++-
 security/security.c  | 12 +---
 3 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index df5e4e8d8e2c..7883975ea6b0 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -493,7 +493,7 @@ int security_task_prctl(int option, unsigned long arg2, 
unsigned long arg3,
unsigned long arg4, unsigned long arg5);
 void security_task_to_inode(struct task_struct *p, struct inode *inode);
 int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
-void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
+void security_ipc_getsecid(struct kern_ipc_perm *ipcp, struct lsmblob *blob);
 int security_msg_msg_alloc(struct msg_msg *msg);
 void security_msg_msg_free(struct msg_msg *msg);
 int security_msg_queue_alloc(struct kern_ipc_perm *msq);
@@ -1214,9 +1214,10 @@ static inline int security_ipc_permission(struct 
kern_ipc_perm *ipcp,
return 0;
 }
 
-static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 
*secid)
+static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp,
+struct lsmblob *blob)
 {
-   *secid = 0;
+   lsmblob_init(blob, 0);
 }
 
 static inline int security_msg_msg_alloc(struct msg_msg *msg)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 3c9525c72c89..ff30714c89dc 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2307,11 +2307,16 @@ void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr 
*mqstat)
 void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
struct audit_context *context = audit_context();
+   struct lsmblob blob;
context->ipc.uid = ipcp->uid;
context->ipc.gid = ipcp->gid;
context->ipc.mode = ipcp->mode;
context->ipc.has_perm = 0;
-   security_ipc_getsecid(ipcp, &context->ipc.osid);
+   security_ipc_getsecid(ipcp, &blob);
+   /* context->ipc.osid will be changed to a lsmblob later in
+* the patch series. This will allow auditing of all the object
+* labels associated with the ipc object. */
+   context->ipc.osid = lsmblob_value(&blob);
context->type = AUDIT_IPC;
 }
 
diff --git a/security/security.c b/security/security.c
index ce0934395c53..c74c7722e5f4 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1866,10 +1866,16 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, 
short flag)
return call_int_hook(ipc_permission, 0, ipcp, flag);
 }
 
-void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
+void security_ipc_getsecid(struct kern_ipc_perm *ipcp, struct lsmblob *blob)
 {
-   *secid = 0;
-   call_void_hook(ipc_getsecid, ipcp, secid);
+   struct security_hook_list *hp;
+
+   lsmblob_init(blob, 0);
+   hlist_for_each_entry(hp, &security_hook_heads.ipc_getsecid, list) {
+   if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+   continue;
+   hp->hook.ipc_getsecid(ipcp, &blob->secid[hp->lsmid->slot]);
+   }
 }
 
 int security_msg_msg_alloc(struct msg_msg *msg)
-- 
2.24.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit



[PATCH v19 07/23] LSM: Use lsmblob in security_secid_to_secctx

2020-07-24 Thread Casey Schaufler
Change security_secid_to_secctx() to take a lsmblob as input
instead of a u32 secid. It will then call the LSM hooks
using the lsmblob element allocated for that module. The
callers have been updated as well. This allows for the
possibility that more than one module may be called upon
to translate a secid to a string, as can occur in the
audit code.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
---
 drivers/android/binder.c| 12 +-
 include/linux/security.h|  5 +++--
 include/net/scm.h   |  8 ++-
 kernel/audit.c  | 20 +++--
 kernel/auditsc.c| 28 +++
 net/ipv4/ip_sockglue.c  |  5 +
 net/netfilter/nf_conntrack_netlink.c| 14 ++--
 net/netfilter/nf_conntrack_standalone.c |  4 +++-
 net/netfilter/nfnetlink_queue.c | 11 +++--
 net/netlabel/netlabel_unlabeled.c   | 30 +
 net/netlabel/netlabel_user.c|  6 ++---
 security/security.c | 11 +
 12 files changed, 117 insertions(+), 37 deletions(-)

diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f50c5f182bb5..41f89bb3c7f1 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3107,10 +3107,20 @@ static void binder_transaction(struct binder_proc *proc,
 
if (target_node && target_node->txn_security_ctx) {
u32 secid;
+   struct lsmblob blob;
size_t added_size;
 
security_task_getsecid(proc->tsk, &secid);
-   ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
+   /*
+* Later in this patch set security_task_getsecid() will
+* provide a lsmblob instead of a secid. lsmblob_init
+* is used to ensure that all the secids in the lsmblob
+* get the value returned from security_task_getsecid(),
+* which means that the one expected by
+* security_secid_to_secctx() will be set.
+*/
+   lsmblob_init(&blob, secid);
+   ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
if (ret) {
return_error = BR_FAILED_REPLY;
return_error_param = ret;
diff --git a/include/linux/security.h b/include/linux/security.h
index 98176faaaba5..df5e4e8d8e2c 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -522,7 +522,7 @@ int security_setprocattr(const char *lsm, const char *name, 
void *value,
 size_t size);
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_ismaclabel(const char *name);
-int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
+int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 
*seclen);
 int security_secctx_to_secid(const char *secdata, u32 seclen,
 struct lsmblob *blob);
 void security_release_secctx(char *secdata, u32 seclen);
@@ -1336,7 +1336,8 @@ static inline int security_ismaclabel(const char *name)
return 0;
 }
 
-static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 
*seclen)
+static inline int security_secid_to_secctx(struct lsmblob *blob,
+  char **secdata, u32 *seclen)
 {
return -EOPNOTSUPP;
 }
diff --git a/include/net/scm.h b/include/net/scm.h
index c09f2dfeec88..31ae605fcc0a 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -97,12 +97,8 @@ static inline void scm_passec(struct socket *sock, struct 
msghdr *msg, struct sc
int err;
 
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
-   /* There can currently be only one value in the lsmblob,
-* so getting it from lsmblob_value is appropriate until
-* security_secid_to_secctx() is converted to taking a
-* lsmblob directly. */
-   err = security_secid_to_secctx(lsmblob_value(&scm->lsmblob),
-  &secdata, &seclen);
+   err = security_secid_to_secctx(&scm->lsmblob, &secdata,
+  &seclen);
 
if (!err) {
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, 
secdata);
diff --git a/kernel/audit.c b/kernel/audit.c
index 8c201f414226..70f331825401 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1431,7 +1431,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct 
nlmsghdr *nlh)
case AUDIT_SIGNAL_INFO:
len = 0;
if (audit_sig_sid) {
-   err = security_secid_to_secctx(audit_sig_sid, &ctx, 
&len);
+   struct lsmblob blob;
+
+   /*
+   

[PATCH v19 06/23] LSM: Use lsmblob in security_secctx_to_secid

2020-07-24 Thread Casey Schaufler
Change security_secctx_to_secid() to fill in a lsmblob instead
of a u32 secid. Multiple LSMs may be able to interpret the
string, and this allows for setting whichever secid is
appropriate. Change security_secmark_relabel_packet() to use a
lsmblob instead of a u32 secid. In some other cases there is
scaffolding where interfaces have yet to be converted.

Reviewed-by: Kees Cook 
Signed-off-by: Casey Schaufler 
Cc: net...@vger.kernel.org
---
 include/linux/security.h  | 30 +++
 include/net/scm.h |  7 +--
 kernel/cred.c |  4 +---
 net/ipv4/ip_sockglue.c|  6 --
 net/netfilter/nft_meta.c  | 18 +---
 net/netfilter/xt_SECMARK.c|  9 ++--
 net/netlabel/netlabel_unlabeled.c | 23 +
 security/security.c   | 34 ++-
 8 files changed, 98 insertions(+), 33 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index d81e8886d799..98176faaaba5 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -189,6 +189,27 @@ static inline bool lsmblob_equal(struct lsmblob *bloba, 
struct lsmblob *blobb)
return !memcmp(bloba, blobb, sizeof(*bloba));
 }
 
+/**
+ * lsmblob_value - find the first non-zero value in an lsmblob structure.
+ * @blob: Pointer to the data
+ *
+ * This needs to be used with extreme caution, as the cases where
+ * it is appropriate are rare.
+ *
+ * Return the first secid value set in the lsmblob.
+ * There should only be one.
+ */
+static inline u32 lsmblob_value(const struct lsmblob *blob)
+{
+   int i;
+
+   for (i = 0; i < LSMBLOB_ENTRIES; i++)
+   if (blob->secid[i])
+   return blob->secid[i];
+
+   return 0;
+}
+
 /* These functions are in security/commoncap.c */
 extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
   int cap, unsigned int opts);
@@ -502,7 +523,8 @@ int security_setprocattr(const char *lsm, const char *name, 
void *value,
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_ismaclabel(const char *name);
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
-int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
+int security_secctx_to_secid(const char *secdata, u32 seclen,
+struct lsmblob *blob);
 void security_release_secctx(char *secdata, u32 seclen);
 void security_inode_invalidate_secctx(struct inode *inode);
 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
@@ -1321,7 +1343,7 @@ static inline int security_secid_to_secctx(u32 secid, 
char **secdata, u32 *secle
 
 static inline int security_secctx_to_secid(const char *secdata,
   u32 seclen,
-  u32 *secid)
+  struct lsmblob *blob)
 {
return -EOPNOTSUPP;
 }
@@ -1411,7 +1433,7 @@ void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req);
 void security_inet_conn_established(struct sock *sk,
struct sk_buff *skb);
-int security_secmark_relabel_packet(u32 secid);
+int security_secmark_relabel_packet(struct lsmblob *blob);
 void security_secmark_refcount_inc(void);
 void security_secmark_refcount_dec(void);
 int security_tun_dev_alloc_security(void **security);
@@ -1584,7 +1606,7 @@ static inline void security_inet_conn_established(struct 
sock *sk,
 {
 }
 
-static inline int security_secmark_relabel_packet(u32 secid)
+static inline int security_secmark_relabel_packet(struct lsmblob *blob)
 {
return 0;
 }
diff --git a/include/net/scm.h b/include/net/scm.h
index e2e71c4bf9d0..c09f2dfeec88 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -97,8 +97,11 @@ static inline void scm_passec(struct socket *sock, struct 
msghdr *msg, struct sc
int err;
 
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
-   /* Scaffolding - it has to be element 0 for now */
-   err = security_secid_to_secctx(scm->lsmblob.secid[0],
+   /* There can currently be only one value in the lsmblob,
+* so getting it from lsmblob_value is appropriate until
+* security_secid_to_secctx() is converted to taking a
+* lsmblob directly. */
+   err = security_secid_to_secctx(lsmblob_value(&scm->lsmblob),
   &secdata, &seclen);
 
if (!err) {
diff --git a/kernel/cred.c b/kernel/cred.c
index 22e0e7cbefde..848306c7d823 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -757,14 +757,12 @@ EXPORT_SYMBOL(set_security_override);
 int set_security_override_from_ctx(struct cred *new, const char *secctx)
 {
struct lsmblob blob;
-   u32 secid;
int ret;
 
-   ret = security_

[PATCH v19 05/23] net: Prepare UDS for security module stacking

2020-07-24 Thread Casey Schaufler
Change the data used in UDS SO_PEERSEC processing from a
secid to a more general struct lsmblob. Update the
security_socket_getpeersec_dgram() interface to use the
lsmblob. There is a small amount of scaffolding code
that will come out when the security_secid_to_secctx()
code is brought in line with the lsmblob.

Signed-off-by: Casey Schaufler 
---
 include/linux/security.h |  7 +--
 include/net/af_unix.h|  2 +-
 include/net/scm.h|  8 +---
 net/ipv4/ip_sockglue.c   |  8 +---
 net/unix/af_unix.c   |  6 +++---
 security/security.c  | 18 +++---
 6 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 6d403a522918..d81e8886d799 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1397,7 +1397,8 @@ int security_socket_shutdown(struct socket *sock, int 
how);
 int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb);
 int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
  int __user *optlen, unsigned len);
-int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, 
u32 *secid);
+int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
+struct lsmblob *blob);
 int security_sk_alloc(struct sock *sk, int family, gfp_t priority);
 void security_sk_free(struct sock *sk);
 void security_sk_clone(const struct sock *sk, struct sock *newsk);
@@ -1535,7 +1536,9 @@ static inline int 
security_socket_getpeersec_stream(struct socket *sock, char __
return -ENOPROTOOPT;
 }
 
-static inline int security_socket_getpeersec_dgram(struct socket *sock, struct 
sk_buff *skb, u32 *secid)
+static inline int security_socket_getpeersec_dgram(struct socket *sock,
+  struct sk_buff *skb,
+  struct lsmblob *blob)
 {
return -ENOPROTOOPT;
 }
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index f42fdddecd41..a86da0cb5ec1 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -36,7 +36,7 @@ struct unix_skb_parms {
kgid_t  gid;
struct scm_fp_list  *fp;/* Passed files */
 #ifdef CONFIG_SECURITY_NETWORK
-   u32 secid;  /* Security ID  */
+   struct lsmblob  lsmblob;/* Security LSM data*/
 #endif
u32 consumed;
 } __randomize_layout;
diff --git a/include/net/scm.h b/include/net/scm.h
index 1ce365f4c256..e2e71c4bf9d0 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -33,7 +33,7 @@ struct scm_cookie {
struct scm_fp_list  *fp;/* Passed files */
struct scm_credscreds;  /* Skb credentials  */
 #ifdef CONFIG_SECURITY_NETWORK
-   u32 secid;  /* Passed security ID   */
+   struct lsmblob  lsmblob;/* Passed LSM data  */
 #endif
 };
 
@@ -46,7 +46,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl);
 #ifdef CONFIG_SECURITY_NETWORK
 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct 
scm_cookie *scm)
 {
-   security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
+   security_socket_getpeersec_dgram(sock, NULL, &scm->lsmblob);
 }
 #else
 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct 
scm_cookie *scm)
@@ -97,7 +97,9 @@ static inline void scm_passec(struct socket *sock, struct 
msghdr *msg, struct sc
int err;
 
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
-   err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
+   /* Scaffolding - it has to be element 0 for now */
+   err = security_secid_to_secctx(scm->lsmblob.secid[0],
+  &secdata, &seclen);
 
if (!err) {
put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, 
secdata);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 84ec3703c909..3ea1103b4c29 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -130,15 +130,17 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, 
struct sk_buff *skb,
 
 static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 {
+   struct lsmblob lb;
char *secdata;
-   u32 seclen, secid;
+   u32 seclen;
int err;
 
-   err = security_socket_getpeersec_dgram(NULL, skb, &secid);
+   err = security_socket_getpeersec_dgram(NULL, skb, &lb);
if (err)
return;
 
-   err = security_secid_to_secctx(secid, &secdata, &seclen);
+   /* Scaffolding - it has to be element 0 */
+   err = security_secid_to_secctx(lb.secid[0], &secdata, &seclen);
if (err)
return;
 
diff --git a/net/u

[PATCH v19 03/23] LSM: Use lsmblob in security_audit_rule_match

2020-07-24 Thread Casey Schaufler
Change the secid parameter of security_audit_rule_match
to a lsmblob structure pointer. Pass the entry from the
lsmblob structure for the approprite slot to the LSM hook.

Change the users of security_audit_rule_match to use the
lsmblob instead of a u32. The scaffolding function lsmblob_init()
fills the blob with the value of the old secid, ensuring that
it is available to the appropriate module hook. The sources of
the secid, security_task_getsecid() and security_inode_getsecid(),
will be converted to use the blob structure later in the series.
At the point the use of lsmblob_init() is dropped.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
---
 include/linux/security.h|  7 ---
 kernel/auditfilter.c|  6 --
 kernel/auditsc.c| 14 ++
 security/integrity/ima/ima.h|  4 ++--
 security/integrity/ima/ima_policy.c |  7 +--
 security/security.c | 10 --
 6 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 591dae299c6f..294410533b51 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1878,7 +1878,8 @@ static inline int security_key_getsecurity(struct key 
*key, char **_buffer)
 #ifdef CONFIG_SECURITY
 int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
 int security_audit_rule_known(struct audit_krule *krule);
-int security_audit_rule_match(u32 secid, u32 field, u32 op, void **lsmrule);
+int security_audit_rule_match(struct lsmblob *blob, u32 field, u32 op,
+ void **lsmrule);
 void security_audit_rule_free(void **lsmrule);
 
 #else
@@ -1894,8 +1895,8 @@ static inline int security_audit_rule_known(struct 
audit_krule *krule)
return 0;
 }
 
-static inline int security_audit_rule_match(u32 secid, u32 field, u32 op,
-   void **lsmrule)
+static inline int security_audit_rule_match(struct lsmblob *blob, u32 field,
+   u32 op, void **lsmrule)
 {
return 0;
 }
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index f9a632ae7be1..15a7fb80d6a7 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1331,6 +1331,7 @@ int audit_filter(int msgtype, unsigned int listtype)
struct audit_field *f = &e->rule.fields[i];
pid_t pid;
u32 sid;
+   struct lsmblob blob;
 
switch (f->type) {
case AUDIT_PID:
@@ -1361,8 +1362,9 @@ int audit_filter(int msgtype, unsigned int listtype)
case AUDIT_SUBJ_CLR:
if (f->lsm_isset) {
security_task_getsecid(current, &sid);
-   result = security_audit_rule_match(sid,
-  f->type, f->op,
+   lsmblob_init(&blob, sid);
+   result = security_audit_rule_match(
+  &blob, f->type, f->op,
   f->lsm_rules);
}
break;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index bafa03a5c866..975c3b8c8d0d 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -456,6 +456,7 @@ static int audit_filter_rules(struct task_struct *tsk,
const struct cred *cred;
int i, need_sid = 1;
u32 sid;
+   struct lsmblob blob;
unsigned int sessionid;
 
cred = rcu_dereference_check(tsk->cred, tsk == current || 
task_creation);
@@ -654,7 +655,9 @@ static int audit_filter_rules(struct task_struct *tsk,
security_task_getsecid(tsk, &sid);
need_sid = 0;
}
-   result = security_audit_rule_match(sid, f->type,
+   lsmblob_init(&blob, sid);
+   result = security_audit_rule_match(&blob,
+  f->type,
   f->op,
   
f->lsm_rules);
}
@@ -669,15 +672,17 @@ static int audit_filter_rules(struct task_struct *tsk,
if (f->lsm_isset) {
/* Find files that match */
if (name) {
+   lsmblob_init(&blob, name->osid);
result = security_audit_rule_match(
-  

[PATCH v19 04/23] LSM: Use lsmblob in security_kernel_act_as

2020-07-24 Thread Casey Schaufler
Change the security_kernel_act_as interface to use a lsmblob
structure in place of the single u32 secid in support of
module stacking. Change its only caller, set_security_override,
to do the same. Change that one's only caller,
set_security_override_from_ctx, to call it with the new
parameter type.

The security module hook is unchanged, still taking a secid.
The infrastructure passes the correct entry from the lsmblob.
lsmblob_init() is used to fill the lsmblob structure, however
this will be removed later in the series when security_secctx_to_secid()
is undated to provide a lsmblob instead of a secid.

Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
---
 include/linux/cred.h |  3 ++-
 include/linux/security.h |  5 +++--
 kernel/cred.c| 10 ++
 security/security.c  | 14 --
 4 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index 18639c069263..03ae0182cba6 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -18,6 +18,7 @@
 
 struct cred;
 struct inode;
+struct lsmblob;
 
 /*
  * COW Supplementary groups list
@@ -165,7 +166,7 @@ extern const struct cred *override_creds(const struct cred 
*);
 extern void revert_creds(const struct cred *);
 extern struct cred *prepare_kernel_cred(struct task_struct *);
 extern int change_create_files_as(struct cred *, struct inode *);
-extern int set_security_override(struct cred *, u32);
+extern int set_security_override(struct cred *, struct lsmblob *);
 extern int set_security_override_from_ctx(struct cred *, const char *);
 extern int set_create_files_as(struct cred *, struct inode *);
 extern int cred_fscmp(const struct cred *, const struct cred *);
diff --git a/include/linux/security.h b/include/linux/security.h
index 294410533b51..6d403a522918 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -441,7 +441,7 @@ void security_cred_free(struct cred *cred);
 int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t 
gfp);
 void security_transfer_creds(struct cred *new, const struct cred *old);
 void security_cred_getsecid(const struct cred *c, u32 *secid);
-int security_kernel_act_as(struct cred *new, u32 secid);
+int security_kernel_act_as(struct cred *new, struct lsmblob *blob);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
 int security_kernel_module_request(char *kmod_name);
 int security_kernel_load_data(enum kernel_load_data_id id);
@@ -1055,7 +1055,8 @@ static inline void security_transfer_creds(struct cred 
*new,
 {
 }
 
-static inline int security_kernel_act_as(struct cred *cred, u32 secid)
+static inline int security_kernel_act_as(struct cred *cred,
+struct lsmblob *blob)
 {
return 0;
 }
diff --git a/kernel/cred.c b/kernel/cred.c
index 421b1149c651..22e0e7cbefde 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -733,14 +733,14 @@ EXPORT_SYMBOL(prepare_kernel_cred);
 /**
  * set_security_override - Set the security ID in a set of credentials
  * @new: The credentials to alter
- * @secid: The LSM security ID to set
+ * @blob: The LSM security information to set
  *
  * Set the LSM security ID in a set of credentials so that the subjective
  * security is overridden when an alternative set of credentials is used.
  */
-int set_security_override(struct cred *new, u32 secid)
+int set_security_override(struct cred *new, struct lsmblob *blob)
 {
-   return security_kernel_act_as(new, secid);
+   return security_kernel_act_as(new, blob);
 }
 EXPORT_SYMBOL(set_security_override);
 
@@ -756,6 +756,7 @@ EXPORT_SYMBOL(set_security_override);
  */
 int set_security_override_from_ctx(struct cred *new, const char *secctx)
 {
+   struct lsmblob blob;
u32 secid;
int ret;
 
@@ -763,7 +764,8 @@ int set_security_override_from_ctx(struct cred *new, const 
char *secctx)
if (ret < 0)
return ret;
 
-   return set_security_override(new, secid);
+   lsmblob_init(&blob, secid);
+   return set_security_override(new, &blob);
 }
 EXPORT_SYMBOL(set_security_override_from_ctx);
 
diff --git a/security/security.c b/security/security.c
index f9a249a93215..d6d882b1f7d5 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1692,9 +1692,19 @@ void security_cred_getsecid(const struct cred *c, u32 
*secid)
 }
 EXPORT_SYMBOL(security_cred_getsecid);
 
-int security_kernel_act_as(struct cred *new, u32 secid)
+int security_kernel_act_as(struct cred *new, struct lsmblob *blob)
 {
-   return call_int_hook(kernel_act_as, 0, new, secid);
+   struct security_hook_list *hp;
+   int rc;
+
+   hlist_for_each_entry(hp, &security_hook_heads.kernel_act_as, list) {
+   if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+   continue;
+   rc = hp->hook.kernel_act_as(new, blob->secid[hp->l

[PATCH v19 00/23] LSM: Module stacking for AppArmor

2020-07-24 Thread Casey Schaufler
This patchset provides the changes required for
the AppArmor security module to stack safely with any other.

v19: Rebase to 5.8-rc6
 Incorporate feedback from v18
 - Revert UDS SO_PEERSEC implementation to use lsmblobs
   directly, rather than allocating as needed. The correct
   treatment of out-of-memory conditions in the later case
   is difficult to define. (patch 0005)
 - Use a size_t in append_ctx() (patch 0021)
 - Fix a memory leak when creating compound contexts. (patch 0021)
 Fix build error when CONFIG_SECURITY isn't set (patch 0013)
 Fix build error when CONFIG_SECURITY isn't set (patch 0020)
 Fix build error when CONFIG_SECURITY isn't set (patch 0021)

v18: Rebase to 5.8-rc3
 Incorporate feedback from v17
 - Null pointer checking in UDS (patch 0005)
 Match changes in IMA code (patch 0012)
 Fix the behavior of LSM context supplimental audit
 records so that there's always exactly one when it's
 appropriate for there to be one. This is a substantial
 change that requires extention of the audit_context beyond
 syscall events. (patch 0020)

v17: Rebase to 5.7-rc4

v16: Rebase to 5.6
 Incorporate feedback from v15 - Thanks Stephen, Mimi and Paul
 - Generally improve commit messages WRT scaffolding
 - Comment ima_lsm_isset() (patch 0002)
 - Some question may remain on IMA warning (patch 0002)
 - Mark lsm_slot as __lsm_ro_after_init not __init_data (patch 0002)
 - Change name of lsmblob variable in ima_match_rules() (patch 0003)
 - Instead of putting a struct lsmblob into the unix_skb_parms
   structure put a pointer to an allocated instance. There is
   currently only space for 5 u32's in unix_skb_parms and it is
   likely to get even tighter. Fortunately, the lifecycle
   management of the allocated lsmblob is simple. (patch 0005)
 - Dropped Acks due to the above change (patch 0005)
 - Improved commentary on secmark labeling scaffolding. (patch 0006)
 - Reduced secmark related labeling scaffolding. (patch 0006)
 - Replace use of the zeroth entry of an lsmblob in scaffolding
   with a function lsmblob_value() to hopefully make it less
   obscure. (patch 0006)
 - Convert security_secmark_relabel_packet to use lsmblob as
   this reduces much of the most contentious scaffolding. (patch 0006)
 - Dropped Acks due to the above change (patch 0006)
 - Added BUILD_BUG_ON() for CIPSO tag 6. (patch 0018)
 - Reworked audit subject information. Instead of adding fields in
   the middle of existing records add a new record to the event. When
   a separate record is required use subj="?". (patch 0020)
 - Dropped Acks due to the above change (patch 0020)
 - Reworked audit object information. Instead of adding fields in
   the middle of existing records add a new record to the event. When
   a separate record is required use obj="?". (patch 0021)
 - Dropped Acks due to the above change (patch 0021)
 - Enhanced documentation (patch 0022)
 - Removed unnecessary error code check in security_getprocattr()
   (patch 0021)

v15: Rebase to 5.6-rc1
 - Revise IMA data use (patch 0002)
 Incorporate feedback from v14
 - Fix lockdown module registration naming (patch 0002)
 - Revise how /proc/self/attr/context is gathered. (patch 0022)
 - Revise access modes on /proc/self/attr/context. (patch 0022)
 - Revise documentation on LSM external interfaces. (patch 0022)

v14: Rebase to 5.5-rc5
 Incorporate feedback from v13
 - Use an array of audit rules (patch 0002)
 - Significant change, removed Acks (patch 0002)
 - Remove unneeded include (patch 0013)
 - Use context.len correctly (patch 0015)
 - Reorder code to be more sensible (patch 0016)
 - Drop SO_PEERCONTEXT as it's not needed yet (patch 0023)

v13: Rebase to 5.5-rc2
 Incorporate feedback from v12
 - Print lsmblob size with %z (Patch 0002)
 - Convert lockdown LSM initialization. (Patch 0002)
 - Restore error check in nft_secmark_compute_secid (Patch 0006)
 - Correct blob scaffolding in ima_must_appraise() (Patch 0009)
 - Make security_setprocattr() clearer (Patch 0013)
 - Use lsm_task_display more widely (Patch 0013)
 - Use passed size in lsmcontext_init() (Patch 0014)
 - Don't add a smack_release_secctx() hook (Patch 0014)
 - Don't print warning in security_release_secctx() (Patch 0014)
 - Don't duplicate the label in nfs4_label_init_security() (Patch 0016)
 - Remove reviewed-by as code has significant change (Patch 0016)
 - Send the entire lsmblob for Tag 6 (Patch 0019)
 - Fix description of socket_getpeersec_stream parameters (Patch 0023)
 - Retain LSMBLOB_FIRST. What was I thinking? (Patch 0023)
 - Add compound context to LSM documentation (Patch 0023)

v12: Rebase to 5.5-rc1
 Fixed a couple of incorrect contractions in the text.

v11: Rebase to 5.4-rc6
 I

[PATCH v19 02/23] LSM: Create and manage the lsmblob data structure.

2020-07-24 Thread Casey Schaufler
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.

The audit rules data is expanded to use an array of
security module data rather than a single instance.
Because IMA uses the audit rule functions it is
affected as well.

Acked-by: Stephen Smalley 
Acked-by: Paul Moore 
Signed-off-by: Casey Schaufler 
---
 include/linux/audit.h   |  4 +-
 include/linux/lsm_hooks.h   | 12 -
 include/linux/security.h| 66 --
 kernel/auditfilter.c| 24 +-
 kernel/auditsc.c| 12 ++---
 security/apparmor/lsm.c |  7 ++-
 security/commoncap.c|  7 ++-
 security/integrity/ima/ima_policy.c | 40 +++-
 security/loadpin/loadpin.c  |  8 +++-
 security/lockdown/lockdown.c|  7 ++-
 security/safesetid/lsm.c|  8 +++-
 security/security.c | 72 -
 security/selinux/hooks.c|  8 +++-
 security/smack/smack_lsm.c  |  7 ++-
 security/tomoyo/tomoyo.c|  8 +++-
 security/yama/yama_lsm.c|  7 ++-
 16 files changed, 242 insertions(+), 55 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 3fcd9ee49734..aabbbe6d9296 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -11,6 +11,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #define AUDIT_INO_UNSET ((unsigned long)-1)
@@ -64,8 +65,9 @@ struct audit_field {
kuid_t  uid;
kgid_t  gid;
struct {
+   boollsm_isset;
char*lsm_str;
-   void*lsm_rule;
+   void*lsm_rules[LSMBLOB_ENTRIES];
};
};
u32 op;
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index b4bcafc79e0b..c9f792066d86 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1532,6 +1532,14 @@ struct security_hook_heads {
#undef LSM_HOOK
 } __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.
@@ -1540,7 +1548,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;
 
 /*
@@ -1575,7 +1583,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 0a0a03b36a3b..591dae299c6f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -131,6 +131,64 @@ enum lockdown_reason {
 
 extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1];
 
+/*
+ * 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)
+{
+   i

[PATCH v19 01/23] LSM: Infrastructure management of the sock security

2020-07-24 Thread Casey Schaufler
Move management of the sock->sk_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.

Acked-by: Paul Moore 
Reviewed-by: Kees Cook 
Reviewed-by: John Johansen 
Acked-by: Stephen Smalley 
Signed-off-by: Casey Schaufler 
---
 include/linux/lsm_hooks.h |  1 +
 security/apparmor/include/net.h   |  6 ++-
 security/apparmor/lsm.c   | 38 ---
 security/security.c   | 36 +-
 security/selinux/hooks.c  | 78 +++
 security/selinux/include/objsec.h |  5 ++
 security/selinux/netlabel.c   | 23 -
 security/smack/smack.h|  5 ++
 security/smack/smack_lsm.c| 64 -
 security/smack/smack_netfilter.c  |  8 ++--
 10 files changed, 144 insertions(+), 120 deletions(-)

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 95b7c1d32062..b4bcafc79e0b 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1550,6 +1550,7 @@ struct lsm_blob_sizes {
int lbs_cred;
int lbs_file;
int lbs_inode;
+   int lbs_sock;
int lbs_ipc;
int lbs_msg_msg;
int lbs_task;
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
index 2431c011800d..5b6f52c62058 100644
--- a/security/apparmor/include/net.h
+++ b/security/apparmor/include/net.h
@@ -51,7 +51,11 @@ struct aa_sk_ctx {
struct aa_label *peer;
 };
 
-#define SK_CTX(X) ((X)->sk_security)
+static inline struct aa_sk_ctx *aa_sock(const struct sock *sk)
+{
+   return sk->sk_security + apparmor_blob_sizes.lbs_sock;
+}
+
 #define SOCK_ctx(X) SOCK_INODE(X)->i_security
 #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P)
  \
struct lsm_network_audit NAME ## _net = { .sk = (SK), \
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index ffeaee5ed968..f1c365905d5e 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -766,33 +766,15 @@ static int apparmor_task_kill(struct task_struct *target, 
struct kernel_siginfo
return error;
 }
 
-/**
- * apparmor_sk_alloc_security - allocate and attach the sk_security field
- */
-static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
-{
-   struct aa_sk_ctx *ctx;
-
-   ctx = kzalloc(sizeof(*ctx), flags);
-   if (!ctx)
-   return -ENOMEM;
-
-   SK_CTX(sk) = ctx;
-
-   return 0;
-}
-
 /**
  * apparmor_sk_free_security - free the sk_security field
  */
 static void apparmor_sk_free_security(struct sock *sk)
 {
-   struct aa_sk_ctx *ctx = SK_CTX(sk);
+   struct aa_sk_ctx *ctx = aa_sock(sk);
 
-   SK_CTX(sk) = NULL;
aa_put_label(ctx->label);
aa_put_label(ctx->peer);
-   kfree(ctx);
 }
 
 /**
@@ -801,8 +783,8 @@ static void apparmor_sk_free_security(struct sock *sk)
 static void apparmor_sk_clone_security(const struct sock *sk,
   struct sock *newsk)
 {
-   struct aa_sk_ctx *ctx = SK_CTX(sk);
-   struct aa_sk_ctx *new = SK_CTX(newsk);
+   struct aa_sk_ctx *ctx = aa_sock(sk);
+   struct aa_sk_ctx *new = aa_sock(newsk);
 
if (new->label)
aa_put_label(new->label);
@@ -858,7 +840,7 @@ static int apparmor_socket_post_create(struct socket *sock, 
int family,
label = aa_get_current_label();
 
if (sock->sk) {
-   struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
+   struct aa_sk_ctx *ctx = aa_sock(sock->sk);
 
aa_put_label(ctx->label);
ctx->label = aa_get_label(label);
@@ -1043,7 +1025,7 @@ static int apparmor_socket_shutdown(struct socket *sock, 
int how)
  */
 static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
-   struct aa_sk_ctx *ctx = SK_CTX(sk);
+   struct aa_sk_ctx *ctx = aa_sock(sk);
 
if (!skb->secmark)
return 0;
@@ -1056,7 +1038,7 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, 
struct sk_buff *skb)
 
 static struct aa_label *sk_peer_label(struct sock *sk)
 {
-   struct aa_sk_ctx *ctx = SK_CTX(sk);
+   struct aa_sk_ctx *ctx = aa_sock(sk);
 
if (ctx->peer)
return ctx->peer;
@@ -1140,7 +1122,7 @@ static int apparmor_socket_getpeersec_dgram(struct socket 
*sock,
  */
 static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
 {
-   struct aa_sk_ctx *ctx = SK_CTX(sk);
+   struct aa_sk_ctx *ctx = aa_sock(sk);
 
if (!ctx->label)
ctx->label = aa_get_current_label();
@@ -1150,7 +1132,7 @@ static void apparmor_sock_graft(struct sock *sk, struct 
socket *parent)
 static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,

Re: null pointer dereference regression in 5.7

2020-07-24 Thread Paul Moore
On Thu, Jul 23, 2020 at 8:57 AM Richard Guy Briggs  wrote:
> On 2020-07-22 21:01, Paul Moore wrote:
> > Do you have a rough idea as to how long it would take to chase down
> > all the code paths?  I'm asking not to rush you, but to figure out if
> > we should revert the patch now to resolve the problem and restore it
> > later once we are confident there are no additional issues lurking.
>
> I figure 2-3 days.

Okay.  I think we need to submit a revert for v5.8 and -stable (which
is pretty limited at this point); can you put that together and send
it to the list?  It should be trivial, if you can't do it let me know.

> I'm trying to remember the name of the tool to build a function calling
> tree, either up or down.  Was it cscope?  Or is there something more
> modern?  It will have some limitations due to op function pointers.

I'm not sure what you're talking about, I always just walk the code by
hand in my editor with cscope or lxr as tools on the side.

-- 
paul moore
www.paul-moore.com

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit