* [PATCH 53/97] LSM: Use lsm_context in release_secctx hooks
From: Casey Schaufler @ 2019-02-28 22:18 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228221933.2551-1-casey@schaufler-ca.com>
Convert SELinux, Smack and AppAror to use the lsm_context structure
instead of a context/secid pair. There is some scaffolding involved
that will be removed when the related data is updated.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 3 +--
security/apparmor/include/secid.h | 2 +-
security/apparmor/secid.c | 4 ++--
security/security.c | 7 +++++--
security/selinux/hooks.c | 4 ++--
security/smack/smack_lsm.c | 4 ++--
6 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 29e52aedd6ac..2f07be4b9800 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1316,7 +1316,6 @@
* @release_secctx:
* Release the security context.
* @secdata contains the security context.
- * @seclen contains the length of the security context.
*
* Security hooks for Audit
*
@@ -1653,7 +1652,7 @@ union security_list_options {
int (*secid_to_secctx)(struct lsm_export *l, struct lsm_context *cp);
int (*secctx_to_secid)(const struct lsm_context *cp,
struct lsm_export *l);
- void (*release_secctx)(char *secdata, u32 seclen);
+ void (*release_secctx)(struct lsm_context *cp);
void (*inode_invalidate_secctx)(struct inode *inode);
int (*inode_notifysecctx)(struct inode *inode, struct lsm_context *cp);
diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h
index acfcf99bff0e..a780e56d4f5b 100644
--- a/security/apparmor/include/secid.h
+++ b/security/apparmor/include/secid.h
@@ -29,7 +29,7 @@ struct aa_label *aa_secid_to_label(struct lsm_export *l);
int apparmor_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp);
int apparmor_secctx_to_secid(const struct lsm_context *cp,
struct lsm_export *l);
-void apparmor_release_secctx(char *secdata, u32 seclen);
+void apparmor_release_secctx(struct lsm_context *cp);
int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c
index 35df38592b6e..46c8b9a67ac7 100644
--- a/security/apparmor/secid.c
+++ b/security/apparmor/secid.c
@@ -123,9 +123,9 @@ int apparmor_secctx_to_secid(const struct lsm_context *cp, struct lsm_export *l)
return 0;
}
-void apparmor_release_secctx(char *secdata, u32 seclen)
+void apparmor_release_secctx(struct lsm_context *cp)
{
- kfree(secdata);
+ kfree(cp->context);
}
/**
diff --git a/security/security.c b/security/security.c
index dadb1cb72920..4dfe053ced5b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1990,7 +1990,6 @@ EXPORT_SYMBOL(security_secid_to_secctx);
int security_secctx_to_secid(struct lsm_context *cp, struct lsm_export *l)
{
-
lsm_export_init(l);
return call_one_int_hook(secctx_to_secid, 0, cp, l);
}
@@ -1998,7 +1997,11 @@ EXPORT_SYMBOL(security_secctx_to_secid);
void security_release_secctx(char *secdata, u32 seclen)
{
- call_one_void_hook(release_secctx, secdata, seclen);
+ struct lsm_context lc;
+
+ lc.context = secdata;
+ lc.len = seclen;
+ call_one_void_hook(release_secctx, &lc);
}
EXPORT_SYMBOL(security_release_secctx);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8b8eb5115d6d..ea9603b63f77 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6215,9 +6215,9 @@ static int selinux_secctx_to_secid(const struct lsm_context *cp,
return rc;
}
-static void selinux_release_secctx(char *secdata, u32 seclen)
+static void selinux_release_secctx(struct lsm_context *cp)
{
- kfree(secdata);
+ kfree(cp->context);
}
static void selinux_inode_invalidate_secctx(struct inode *inode)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 26cf42ddba0e..332ac71e8a41 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4383,9 +4383,9 @@ static int smack_secctx_to_secid(const struct lsm_context *cp,
}
/*
- * There smack_release_secctx hook does nothing
+ * The smack_release_secctx hook does nothing
*/
-static void smack_release_secctx(char *secdata, u32 seclen)
+static void smack_release_secctx(struct lsm_context *cp)
{
}
--
2.17.0
^ permalink raw reply related
* [PATCH 35/97] NET: Remove scaffolding on new secmarks
From: Casey Schaufler @ 2019-02-28 22:18 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228221933.2551-1-casey@schaufler-ca.com>
Replace the lsm_export scaffolding in nft_meta.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
net/netfilter/nft_meta.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index a03de2ab833a..9f5040140fe0 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -568,11 +568,17 @@ static int nft_secmark_compute_secid(struct nft_secmark *priv)
u32 tmp_secid = 0;
int err;
+ lsm_export_init(&le);
err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &le);
if (err)
return err;
- lsm_export_secid(&le, &tmp_secid);
+ /* Use the "best" secid */
+ if (le.selinux)
+ tmp_secid = le.selinux;
+ else
+ tmp_secid = le.smack;
+
if (!tmp_secid)
return -ENOENT;
--
2.17.0
^ permalink raw reply related
* [PATCH 30/97] Audit: Convert target_sid to an lsm_export structure
From: Casey Schaufler @ 2019-02-28 22:18 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228221933.2551-1-casey@schaufler-ca.com>
Convert target_sid to be an lsm_export structure
instead of a u32 secid. Clean out the associated
scaffolding. Change the name to target_lsm to be
descriptive.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
kernel/audit.h | 3 ++-
kernel/auditsc.c | 30 ++++++++++++------------------
2 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/kernel/audit.h b/kernel/audit.h
index 06c732e0f301..63883a773aa2 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -22,6 +22,7 @@
#include <linux/fs.h>
#include <linux/audit.h>
#include <linux/skbuff.h>
+#include <linux/security.h>
#include <uapi/linux/mqueue.h>
#include <linux/tty.h>
@@ -146,7 +147,7 @@ struct audit_context {
kuid_t target_auid;
kuid_t target_uid;
unsigned int target_sessionid;
- u32 target_sid;
+ struct lsm_export target_lsm;
char target_comm[TASK_COMM_LEN];
struct audit_tree_refs *trees, *first_trees;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index c57c2e346c6d..2ee74d18c90c 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -112,7 +112,7 @@ struct audit_aux_data_pids {
kuid_t target_auid[AUDIT_AUX_PIDS];
kuid_t target_uid[AUDIT_AUX_PIDS];
unsigned int target_sessionid[AUDIT_AUX_PIDS];
- u32 target_sid[AUDIT_AUX_PIDS];
+ struct lsm_export target_lsm[AUDIT_AUX_PIDS];
char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
int pid_count;
};
@@ -934,14 +934,14 @@ static inline void audit_free_context(struct audit_context *context)
}
static int audit_log_pid_context(struct audit_context *context, pid_t pid,
- kuid_t auid, kuid_t uid, unsigned int sessionid,
- u32 sid, char *comm)
+ kuid_t auid, kuid_t uid,
+ unsigned int sessionid,
+ struct lsm_export *l, char *comm)
{
struct audit_buffer *ab;
char *ctx = NULL;
u32 len;
int rc = 0;
- struct lsm_export le;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
if (!ab)
@@ -950,9 +950,8 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
from_kuid(&init_user_ns, auid),
from_kuid(&init_user_ns, uid), sessionid);
- if (sid) {
- lsm_export_to_all(&le, sid);
- if (security_secid_to_secctx(&le, &ctx, &len)) {
+ if (lsm_export_any(l)) {
+ if (security_secid_to_secctx(l, &ctx, &len)) {
audit_log_format(ab, " obj=(none)");
rc = 1;
} else {
@@ -1401,7 +1400,7 @@ static void audit_log_exit(void)
axs->target_auid[i],
axs->target_uid[i],
axs->target_sessionid[i],
- axs->target_sid[i],
+ &axs->target_lsm[i],
axs->target_comm[i]))
call_panic = 1;
}
@@ -1410,7 +1409,7 @@ static void audit_log_exit(void)
audit_log_pid_context(context, context->target_pid,
context->target_auid, context->target_uid,
context->target_sessionid,
- context->target_sid, context->target_comm))
+ &context->target_lsm, context->target_comm))
call_panic = 1;
if (context->pwd.dentry && context->pwd.mnt) {
@@ -1587,7 +1586,7 @@ void __audit_syscall_exit(int success, long return_code)
context->aux = NULL;
context->aux_pids = NULL;
context->target_pid = 0;
- context->target_sid = 0;
+ lsm_export_init(&context->target_lsm);
context->sockaddr_len = 0;
context->type = 0;
context->fds[0] = -1;
@@ -2260,14 +2259,12 @@ int __audit_sockaddr(int len, void *a)
void __audit_ptrace(struct task_struct *t)
{
struct audit_context *context = audit_context();
- struct lsm_export le;
context->target_pid = task_tgid_nr(t);
context->target_auid = audit_get_loginuid(t);
context->target_uid = task_uid(t);
context->target_sessionid = audit_get_sessionid(t);
- security_task_getsecid(t, &le);
- lsm_export_secid(&le, &context->target_sid);
+ security_task_getsecid(t, &context->target_lsm);
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
}
@@ -2284,7 +2281,6 @@ int audit_signal_info(int sig, struct task_struct *t)
struct audit_aux_data_pids *axp;
struct audit_context *ctx = audit_context();
kuid_t uid = current_uid(), auid, t_uid = task_uid(t);
- struct lsm_export le;
if (auditd_test_task(t) &&
(sig == SIGTERM || sig == SIGHUP ||
@@ -2308,8 +2304,7 @@ int audit_signal_info(int sig, struct task_struct *t)
ctx->target_auid = audit_get_loginuid(t);
ctx->target_uid = t_uid;
ctx->target_sessionid = audit_get_sessionid(t);
- security_task_getsecid(t, &le);
- lsm_export_secid(&le, &ctx->target_sid);
+ security_task_getsecid(t, &ctx->target_lsm);
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
return 0;
}
@@ -2330,8 +2325,7 @@ int audit_signal_info(int sig, struct task_struct *t)
axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
axp->target_uid[axp->pid_count] = t_uid;
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
- security_task_getsecid(t, &le);
- lsm_export_secid(&le, &axp->target_sid[axp->pid_count]);
+ security_task_getsecid(t, &axp->target_lsm[axp->pid_count]);
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
axp->pid_count++;
--
2.17.0
^ permalink raw reply related
* [PATCH 36/97] NET: Remove netfilter scaffolding for lsm_export
From: Casey Schaufler @ 2019-02-28 22:18 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228221933.2551-1-casey@schaufler-ca.com>
Remove scaffolding functions from the netfilter code.
Replace with direct access to lsm_export fields so as
to be explicit about how the secmarks are being
handled.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
net/netfilter/nf_conntrack_netlink.c | 12 ++++++++++--
net/netfilter/nf_conntrack_standalone.c | 9 +++++++--
net/netfilter/nfnetlink_queue.c | 8 ++++++--
3 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index d19092fc6580..65741838985f 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -332,7 +332,11 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
char *secctx;
struct lsm_export le;
- lsm_export_to_all(&le, ct->secmark);
+ lsm_export_init(&le);
+ le.flags = LSM_EXPORT_SELINUX | LSM_EXPORT_SMACK;
+ le.selinux = ct->secmark;
+ le.smack = ct->secmark;
+
ret = security_secid_to_secctx(&le, &secctx, &len);
if (ret)
return 0;
@@ -619,7 +623,11 @@ static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
int len, ret;
struct lsm_export le;
- lsm_export_to_all(&le, ct->secmark);
+ lsm_export_init(&le);
+ le.flags = LSM_EXPORT_SELINUX | LSM_EXPORT_SMACK;
+ le.selinux = ct->secmark;
+ le.smack = ct->secmark;
+
ret = security_secid_to_secctx(&le, NULL, &len);
if (ret)
return 0;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 51dc1e390d84..b47ca79b8e14 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -173,8 +173,13 @@ static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
char *secctx;
struct lsm_export le;
- lsm_export_to_all(&le, ct->secmark);
- ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+ /* Whichever LSM may be using the secmark */
+ lsm_export_init(&le);
+ le.flags = LSM_EXPORT_SELINUX | LSM_EXPORT_SMACK;
+ le.selinux = ct->secmark;
+ le.smack = ct->secmark;
+
+ ret = security_secid_to_secctx(&le, &secctx, &len);
if (ret)
return;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 537effb6e5be..a0670137477b 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -317,8 +317,12 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
read_lock_bh(&skb->sk->sk_callback_lock);
if (skb->secmark) {
- lsm_export_to_all(&le, skb->secmark);
- security_secid_to_secctx(skb->secmark, secdata, &seclen);
+ /* Whichever LSM may be using the secmark */
+ lsm_export_init(&le);
+ le.flags = LSM_EXPORT_SELINUX | LSM_EXPORT_SMACK;
+ le.selinux = skb->secmark;
+ le.smack = skb->secmark;
+ security_secid_to_secctx(&le, secdata, &seclen);
}
read_unlock_bh(&skb->sk->sk_callback_lock);
--
2.17.0
^ permalink raw reply related
* [PATCH 33/97] NET: Store LSM access information in the socket blob for UDS
From: Casey Schaufler @ 2019-02-28 22:18 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228221933.2551-1-casey@schaufler-ca.com>
UNIX domain socket connections don't have sufficient
space in the socket buffer (skb) secmark for more than
one Linux security module (LSM) to pass data. Expanding
the secmark has been ruled out as an option. Store the
necessary data in the socket security blob pointed to
by the skb socket.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 20 +++++++++++++++++++-
net/unix/af_unix.c | 14 ++++++++------
security/security.c | 17 ++++++++++++++++-
3 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index ae79b24f076d..6659ffa8cacc 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -68,6 +68,7 @@ struct ctl_table;
struct audit_krule;
struct user_namespace;
struct timezone;
+struct sk_buff;
enum lsm_event {
LSM_POLICY_CHANGE,
@@ -97,6 +98,22 @@ static inline bool lsm_export_any(struct lsm_export *l)
((l->flags & LSM_EXPORT_APPARMOR) && l->apparmor));
}
+static inline bool lsm_export_equal(struct lsm_export *l, struct lsm_export *m)
+{
+ if (l->flags != m->flags || l->flags == LSM_EXPORT_NONE)
+ return false;
+ if (l->flags & LSM_EXPORT_SELINUX &&
+ (l->selinux != m->selinux || l->selinux == 0))
+ return false;
+ if (l->flags & LSM_EXPORT_SMACK &&
+ (l->smack != m->smack || l->smack == 0))
+ return false;
+ if (l->flags & LSM_EXPORT_APPARMOR &&
+ (l->apparmor != m->apparmor || l->apparmor == 0))
+ return false;
+ return true;
+}
+
/**
* lsm_export_secid - pull the useful secid out of a lsm_export
* @data: the containing data structure
@@ -140,6 +157,8 @@ static inline void lsm_export_to_all(struct lsm_export *data, u32 secid)
LSM_EXPORT_APPARMOR;
}
+extern struct lsm_export *lsm_export_skb(struct sk_buff *skb);
+
/* These functions are in security/commoncap.c */
extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
int cap, unsigned int opts);
@@ -171,7 +190,6 @@ extern int cap_task_setnice(struct task_struct *p, int nice);
extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
struct msghdr;
-struct sk_buff;
struct sock;
struct sockaddr;
struct socket;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index e2327428aecb..df183ff69d61 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -141,21 +141,23 @@ static struct hlist_head *unix_sockets_unbound(void *addr)
#ifdef CONFIG_SECURITY_NETWORK
static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{
- lsm_export_secid(&scm->le, &(UNIXCB(skb).secid));
+ struct lsm_export *ble = lsm_export_skb(skb);
+
+ *ble = scm->le;
}
static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{
- lsm_export_to_all(&scm->le, UNIXCB(skb).secid);
+ struct lsm_export *ble = lsm_export_skb(skb);
+
+ scm->le = *ble;
}
static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
{
- u32 best_secid;
-
- lsm_export_secid(&scm->le, &best_secid);
- return (best_secid == UNIXCB(skb).secid);
+ return lsm_export_equal(&scm->le, lsm_export_skb(skb));
}
+
#else
static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{ }
diff --git a/security/security.c b/security/security.c
index e52b500adb27..2f9411b93f70 100644
--- a/security/security.c
+++ b/security/security.c
@@ -46,7 +46,22 @@ static struct kmem_cache *lsm_file_cache;
static struct kmem_cache *lsm_inode_cache;
char *lsm_names;
-static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
+
+/* Socket blobs include infrastructure managed data */
+static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init = {
+ .lbs_sock = sizeof(struct lsm_export),
+};
+
+/**
+ * lsm_export_skb - pointer to the lsm_export associated with the skb
+ * @skb: the socket buffer
+ *
+ * Returns a pointer to the LSM managed data.
+ */
+struct lsm_export *lsm_export_skb(struct sk_buff *skb)
+{
+ return skb->sk->sk_security;
+}
/* Boot-time LSM user choice */
static __initdata const char *chosen_lsm_order;
--
2.17.0
^ permalink raw reply related
* [PATCH 27/97] LSM: Use lsm_export in security_cred_getsecid
From: Casey Schaufler @ 2019-02-28 22:18 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228221933.2551-1-casey@schaufler-ca.com>
Convert security_cred_getsecid to use the lsm_export structure
instead of a u32 secid. There is some scaffolding involved
that will be removed when the related data is updated.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 2 +-
security/integrity/ima/ima_main.c | 3 ++-
security/security.c | 8 +++-----
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 07fd36f6616d..87085ff519bf 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -376,7 +376,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 lsm_export *l);
int security_kernel_act_as(struct cred *new, struct lsm_export *l);
int security_kernel_create_files_as(struct cred *new, struct inode *inode);
int security_kernel_module_request(char *kmod_name);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index e78658b26a74..7efc806eb5ab 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -374,7 +374,8 @@ int ima_bprm_check(struct linux_binprm *bprm)
if (ret)
return ret;
- security_cred_getsecid(bprm->cred, &secid);
+ security_cred_getsecid(bprm->cred, &le);
+ lsm_export_secid(&le, &secid);
return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
MAY_EXEC, CREDS_CHECK);
}
diff --git a/security/security.c b/security/security.c
index c2cf82b063ca..06461712c881 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1590,12 +1590,10 @@ void security_transfer_creds(struct cred *new, const struct cred *old)
call_void_hook(cred_transfer, new, old);
}
-void security_cred_getsecid(const struct cred *c, u32 *secid)
+void security_cred_getsecid(const struct cred *c, struct lsm_export *l)
{
- struct lsm_export data = { .flags = LSM_EXPORT_NONE };
-
- call_void_hook(cred_getsecid, c, &data);
- lsm_export_secid(&data, secid);
+ lsm_export_init(l);
+ call_void_hook(cred_getsecid, c, l);
}
EXPORT_SYMBOL(security_cred_getsecid);
--
2.17.0
^ permalink raw reply related
* Re: [PULL REQUEST] Lock down patches
From: Mimi Zohar @ 2019-02-28 22:20 UTC (permalink / raw)
To: Matthew Garrett, jmorris
Cc: LSM List, Linux Kernel Mailing List, David Howells
In-Reply-To: <CACdnJuvW47m3JvEcuEX1bsr+L2Ht9LDn_iCuPbHLOoaohOFW4Q@mail.gmail.com>
On Thu, 2019-02-28 at 13:28 -0800, Matthew Garrett wrote:
> Hi James,
>
> David is low on cycles at the moment, so I'm taking over for this time
> round. This patchset introduces an optional kernel lockdown feature,
> intended to strengthen the boundary between UID 0 and the kernel. When
> enabled and active (by enabling the config option and passing the
> "lockdown" option on the kernel command line), various pieces of
> kernel functionality are restricted. Applications that rely on
> low-level access to either hardware or the kernel may cease working as
> a result - therefore this should not be enabled without appropriate
> evaluation beforehand.
>
> The majority of mainstream distributions have been carrying variants
> of this patchset for many years now, so there's value in providing a
> unified upstream implementation to reduce the delta. This PR probably
> doesn't meet every distribution requirement, but gets us much closer
> to not requiring external patches.
>
> This PR is mostly the same as the previous attempt, but with the
> following changes:
Where/when was this latest version of the patches posted?
>
> 1) The integration between EFI secure boot and the lockdown state has
> been removed
> 2) A new CONFIG_KERNEL_LOCK_DOWN_FORCE kconfig option has been added,
> which will always enable lockdown regardless of the kernel command
> line
> 3) The integration with IMA has been dropped for now. Requiring the
> use of the IMA secure boot policy when lockdown is enabled isn't
> practical for most distributions at the moment, as there's still not a
> great deal of infrastructure for shipping packages with appropriate
> IMA signatures, and it makes it complicated for end users to manage
> custom IMA policies.
I'm all in favor of dropping the original attempt to coordinate
between the kexec PE and IMA kernel image signatures and the kernel
appended and IMA modules signatures, but there has been quite a bit of
work recently coordinating the different types of signatures.
Preventing systems which do use IMA for signature verification, should
not limit their ability to enable "lock down". Does this version of
the "lock down" patches coordinate the different kexec kernel image
and kernel module signature verification methods?
Mimi
^ permalink raw reply
* [PATCH 00/97] LSM: Complete module stacking
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
This is a preliminary version of the complete stacking
implementation. The patches need to be cleaned up, and
several are not strictly necessary. There is likely to
be work required in the audit sub-system. It does address
all the shared data, including CIPSO headers. It should
handle CALIPSO once Smack supports it. I will be revising
the set after 5.1.
Complete the transition from module based blob management
to infrastructure based blob management. This includes
the socket, superblock and key blobs.
Change the LSM infrastructure from exposing secids to
exposing an opaque "lsm_export" structure that can contain
information for multiple active security modules. Update
all of the security modules to use information from the
lsm_export structure. Update the LSM interfaces that expose
secids for more than one module to use the export structure.
Update all the users of these interfaces.
Change the LSM infrastructure from using a string/size pair
for security "contexts" to a "lsm_context" structure that
can represent information for multiple modules. This contains
information that allows the "context" to be properly freed
regardless of where it is allocated and where it is used.
Add an interface to identify which security module data
should be presented with SO_PEERSEC. /proc/.../attr/display
will set and report the name of the LSM for which the
security_secid_to_secctx() will use to translate to text.
If it is not explicitly set, the first security module that
supplies secid (now lsm_export) interfaces will be used.
To ensure consistency, a set of module hooks dealing with
the secid/context processing is maintained with each process
that explicitly sets it.
Before sending a network packet verify that all interested
security modules agree on the labeling. Fail if the labeling
cannot be reconciled. This requires a new Netlabel interface
to compare proposed labels, and a change to the return values
from the existing netlabel attribute setting functions.
git://github.com/cschaufler/lsm-stacking.git#5.0-rc3-plus-a
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/kernfs/dir.c | 6 +-
fs/kernfs/inode.c | 31 +-
fs/kernfs/kernfs-internal.h | 4 +-
fs/nfs/inode.c | 13 +-
fs/nfs/internal.h | 8 +-
fs/nfs/nfs4proc.c | 17 +-
fs/nfs/nfs4xdr.c | 16 +-
fs/nfsd/nfs4proc.c | 8 +-
fs/nfsd/nfs4xdr.c | 14 +-
fs/nfsd/vfs.c | 7 +-
fs/proc/base.c | 1 +
include/linux/cred.h | 3 +-
include/linux/lsm_hooks.h | 122 ++--
include/linux/nfs4.h | 8 +-
include/linux/security.h | 165 +++--
include/net/netlabel.h | 18 +-
include/net/route.h | 55 +-
include/net/scm.h | 14 +-
include/net/sock.h | 14 +-
include/uapi/linux/netfilter/xt_CONNMARK.h | 45 +-
include/uapi/linux/netfilter/xt_DSCP.h | 27 +-
include/uapi/linux/netfilter/xt_MARK.h | 17 +-
include/uapi/linux/netfilter/xt_RATEEST.h | 38 +-
include/uapi/linux/netfilter/xt_TCPMSS.h | 13 +-
include/uapi/linux/netfilter_ipv4/ipt_ECN.h | 40 +-
include/uapi/linux/netfilter_ipv4/ipt_TTL.h | 14 +-
include/uapi/linux/netfilter_ipv6/ip6t_HL.h | 14 +-
kernel/audit.c | 60 +-
kernel/audit.h | 9 +-
kernel/auditfilter.c | 6 +-
kernel/auditsc.c | 61 +-
kernel/cred.c | 15 +-
net/ipv4/cipso_ipv4.c | 13 +-
net/ipv4/ip_sockglue.c | 14 +-
net/ipv4/route.c | 61 ++
net/netfilter/nf_conntrack_netlink.c | 27 +-
net/netfilter/nf_conntrack_standalone.c | 16 +-
net/netfilter/nfnetlink_queue.c | 35 +-
net/netfilter/nft_meta.c | 8 +-
net/netfilter/xt_DSCP.c | 149 ++---
net/netfilter/xt_HL.c | 164 ++---
net/netfilter/xt_RATEEST.c | 278 +++------
net/netfilter/xt_SECMARK.c | 9 +-
net/netfilter/xt_TCPMSS.c | 378 +++---------
net/netlabel/netlabel_kapi.c | 125 +++-
net/netlabel/netlabel_unlabeled.c | 99 ++-
net/netlabel/netlabel_unlabeled.h | 2 +-
net/netlabel/netlabel_user.c | 13 +-
net/netlabel/netlabel_user.h | 2 +-
net/socket.c | 17 +
net/unix/af_unix.c | 11 +-
security/apparmor/audit.c | 4 +-
security/apparmor/include/audit.h | 2 +-
security/apparmor/include/net.h | 6 +-
security/apparmor/include/secid.h | 9 +-
security/apparmor/lsm.c | 64 +-
security/apparmor/secid.c | 42 +-
security/integrity/ima/ima.h | 14 +-
security/integrity/ima/ima_api.c | 9 +-
security/integrity/ima/ima_appraise.c | 6 +-
security/integrity/ima/ima_main.c | 34 +-
security/integrity/ima/ima_policy.c | 19 +-
security/security.c | 682 ++++++++++++++++++---
security/selinux/hooks.c | 308 +++++-----
security/selinux/include/audit.h | 6 +-
security/selinux/include/netlabel.h | 7 +
security/selinux/include/objsec.h | 43 +-
security/selinux/netlabel.c | 69 ++-
security/selinux/ss/services.c | 19 +-
security/smack/smack.h | 34 +
security/smack/smack_access.c | 14 +-
security/smack/smack_lsm.c | 389 ++++++------
security/smack/smack_netfilter.c | 48 +-
security/smack/smackfs.c | 23 +-
.../Z6.0+pooncelock+poonceLock+pombonce.litmus | 12 +-
75 files changed, 2369 insertions(+), 1798 deletions(-)
^ permalink raw reply
* [PATCH 72/97] LSM: Add secmark refcounting to call_one list - part 2
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Add secmark_refcount_dec and secmark_refcount_inc to the
LSM hooks for which only the designated module is called.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/security/security.c b/security/security.c
index af3f6a89ee88..fc446af4c3bf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2125,6 +2125,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
loh->secctx_to_secid = secctx_to_secid;
loh->socket_getpeersec_stream = socket_getpeersec_stream;
loh->secmark_relabel_packet = secmark_relabel_packet;
+ loh->secmark_refcount_inc = secmark_refcount_inc;
+ loh->secmark_refcount_dec = secmark_refcount_dec;
return size;
}
--
2.17.0
^ permalink raw reply related
* [PATCH 71/97] LSM: Add secmark refcounting to call_one list
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Add secmark_refcount_dec and secmark_refcount_inc to the
LSM hooks for which only the designated module is called.
This is in support of consistant secmark behavior.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 2 ++
security/security.c | 42 +++++++++++++++++++++++++++++++++++++--
2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index e76e5cd05180..4020e13f0669 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2029,6 +2029,8 @@ struct lsm_one_hooks {
union security_list_options secctx_to_secid;
union security_list_options socket_getpeersec_stream;
union security_list_options secmark_relabel_packet;
+ union security_list_options secmark_refcount_inc;
+ union security_list_options secmark_refcount_dec;
};
/*
diff --git a/security/security.c b/security/security.c
index 024601db215e..af3f6a89ee88 100644
--- a/security/security.c
+++ b/security/security.c
@@ -472,6 +472,12 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
else if (hooks[i].head ==
&security_hook_heads.secmark_relabel_packet)
lsm_base_one.secmark_relabel_packet = hooks[i].hook;
+ else if (hooks[i].head ==
+ &security_hook_heads.secmark_refcount_inc)
+ lsm_base_one.secmark_refcount_inc = hooks[i].hook;
+ else if (hooks[i].head ==
+ &security_hook_heads.secmark_refcount_dec)
+ lsm_base_one.secmark_refcount_dec = hooks[i].hook;
else
continue;
if (lsm_base_one.lsm == NULL)
@@ -752,6 +758,14 @@ int lsm_superblock_alloc(struct super_block *sb)
RC; \
})
+#define call_one_void_hook(FUNC, ...) ({ \
+ struct lsm_one_hooks *LOH = current_cred()->security; \
+ if (LOH->FUNC.FUNC) \
+ LOH->FUNC.FUNC(__VA_ARGS__); \
+ else if (LOH->lsm == NULL && lsm_base_one.FUNC.FUNC) \
+ lsm_base_one.FUNC.FUNC(__VA_ARGS__); \
+})
+
#define call_one_int_hook(FUNC, IRC, ...) ({ \
int RC = IRC; \
struct lsm_one_hooks *LOH = current_cred()->security; \
@@ -2022,6 +2036,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
union security_list_options secctx_to_secid;
union security_list_options socket_getpeersec_stream;
union security_list_options secmark_relabel_packet;
+ union security_list_options secmark_refcount_inc;
+ union security_list_options secmark_refcount_dec;
if (size == 0 || size >= 100)
return -EINVAL;
@@ -2068,6 +2084,28 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
break;
}
}
+ secmark_refcount_inc.secmark_refcount_inc = NULL;
+ hlist_for_each_entry(hp,
+ &security_hook_heads.secmark_refcount_inc,
+ list) {
+ if (size >= strlen(hp->lsm) &&
+ !strncmp(value, hp->lsm, size)) {
+ secmark_refcount_inc = hp->hook;
+ found = true;
+ break;
+ }
+ }
+ secmark_refcount_dec.secmark_refcount_dec = NULL;
+ hlist_for_each_entry(hp,
+ &security_hook_heads.secmark_refcount_dec,
+ list) {
+ if (size >= strlen(hp->lsm) &&
+ !strncmp(value, hp->lsm, size)) {
+ secmark_refcount_dec = hp->hook;
+ found = true;
+ break;
+ }
+ }
if (!found)
return -EINVAL;
@@ -2339,13 +2377,13 @@ EXPORT_SYMBOL(security_secmark_relabel_packet);
void security_secmark_refcount_inc(void)
{
- call_void_hook(secmark_refcount_inc);
+ call_one_void_hook(secmark_refcount_inc);
}
EXPORT_SYMBOL(security_secmark_refcount_inc);
void security_secmark_refcount_dec(void)
{
- call_void_hook(secmark_refcount_dec);
+ call_one_void_hook(secmark_refcount_dec);
}
EXPORT_SYMBOL(security_secmark_refcount_dec);
--
2.17.0
^ permalink raw reply related
* [PATCH 73/97] LSM: refactor security_setprocattr
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Break the common code for setting the lsm_one hooks into
helper function.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 120 ++++++++++++++++----------------------------
1 file changed, 43 insertions(+), 77 deletions(-)
diff --git a/security/security.c b/security/security.c
index fc446af4c3bf..66bc1a580d48 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2016,12 +2016,31 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
return -EINVAL;
}
+/*
+ * The use of the secid_to_secctx memeber of the union is
+ * arbitrary. Any member would work.
+ */
+static bool lsm_add_one(union security_list_options *hook,
+ struct hlist_head *head, char *lsm, size_t size,
+ bool was)
+{
+ struct security_hook_list *hp;
+
+ hlist_for_each_entry(hp, head, list) {
+ if (size >= strlen(hp->lsm) && !strncmp(lsm, hp->lsm, size)) {
+ hook->secid_to_secctx = hp->hook.secid_to_secctx;
+ return true;
+ }
+ }
+ hook->secid_to_secctx = NULL;
+ return was;
+}
+
int security_setprocattr(const char *lsm, const char *name, void *value,
size_t size)
{
struct security_hook_list *hp;
struct lsm_one_hooks *loh = current_cred()->security;
- bool found = false;
char *s;
/*
@@ -2032,80 +2051,31 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
*s = '\0';
if (!strcmp(name, "display")) {
- union security_list_options secid_to_secctx;
- union security_list_options secctx_to_secid;
- union security_list_options socket_getpeersec_stream;
- union security_list_options secmark_relabel_packet;
- union security_list_options secmark_refcount_inc;
- union security_list_options secmark_refcount_dec;
+ struct lsm_one_hooks o;
+ bool found = false;
if (size == 0 || size >= 100)
return -EINVAL;
- secid_to_secctx.secid_to_secctx = NULL;
- hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- secid_to_secctx = hp->hook;
- found = true;
- break;
- }
- }
- secctx_to_secid.secctx_to_secid = NULL;
- hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- secctx_to_secid = hp->hook;
- found = true;
- break;
- }
- }
- socket_getpeersec_stream.socket_getpeersec_stream = NULL;
- hlist_for_each_entry(hp,
- &security_hook_heads.socket_getpeersec_stream,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- socket_getpeersec_stream = hp->hook;
- found = true;
- break;
- }
- }
- secmark_relabel_packet.secmark_relabel_packet = NULL;
- hlist_for_each_entry(hp,
- &security_hook_heads.secmark_relabel_packet,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- secmark_relabel_packet = hp->hook;
- found = true;
- break;
- }
- }
- secmark_refcount_inc.secmark_refcount_inc = NULL;
- hlist_for_each_entry(hp,
- &security_hook_heads.secmark_refcount_inc,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- secmark_refcount_inc = hp->hook;
- found = true;
- break;
- }
- }
- secmark_refcount_dec.secmark_refcount_dec = NULL;
- hlist_for_each_entry(hp,
- &security_hook_heads.secmark_refcount_dec,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- secmark_refcount_dec = hp->hook;
- found = true;
- break;
- }
- }
+ found = lsm_add_one(&o.secid_to_secctx,
+ &security_hook_heads.secid_to_secctx,
+ value, size, found);
+ found = lsm_add_one(&o.secctx_to_secid,
+ &security_hook_heads.secctx_to_secid,
+ value, size, found);
+ found = lsm_add_one(&o.socket_getpeersec_stream,
+ &security_hook_heads.socket_getpeersec_stream,
+ value, size, found);
+ found = lsm_add_one(&o.secmark_relabel_packet,
+ &security_hook_heads.secmark_relabel_packet,
+ value, size, found);
+ found = lsm_add_one(&o.secmark_refcount_inc,
+ &security_hook_heads.secmark_refcount_inc,
+ value, size, found);
+ found = lsm_add_one(&o.secmark_refcount_dec,
+ &security_hook_heads.secmark_refcount_dec,
+ value, size, found);
+
if (!found)
return -EINVAL;
@@ -2120,13 +2090,9 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
if (loh->lsm)
kfree(loh->lsm);
+
+ *loh = o;
loh->lsm = s;
- loh->secid_to_secctx = secid_to_secctx;
- loh->secctx_to_secid = secctx_to_secid;
- loh->socket_getpeersec_stream = socket_getpeersec_stream;
- loh->secmark_relabel_packet = secmark_relabel_packet;
- loh->secmark_refcount_inc = secmark_refcount_inc;
- loh->secmark_refcount_dec = secmark_refcount_dec;
return size;
}
--
2.17.0
^ permalink raw reply related
* [PATCH 77/97] LSM: Correct handling of ENOSYS in inode_setxattr
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
The usual "bail on fail" behavior of LSM hooks doesn't
work for security_inode_setxattr(). Modules are allowed
to return -ENOSYS if the attribute specifed isn't one
they manage. Fix the code to accomodate this unusal case.
This requires changes to the hooks in SELinux and Smack.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 28 ++++++++++++++--------------
security/selinux/hooks.c | 7 ++-----
security/smack/smack_lsm.c | 10 +++++-----
3 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/security/security.c b/security/security.c
index bb0eea873a7e..105b5ee22bcf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1343,24 +1343,24 @@ int security_inode_getattr(const struct path *path)
int security_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
- int ret;
+ struct security_hook_list *hp;
+ int rc = -ENOSYS;
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
- /*
- * SELinux and Smack integrate the cap call,
- * so assume that all LSMs supplying this call do so.
- */
- ret = call_int_hook(inode_setxattr, 1, dentry, name, value, size,
- flags);
- if (ret == 1)
- ret = cap_inode_setxattr(dentry, name, value, size, flags);
- if (ret)
- return ret;
- ret = ima_inode_setxattr(dentry, name, value, size);
- if (ret)
- return ret;
+ hlist_for_each_entry(hp, &security_hook_heads.inode_setxattr, list) {
+ rc = hp->hook.inode_setxattr(dentry, name, value, size, flags);
+ if (rc != -ENOSYS)
+ break;
+ }
+ if (rc == -ENOSYS)
+ rc = cap_inode_setxattr(dentry, name, value, size, flags);
+ if (rc)
+ return rc;
+ rc = ima_inode_setxattr(dentry, name, value, size);
+ if (rc)
+ return rc;
return evm_inode_setxattr(dentry, name, value, size);
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f58c96e2b6c1..501aed18f100 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2998,13 +2998,10 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
int rc = 0;
if (strcmp(name, XATTR_NAME_SELINUX)) {
- rc = cap_inode_setxattr(dentry, name, value, size, flags);
- if (rc)
- return rc;
-
/* Not an attribute we recognize, so just check the
ordinary setattr permission. */
- return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
+ rc = dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
+ return rc ? rc : -ENOSYS;
}
sbsec = selinux_superblock(inode->i_sb);
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c45e2dc3f959..c84c71a31b80 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1194,7 +1194,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
rc = -EINVAL;
} else
- rc = cap_inode_setxattr(dentry, name, value, size, flags);
+ rc = -ENOSYS;
if (check_priv && !smack_privileged(CAP_MAC_ADMIN))
rc = -EPERM;
@@ -1208,11 +1208,11 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
rc = -EINVAL;
}
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
- smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-
if (rc == 0) {
- rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+ smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
+ smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
+ rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)),
+ MAY_WRITE, &ad);
rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
}
--
2.17.0
^ permalink raw reply related
* [PATCH 74/97] Smack: Detect if secmarks can be safely used
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Utilize the security_secmark_refcount_in() hooks to determine
if Smack can safely assume that IP secmarks are not being used
by another LSM. Only use secmarks if they can be determined to
belong to Smack.
[cschaufler@localhost lsm-stacking]$ head -30 ../from-lap-190128/0073*
From 796ddbf9da8e0e8180805591badf182d2578ed5a Mon Sep 17 00:00:00 2001
From: Casey Schaufler <casey@schaufler-ca.com>
Date: Thu, 3 Jan 2019 15:56:59 -0800
Subject: [PATCH 73/79] Smack: Detect if secmarks can be safely used
Utilize the security_secmark_refcount_in() hooks to determine
if Smack can safely assume that IP secmarks are not being used
by another LSM. Only use secmarks if they can be determined to
belong to Smack.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smack.h | 15 +++++++++++++++
security/smack/smack_lsm.c | 16 +++++-----------
security/smack/smack_netfilter.c | 25 +++++++++++++++++++++++--
3 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/security/smack/smack.h b/security/smack/smack.h
index f623d059421d..147afb9233b4 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -553,4 +553,19 @@ static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
}
#endif
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+extern bool smack_use_secmark;
+void smack_secmark_refcount_inc(void);
+
+static inline bool smk_use_secmark(void)
+{
+ return smack_use_secmark;
+}
+#else
+static inline bool smk_use_secmark(void)
+{
+ return false;
+}
+#endif
+
#endif /* _SECURITY_SMACK_H */
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 7b8ad16c09e0..c45e2dc3f959 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3742,7 +3742,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
*/
static struct smack_known *smack_from_skb(struct sk_buff *skb)
{
- if (skb == NULL || skb->secmark == 0)
+ if (skb == NULL || skb->secmark == 0 || !smk_use_secmark())
return NULL;
return smack_from_secid(skb->secmark);
@@ -3776,7 +3776,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
switch (family) {
case PF_INET:
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
/*
* If there is a secmark use it rather than the CIPSO label.
* If there is no secmark fall back to CIPSO.
@@ -3785,7 +3784,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
skp = smack_from_skb(skb);
if (skp)
goto access_check;
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
/*
* Translate what netlabel gave us.
*/
@@ -3799,9 +3797,8 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
netlbl_secattr_destroy(&secattr);
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
access_check:
-#endif
+
#ifdef CONFIG_AUDIT
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
ad.a.u.net->family = family;
@@ -3928,13 +3925,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
s = ssp->smk_out->smk_secid;
break;
case PF_INET:
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
skp = smack_from_skb(skb);
if (skp) {
s = skp->smk_secid;
break;
}
-#endif
/*
* Translate what netlabel gave us.
*/
@@ -4024,7 +4019,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
}
#endif /* CONFIG_IPV6 */
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
/*
* If there is a secmark use it rather than the CIPSO label.
* If there is no secmark fall back to CIPSO.
@@ -4033,7 +4027,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
skp = smack_from_skb(skb);
if (skp)
goto access_check;
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
@@ -4043,9 +4036,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
skp = &smack_known_huh;
netlbl_secattr_destroy(&secattr);
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
access_check:
-#endif
#ifdef CONFIG_AUDIT
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
@@ -4620,6 +4611,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
#ifdef SMACK_IPV6_PORT_LABELING
LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
+#endif
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+ LSM_HOOK_INIT(secmark_refcount_inc, smack_secmark_refcount_inc),
#endif
LSM_HOOK_INIT(sock_graft, smack_sock_graft),
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index 701a1cc1bdcc..ea45b173f8ca 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -21,6 +21,15 @@
#include <net/net_namespace.h>
#include "smack.h"
+bool smack_use_secmark;
+static bool smack_checked_secmark;
+
+void smack_secmark_refcount_inc(void)
+{
+ smack_use_secmark = true;
+ pr_info("Smack: Using network secmarks.\n");
+}
+
#if IS_ENABLED(CONFIG_IPV6)
static unsigned int smack_ipv6_output(void *priv,
@@ -31,7 +40,13 @@ static unsigned int smack_ipv6_output(void *priv,
struct socket_smack *ssp;
struct smack_known *skp;
- if (sk && smack_sock(sk)) {
+ if (!smack_checked_secmark) {
+ security_secmark_refcount_inc();
+ security_secmark_refcount_dec();
+ smack_checked_secmark = true;
+ }
+
+ if (smack_use_secmark && sk && smack_sock(sk)) {
ssp = smack_sock(sk);
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
@@ -49,7 +64,13 @@ static unsigned int smack_ipv4_output(void *priv,
struct socket_smack *ssp;
struct smack_known *skp;
- if (sk && smack_sock(sk)) {
+ if (!smack_checked_secmark) {
+ security_secmark_refcount_inc();
+ security_secmark_refcount_dec();
+ smack_checked_secmark = true;
+ }
+
+ if (smack_use_secmark && sk && smack_sock(sk)) {
ssp = smack_sock(sk);
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
--
2.17.0
^ permalink raw reply related
* [PATCH 75/97] LSM: Support multiple LSMs using inode_init_security
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Refactor security_inode_init_security() so that it can
do the integrity processing for more than one LSM.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 48 +++++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 19 deletions(-)
diff --git a/security/security.c b/security/security.c
index 66bc1a580d48..16ff98c86414 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1066,9 +1066,10 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
const initxattrs initxattrs, void *fs_data)
{
- struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
- struct xattr *lsm_xattr, *evm_xattr, *xattr;
- int ret;
+ struct security_hook_list *p;
+ struct xattr *repo;
+ int rc;
+ int i;
if (unlikely(IS_PRIVATE(inode)))
return 0;
@@ -1076,24 +1077,33 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
if (!initxattrs)
return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
dir, qstr, NULL, NULL, NULL);
- memset(new_xattrs, 0, sizeof(new_xattrs));
- lsm_xattr = new_xattrs;
- ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
- &lsm_xattr->name,
- &lsm_xattr->value,
- &lsm_xattr->value_len);
- if (ret)
- goto out;
- evm_xattr = lsm_xattr + 1;
- ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
- if (ret)
- goto out;
- ret = initxattrs(inode, new_xattrs, fs_data);
+ repo = kzalloc((LSM_COUNT * 2) * sizeof(*repo), GFP_NOFS);
+ if (repo == NULL)
+ return -ENOMEM;
+
+ i = 0;
+ rc = -EOPNOTSUPP;
+ hlist_for_each_entry(p, &security_hook_heads.inode_init_security,
+ list) {
+ rc = p->hook.inode_init_security(inode, dir, qstr,
+ &repo[i].name, &repo[i].value,
+ &repo[i].value_len);
+ if (rc)
+ goto out;
+
+ rc = evm_inode_init_security(inode, &repo[i], &repo[i + 1]);
+ if (rc)
+ goto out;
+
+ i += 2;
+ }
+ rc = initxattrs(inode, repo, fs_data);
out:
- for (xattr = new_xattrs; xattr->value != NULL; xattr++)
- kfree(xattr->value);
- return (ret == -EOPNOTSUPP) ? 0 : ret;
+ for (i-- ; i >= 0; i--)
+ kfree(repo[i].value);
+ kfree(repo);
+ return (rc == -EOPNOTSUPP) ? 0 : rc;
}
EXPORT_SYMBOL(security_inode_init_security);
--
2.17.0
^ permalink raw reply related
* [PATCH 76/97] LSM: Use full security context in security_inode_setsecctx
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
The security hooks security_inode_setsecctx and security_inode_getsecctx
need to maintain the context strings for any and all LSMs that
provide contexts. This information is internal to the kernel
and volitile. If only one LSM uses this information the raw form is
used.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 110 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 108 insertions(+), 2 deletions(-)
diff --git a/security/security.c b/security/security.c
index 16ff98c86414..bb0eea873a7e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -438,6 +438,9 @@ static int lsm_append(char *new, char **result)
/* Base list of once-only hooks */
struct lsm_one_hooks lsm_base_one;
+/* Count of inode_[gs]etsecctx hooks */
+static int lsm_inode_secctx_count;
+
/**
* security_add_hooks - Add a modules hooks to the hook lists.
* @hooks: the hooks to add
@@ -455,6 +458,15 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
hooks[i].lsm = lsm;
hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
+ /*
+ * Keep count of the internal security context using hooks.
+ * Assume that there is a 1:1 mapping from inode_getsecctx
+ * to inode_setsecctx in the security modules.
+ */
+ if (hooks[i].head == &security_hook_heads.inode_getsecctx) {
+ lsm_inode_secctx_count++;
+ continue;
+ }
/*
* Check for the special hooks that are restricted to
* a single module to create the base set. Use the hooks
@@ -2162,15 +2174,109 @@ int security_inode_notifysecctx(struct inode *inode, struct lsm_context *cp)
}
EXPORT_SYMBOL(security_inode_notifysecctx);
+/*
+ * The inode_[gs]etsecctx functions need to proved a context
+ * for multiple security modules. If there is more than one
+ * LSM supplying hooks the format will be
+ * lsm1='value',lsm2='value'[,lsmN='value']...
+ */
+static void lsm_release_secctx(struct lsm_context *cp)
+{
+ kfree(cp->context);
+}
+
int security_inode_setsecctx(struct dentry *dentry, struct lsm_context *cp)
{
- return call_int_hook(inode_setsecctx, 0, dentry, cp);
+ struct security_hook_list *hp;
+ struct lsm_context lc;
+ char *full;
+ char *ctx;
+ char *quote;
+ int rc = 0;
+
+ if (lsm_inode_secctx_count <= 1)
+ return call_int_hook(inode_setsecctx, 0, dentry, cp);
+
+ full = kstrndup(cp->context, cp->len, GFP_KERNEL);
+ if (full == NULL)
+ return -ENOMEM;
+
+ ctx = full;
+ hlist_for_each_entry(hp, &security_hook_heads.inode_setsecctx, list) {
+ if (strncmp(ctx, hp->lsm, strlen(hp->lsm))) {
+ WARN_ONCE(1, "security_inode_setsecctx form1 error\n");
+ rc = -EINVAL;
+ break;
+ }
+ ctx += strlen(hp->lsm);
+ if (ctx[0] != '=' || ctx[1] != '\'') {
+ WARN_ONCE(1, "security_inode_setsecctx form2 error\n");
+ rc = -EINVAL;
+ break;
+ }
+ ctx += 2;
+ quote = strnchr(ctx, cp->len, '\'');
+ if (quote == NULL) {
+ WARN_ONCE(1, "security_inode_setsecctx form3 error\n");
+ rc = -EINVAL;
+ break;
+ }
+ quote[0] = '\0';
+ if (quote[1] != ',' && quote[1] != '\0') {
+ WARN_ONCE(1, "security_inode_setsecctx form4 error\n");
+ rc = -EINVAL;
+ break;
+ }
+ lc.context = ctx;
+ lc.len = strlen(ctx);
+
+ ctx = quote + 2;
+
+ rc = hp->hook.inode_setsecctx(dentry, &lc);
+ if (rc)
+ break;
+ }
+
+ kfree(full);
+ return rc;
}
EXPORT_SYMBOL(security_inode_setsecctx);
int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
{
- return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, cp);
+ struct security_hook_list *hp;
+ struct lsm_context lc;
+ char *final = NULL;
+ char *tp;
+ int rc;
+
+ if (lsm_inode_secctx_count <= 1)
+ return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, cp);
+
+ hlist_for_each_entry(hp, &security_hook_heads.inode_getsecctx, list) {
+ rc = hp->hook.inode_getsecctx(inode, &lc);
+ if (rc) {
+ kfree(final);
+ return rc;
+ }
+ if (final) {
+ tp = kasprintf(GFP_KERNEL, "%s,%s='%s'", final,
+ hp->lsm, lc.context);
+ kfree(final);
+ } else
+ tp = kasprintf(GFP_KERNEL, "%s='%s'", hp->lsm,
+ lc.context);
+ security_release_secctx(&lc);
+ if (tp == NULL) {
+ kfree(final);
+ return -ENOMEM;
+ }
+ final = tp;
+ }
+ cp->context = final;
+ cp->len = strlen(final);
+ cp->release = lsm_release_secctx;
+ return 0;
}
EXPORT_SYMBOL(security_inode_getsecctx);
--
2.17.0
^ permalink raw reply related
* [PATCH 79/97] LSM: Fix for security_init_inode_security
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
The code assumes you can call evm_init_inode_security more
than once for an inode, but that won't work because security.evm
is a single value attribute. This does not make EVM work properly,
but does allow the security modules to initialize their attribures.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 35 +++++++++++++++++++++++++----------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/security/security.c b/security/security.c
index 780c914df9fb..c4265ceb6dd0 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1104,11 +1104,24 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
if (unlikely(IS_PRIVATE(inode)))
return 0;
- if (!initxattrs)
- return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
- dir, qstr, NULL, NULL, NULL);
+ if (!initxattrs) {
+ rc = -EOPNOTSUPP;
+ hlist_for_each_entry(p,
+ &security_hook_heads.inode_init_security,
+ list) {
+ rc = p->hook.inode_init_security(inode, dir, qstr,
+ NULL, NULL, NULL);
+ if (rc == -EOPNOTSUPP) {
+ rc = 0;
+ continue;
+ }
+ if (rc)
+ break;
+ }
+ return rc;
+ }
- repo = kzalloc((LSM_COUNT * 2) * sizeof(*repo), GFP_NOFS);
+ repo = kzalloc((LSM_COUNT + 1) * sizeof(*repo), GFP_NOFS);
if (repo == NULL)
return -ENOMEM;
@@ -1119,18 +1132,20 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
rc = p->hook.inode_init_security(inode, dir, qstr,
&repo[i].name, &repo[i].value,
&repo[i].value_len);
+ if (rc == -EOPNOTSUPP)
+ continue;
if (rc)
goto out;
- rc = evm_inode_init_security(inode, &repo[i], &repo[i + 1]);
- if (rc)
- goto out;
-
- i += 2;
+ i++;
}
+ rc = evm_inode_init_security(inode, &repo[i], &repo[i + 1]);
+ if (rc)
+ goto out;
+
rc = initxattrs(inode, repo, fs_data);
out:
- for (i-- ; i >= 0; i--)
+ for (i++ ; i >= 0; i--)
kfree(repo[i].value);
kfree(repo);
return (rc == -EOPNOTSUPP) ? 0 : rc;
--
2.17.0
^ permalink raw reply related
* [PATCH 78/97] LSM: Infrastructure security blobs for mount options
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Manage LSM data for mount options in the infrastructure
rather than in the individual modules.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 5 +++++
security/security.c | 18 ++++++++++++++++++
security/selinux/hooks.c | 31 ++++++++++++++++++-------------
security/smack/smack_lsm.c | 19 +++++++++++++------
4 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 4020e13f0669..58e5465fdd79 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2046,6 +2046,7 @@ struct lsm_blob_sizes {
int lbs_key;
int lbs_msg_msg;
int lbs_task;
+ int lbs_mnt_opts;
};
/*
@@ -2119,4 +2120,8 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
extern int lsm_inode_alloc(struct inode *inode);
+#ifdef CONFIG_SECURITY
+void *lsm_mnt_opts_alloc(void);
+#endif
+
#endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/security.c b/security/security.c
index 105b5ee22bcf..780c914df9fb 100644
--- a/security/security.c
+++ b/security/security.c
@@ -194,6 +194,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
#ifdef CONFIG_KEYS
lsm_set_blob_size(&needed->lbs_key, &blob_sizes.lbs_key);
#endif
+ lsm_set_blob_size(&needed->lbs_mnt_opts, &blob_sizes.lbs_mnt_opts);
lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
@@ -328,6 +329,7 @@ static void __init ordered_lsm_init(void)
#ifdef CONFIG_KEYS
init_debug("key blob size = %d\n", blob_sizes.lbs_key);
#endif /* CONFIG_KEYS */
+ init_debug("mnt_opts blob size = %d\n", blob_sizes.lbs_mnt_opts);
init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg);
init_debug("sock blob size = %d\n", blob_sizes.lbs_sock);
init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
@@ -738,6 +740,21 @@ int lsm_superblock_alloc(struct super_block *sb)
return 0;
}
+/**
+ * lsm_mnt_opts_alloc - allocate a composite mnt_opts blob
+ *
+ * Allocate the mount options blob
+ *
+ * Returns the blob, or NULL if memory can't be allocated.
+ */
+void *lsm_mnt_opts_alloc(void)
+{
+ if (blob_sizes.lbs_mnt_opts == 0)
+ return NULL;
+
+ return kzalloc(blob_sizes.lbs_mnt_opts, GFP_KERNEL);
+}
+
/*
* Hook list operation macros.
*
@@ -941,6 +958,7 @@ void security_free_mnt_opts(void **mnt_opts)
if (!*mnt_opts)
return;
call_void_hook(sb_free_mnt_opts, *mnt_opts);
+ kfree(*mnt_opts);
*mnt_opts = NULL;
}
EXPORT_SYMBOL(security_free_mnt_opts);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 501aed18f100..e149be6226d6 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -381,14 +381,20 @@ struct selinux_mnt_opts {
const char *fscontext, *context, *rootcontext, *defcontext;
};
+static void *selinux_mnt_opts(void *mnt_opts)
+{
+ if (mnt_opts)
+ return mnt_opts + selinux_blob_sizes.lbs_mnt_opts;
+ return NULL;
+}
+
static void selinux_free_mnt_opts(void *mnt_opts)
{
- struct selinux_mnt_opts *opts = mnt_opts;
+ struct selinux_mnt_opts *opts = selinux_mnt_opts(mnt_opts);
kfree(opts->fscontext);
kfree(opts->context);
kfree(opts->rootcontext);
kfree(opts->defcontext);
- kfree(opts);
}
static inline int inode_doinit(struct inode *inode)
@@ -614,7 +620,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
const struct cred *cred = current_cred();
struct superblock_security_struct *sbsec = selinux_superblock(sb);
struct dentry *root = sbsec->sb->s_root;
- struct selinux_mnt_opts *opts = mnt_opts;
+ struct selinux_mnt_opts *opts = selinux_mnt_opts(mnt_opts);
struct inode_security_struct *root_isec;
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
u32 defcontext_sid = 0;
@@ -629,7 +635,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
server is ready to handle calls. */
goto out;
}
- rc = -EINVAL;
+ /* Don't set any SELinux options. Allow any other LSM
+ that's on the stack to do so. */
pr_warn("SELinux: Unable to set superblock options "
"before the security server is initialized\n");
goto out;
@@ -953,16 +960,17 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
static int selinux_add_opt(int token, const char *s, void **mnt_opts)
{
- struct selinux_mnt_opts *opts = *mnt_opts;
+ struct selinux_mnt_opts *opts = selinux_mnt_opts(*mnt_opts);
if (token == Opt_seclabel) /* eaten and completely ignored */
return 0;
if (!opts) {
- opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
+ opts = lsm_mnt_opts_alloc();
if (!opts)
return -ENOMEM;
*mnt_opts = opts;
+ opts = selinux_mnt_opts(opts);
}
if (!s)
return -ENOMEM;
@@ -1015,10 +1023,8 @@ static int selinux_add_mnt_opt(const char *option, const char *val, int len,
rc = selinux_add_opt(token, val, mnt_opts);
if (unlikely(rc)) {
kfree(val);
- if (*mnt_opts) {
+ if (*mnt_opts)
selinux_free_mnt_opts(*mnt_opts);
- *mnt_opts = NULL;
- }
}
return rc;
}
@@ -2583,10 +2589,8 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
rc = selinux_add_opt(token, arg, mnt_opts);
if (unlikely(rc)) {
kfree(arg);
- if (*mnt_opts) {
+ if (*mnt_opts)
selinux_free_mnt_opts(*mnt_opts);
- *mnt_opts = NULL;
- }
return rc;
}
} else {
@@ -2609,7 +2613,7 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts)
static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
{
- struct selinux_mnt_opts *opts = mnt_opts;
+ struct selinux_mnt_opts *opts = selinux_mnt_opts(mnt_opts);
struct superblock_security_struct *sbsec = selinux_superblock(sb);
u32 sid;
int rc;
@@ -6532,6 +6536,7 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
#ifdef CONFIG_KEYS
.lbs_key = sizeof(struct key_security_struct),
#endif /* CONFIG_KEYS */
+ .lbs_mnt_opts = sizeof(struct selinux_mnt_opts),
.lbs_msg_msg = sizeof(struct msg_security_struct),
.lbs_sock = sizeof(struct sk_security_struct),
.lbs_superblock = sizeof(struct superblock_security_struct),
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c84c71a31b80..f1e0f1378666 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -573,26 +573,33 @@ struct smack_mnt_opts {
const char *fsdefault, *fsfloor, *fshat, *fsroot, *fstransmute;
};
+static void *smack_mnt_opts(void *opts)
+{
+ if (opts)
+ return opts + smack_blob_sizes.lbs_mnt_opts;
+ return NULL;
+}
+
static void smack_free_mnt_opts(void *mnt_opts)
{
- struct smack_mnt_opts *opts = mnt_opts;
+ struct smack_mnt_opts *opts = smack_mnt_opts(mnt_opts);
kfree(opts->fsdefault);
kfree(opts->fsfloor);
kfree(opts->fshat);
kfree(opts->fsroot);
kfree(opts->fstransmute);
- kfree(opts);
}
static int smack_add_opt(int token, const char *s, void **mnt_opts)
{
- struct smack_mnt_opts *opts = *mnt_opts;
+ struct smack_mnt_opts *opts = smack_mnt_opts(*mnt_opts);
if (!opts) {
- opts = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
+ opts = lsm_mnt_opts_alloc();
if (!opts)
return -ENOMEM;
*mnt_opts = opts;
+ opts = smack_mnt_opts(opts);
}
if (!s)
return -ENOMEM;
@@ -654,7 +661,6 @@ static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts)
kfree(arg);
if (*mnt_opts)
smack_free_mnt_opts(*mnt_opts);
- *mnt_opts = NULL;
return rc;
}
} else {
@@ -697,7 +703,7 @@ static int smack_set_mnt_opts(struct super_block *sb,
struct superblock_smack *sp = smack_superblock(sb);
struct inode_smack *isp;
struct smack_known *skp;
- struct smack_mnt_opts *opts = mnt_opts;
+ struct smack_mnt_opts *opts = smack_mnt_opts(mnt_opts);
bool transmute = false;
if (sp->smk_flags & SMK_SB_INITIALIZED)
@@ -4501,6 +4507,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
#ifdef CONFIG_KEYS
.lbs_key = sizeof(struct smack_known *),
#endif /* CONFIG_KEYS */
+ .lbs_mnt_opts = sizeof(struct smack_mnt_opts),
.lbs_msg_msg = sizeof(struct smack_known *),
.lbs_sock = sizeof(struct socket_smack),
.lbs_superblock = sizeof(struct superblock_smack),
--
2.17.0
^ permalink raw reply related
* [PATCH 80/97] Smack: Advertise the secid to netlabel
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Add the secid to the attributes shared with netlabel.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smack_access.c | 8 ++++++--
security/smack/smackfs.c | 8 ++++++--
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index fe2ce3a65822..0764bb85daee 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -549,8 +549,12 @@ struct smack_known *smk_import_entry(const char *string, int len)
skp->smk_known = smack;
skp->smk_secid = smack_next_secid++;
skp->smk_netlabel.domain = skp->smk_known;
- skp->smk_netlabel.flags =
- NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
+ lsm_export_init(&skp->smk_netlabel.attr.le);
+ skp->smk_netlabel.attr.le.flags = LSM_EXPORT_SMACK;
+ skp->smk_netlabel.attr.le.smack = skp->smk_secid;
+ skp->smk_netlabel.flags = NETLBL_SECATTR_DOMAIN |
+ NETLBL_SECATTR_MLS_LVL |
+ NETLBL_SECATTR_SECID;
/*
* If direct labeling works use it.
* Otherwise use mapped labeling.
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 28c567465f6c..abaa5325c32f 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -2953,8 +2953,12 @@ static struct vfsmount *smackfs_mount;
static int __init smk_preset_netlabel(struct smack_known *skp)
{
skp->smk_netlabel.domain = skp->smk_known;
- skp->smk_netlabel.flags =
- NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
+ lsm_export_init(&skp->smk_netlabel.attr.le);
+ skp->smk_netlabel.attr.le.flags = LSM_EXPORT_SMACK;
+ skp->smk_netlabel.attr.le.smack = skp->smk_secid;
+ skp->smk_netlabel.flags = NETLBL_SECATTR_DOMAIN |
+ NETLBL_SECATTR_MLS_LVL |
+ NETLBL_SECATTR_SECID;
return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
&skp->smk_netlabel, strlen(skp->smk_known));
}
--
2.17.0
^ permalink raw reply related
* [PATCH 83/97] Smack: Set netlabel flags properly on new label import
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Ensure that all netlabel flags are correctly set on the
netlabel attribute of a newly imported Smack label.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smackfs.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index abaa5325c32f..0abfa4315fb1 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -931,6 +931,9 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
smack_catset_bit(cat, mapcatset);
}
+ skp->smk_netlabel.flags = NETLBL_SECATTR_DOMAIN |
+ NETLBL_SECATTR_MLS_LVL |
+ NETLBL_SECATTR_SECID;
rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
if (rc >= 0) {
netlbl_catmap_free(skp->smk_netlabel.attr.mls.cat);
--
2.17.0
^ permalink raw reply related
* [PATCH 82/97] Smack: Fix setting of the CIPSO MLS_CAT flags
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Don't tell CIPSO that a netlabel created by Smack has
categories set whenit doesn't.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smack_access.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 0764bb85daee..5fe5c6799b27 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -494,8 +494,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
int cat;
int rc;
int byte;
+ bool has = false;
- sap->flags |= NETLBL_SECATTR_MLS_CAT;
sap->attr.mls.lvl = level;
sap->attr.mls.cat = NULL;
@@ -503,6 +503,7 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
for (m = 0x80; m != 0; m >>= 1, cat++) {
if ((m & *cp) == 0)
continue;
+ has = true;
rc = netlbl_catmap_setbit(&sap->attr.mls.cat,
cat, GFP_KERNEL);
if (rc < 0) {
@@ -511,6 +512,9 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
}
}
+ if (has)
+ sap->flags |= NETLBL_SECATTR_MLS_CAT;
+
return 0;
}
--
2.17.0
^ permalink raw reply related
* [PATCH 81/97] LSM: Change error detection for UDP peer security
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
security_socket_getpeercred_dgram() supplies secids for use
by security_secid_to_secctx(). Sometimes a secid will be invalid.
Move the check for an invalid secid from the LSM specific
socket_getpeercred_dgram hooks into the secid_to_secctx hooks.
This allows for the case where one LSM (Smack) will provide a
secid and another (SELinux) to have an error for the same call.
Regardless of which LSM the caller wants to see the peer security
attributes for the correct result will be provided.
As there is no longer any reason for security_secid_to_secctx()
to return a value make all the secid_to_secctx functions void
instead of int. Add checking for a invalid secid to the Smack
and SELinux secid_to_secctx hooks.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 3 +--
include/linux/security.h | 11 +++++------
net/ipv4/ip_sockglue.c | 4 +---
security/security.c | 7 +++----
security/selinux/hooks.c | 13 +++++++------
security/smack/smack_lsm.c | 17 ++++++++---------
6 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 58e5465fdd79..fec7f86897ea 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -867,7 +867,6 @@
* @sock is the socket
* @skb is the skbuff for the packet being queried
* @l is a pointer to a buffer in which to copy the security data
- * Return 0 on success, error on failure.
* @sk_alloc_security:
* Allocate and attach a security structure to the sk->sk_security field,
* which is used to copy security attributes between local stream sockets.
@@ -1681,7 +1680,7 @@ union security_list_options {
int (*socket_getpeersec_stream)(struct socket *sock,
char __user *optval,
int __user *optlen, unsigned len);
- int (*socket_getpeersec_dgram)(struct socket *sock,
+ void (*socket_getpeersec_dgram)(struct socket *sock,
struct sk_buff *skb,
struct lsm_export *l);
int (*sk_alloc_security)(struct sock *sk, int family, gfp_t priority);
diff --git a/include/linux/security.h b/include/linux/security.h
index cb392c6b620f..7edceb91d77f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1274,8 +1274,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,
- struct lsm_export *l);
+void security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
+ struct lsm_export *l);
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);
@@ -1413,11 +1413,10 @@ 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,
- struct lsm_export *l)
+static inline void security_socket_getpeersec_dgram(struct socket *sock,
+ struct sk_buff *skb,
+ struct lsm_export *l)
{
- return -ENOPROTOOPT;
}
static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 56035b53952d..ae69718d87ae 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -134,9 +134,7 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
struct lsm_context lc;
int err;
- err = security_socket_getpeersec_dgram(NULL, skb, &le);
- if (err)
- return;
+ security_socket_getpeersec_dgram(NULL, skb, &le);
err = security_secid_to_secctx(&le, &lc);
if (err)
diff --git a/security/security.c b/security/security.c
index c4265ceb6dd0..ab1050a2dce3 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2414,12 +2414,11 @@ int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
optval, optlen, len);
}
-int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
- struct lsm_export *l)
+void security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
+ struct lsm_export *l)
{
lsm_export_init(l);
- return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock, skb,
- l);
+ call_void_hook(socket_getpeersec_dgram, sock, skb, l);
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e149be6226d6..22a190f291c0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4835,9 +4835,9 @@ static int selinux_socket_getpeersec_stream(struct socket *sock,
return err;
}
-static int selinux_socket_getpeersec_dgram(struct socket *sock,
- struct sk_buff *skb,
- struct lsm_export *l)
+static void selinux_socket_getpeersec_dgram(struct socket *sock,
+ struct sk_buff *skb,
+ struct lsm_export *l)
{
u32 peer_secid = SECSID_NULL;
u16 family;
@@ -4860,9 +4860,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock,
out:
selinux_export_secid(l, peer_secid);
- if (peer_secid == SECSID_NULL)
- return -EINVAL;
- return 0;
+ return;
}
static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
@@ -6206,6 +6204,9 @@ static int selinux_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp)
u32 secid;
selinux_import_secid(l, &secid);
+ if (secid == SECSID_NULL)
+ return -EINVAL;
+
cp->release = selinux_release_secctx;
if (l->flags & LSM_EXPORT_LENGTH)
return security_sid_to_context(&selinux_state, secid,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index f1e0f1378666..a4c8f93534ec 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3902,9 +3902,9 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
*
* Sets the netlabel socket state on sk from parent
*/
-static int smack_socket_getpeersec_dgram(struct socket *sock,
- struct sk_buff *skb,
- struct lsm_export *l)
+static void smack_socket_getpeersec_dgram(struct socket *sock,
+ struct sk_buff *skb,
+ struct lsm_export *l)
{
struct netlbl_lsm_secattr secattr;
@@ -3912,7 +3912,6 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
struct smack_known *skp;
int family = PF_UNSPEC;
u32 s = 0; /* 0 is the invalid secid */
- int rc;
if (skb != NULL) {
if (skb->protocol == htons(ETH_P_IP))
@@ -3942,8 +3941,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
if (sock != NULL && sock->sk != NULL)
ssp = smack_sock(sock->sk);
netlbl_secattr_init(&secattr);
- rc = netlbl_skbuff_getattr(skb, family, &secattr);
- if (rc == 0) {
+ if (netlbl_skbuff_getattr(skb, family, &secattr) == 0) {
skp = smack_from_secattr(&secattr, ssp);
s = skp->smk_secid;
}
@@ -3958,9 +3956,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
break;
}
smack_export_secid(l, s);
- if (s == 0)
- return -EINVAL;
- return 0;
+ return;
}
/**
@@ -4373,6 +4369,9 @@ static int smack_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp)
u32 secid;
smack_import_secid(l, &secid);
+ if (secid == 0)
+ return -EINVAL;
+
skp = smack_from_secid(secid);
cp->context = (l->flags & LSM_EXPORT_LENGTH) ? NULL : skp->smk_known;
--
2.17.0
^ permalink raw reply related
* [PATCH 87/97] Smack: Let netlabel do the work on connections
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Rather than removing the netlabel socket attribute
on connections set the ambient domain. This is more
in line with the way netlabel "should" be used.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smack_lsm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d9055a0df75c..f965c9e6287e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4057,7 +4057,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
if (hskp == NULL)
rc = netlbl_req_setattr(req, &skp->smk_netlabel);
else
- netlbl_req_delattr(req);
+ rc = netlbl_req_setattr(req, &smack_net_ambient->smk_netlabel);
return rc;
}
--
2.17.0
^ permalink raw reply related
* [PATCH 88/97] Netlabel: Return the labeling type on socket
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Change netlbl_sock_setattr() to return the labeling
type of the domain. This allows the labeling types to
be compared when two LSMs want to determine how a socket
should be used.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
net/netlabel/netlabel_kapi.c | 25 ++++++++++++-------------
security/selinux/netlabel.c | 11 ++++-------
security/smack/smack_lsm.c | 2 ++
3 files changed, 18 insertions(+), 20 deletions(-)
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index db6bb1c037f9..61766da2cfac 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -973,15 +973,14 @@ int netlbl_enabled(void)
* Attach the correct label to the given socket using the security attributes
* specified in @secattr. This function requires exclusive access to @sk,
* which means it either needs to be in the process of being created or locked.
- * Returns zero on success, -EDESTADDRREQ if the domain is configured to use
- * network address selectors (can't blindly label the socket), and negative
- * values on all other failures.
+ * Returns the labeling type of the domain, or negative values on failures.
*
*/
int netlbl_sock_setattr(struct sock *sk,
u16 family,
const struct netlbl_lsm_secattr *secattr)
{
+ int rc;
int ret_val;
struct netlbl_dom_map *dom_entry;
@@ -993,17 +992,17 @@ int netlbl_sock_setattr(struct sock *sk,
}
switch (family) {
case AF_INET:
+ ret_val = dom_entry->def.type;
switch (dom_entry->def.type) {
case NETLBL_NLTYPE_ADDRSELECT:
- ret_val = -EDESTADDRREQ;
break;
case NETLBL_NLTYPE_CIPSOV4:
- ret_val = cipso_v4_sock_setattr(sk,
- dom_entry->def.cipso,
- secattr);
+ rc = cipso_v4_sock_setattr(sk, dom_entry->def.cipso,
+ secattr);
+ if (rc < 0)
+ ret_val = rc;
break;
case NETLBL_NLTYPE_UNLABELED:
- ret_val = 0;
break;
default:
ret_val = -ENOENT;
@@ -1011,17 +1010,17 @@ int netlbl_sock_setattr(struct sock *sk,
break;
#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
+ ret_val = dom_entry->def.type;
switch (dom_entry->def.type) {
case NETLBL_NLTYPE_ADDRSELECT:
- ret_val = -EDESTADDRREQ;
break;
case NETLBL_NLTYPE_CALIPSO:
- ret_val = calipso_sock_setattr(sk,
- dom_entry->def.calipso,
- secattr);
+ rc = calipso_sock_setattr(sk, dom_entry->def.calipso,
+ secattr);
+ if (rc < 0)
+ ret_val = rc;
break;
case NETLBL_NLTYPE_UNLABELED:
- ret_val = 0;
break;
default:
ret_val = -ENOENT;
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 4bbd50237a8a..85156a0cdfc3 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -418,15 +418,12 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
if (secattr == NULL)
return -ENOMEM;
rc = netlbl_sock_setattr(sk, family, secattr);
- switch (rc) {
- case 0:
- sksec->nlbl_state = NLBL_LABELED;
- break;
- case -EDESTADDRREQ:
+ if (rc == NETLBL_NLTYPE_ADDRSELECT)
sksec->nlbl_state = NLBL_REQSKB;
+ else if (rc >= 0)
+ sksec->nlbl_state = NLBL_LABELED;
+ if (rc > 0)
rc = 0;
- break;
- }
return rc;
}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index f965c9e6287e..20eed64e91de 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2337,6 +2337,8 @@ static int smack_netlabel(struct sock *sk)
skp = ssp->smk_out;
rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
+ if (rc > 0)
+ rc = 0;
bh_unlock_sock(sk);
local_bh_enable();
--
2.17.0
^ permalink raw reply related
* [PATCH 86/97] Smack: Don't set the socket label on each send
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
The socket does not need to be relabeled on each send.
Remove the code that does that.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smack_lsm.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d2a73d8a6976..d9055a0df75c 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2379,10 +2379,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc);
}
rcu_read_unlock();
- if (rc != 0)
- return rc;
-
- return smack_netlabel(sk);
+ return rc;
}
#if IS_ENABLED(CONFIG_IPV6)
--
2.17.0
^ permalink raw reply related
* [PATCH 85/97] Smack: Let netlabel do the work on the ambient domain
From: Casey Schaufler @ 2019-02-28 22:43 UTC (permalink / raw)
To: jmorris, linux-security-module, selinux
Cc: keescook, john.johansen, penguin-kernel, paul
In-Reply-To: <20190228224356.2608-1-casey@schaufler-ca.com>
Don't delete the netlabel data from sockets on the
ambient domain as netlabel will do it correctly without
any help.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smack_lsm.c | 31 ++++++++-----------------------
1 file changed, 8 insertions(+), 23 deletions(-)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index a4c8f93534ec..d2a73d8a6976 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2316,37 +2316,27 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
/**
* smack_netlabel - Set the secattr on a socket
* @sk: the socket
- * @labeled: socket label scheme
*
* Convert the outbound smack value (smk_out) to a
* secattr and attach it to the socket.
*
* Returns 0 on success or an error code
*/
-static int smack_netlabel(struct sock *sk, int labeled)
+static int smack_netlabel(struct sock *sk)
{
struct smack_known *skp;
struct socket_smack *ssp = smack_sock(sk);
int rc = 0;
/*
- * Usually the netlabel code will handle changing the
+ * The netlabel code will handle changing the
* packet labeling based on the label.
- * The case of a single label host is different, because
- * a single label host should never get a labeled packet
- * even though the label is usually associated with a packet
- * label.
*/
local_bh_disable();
bh_lock_sock_nested(sk);
- if (ssp->smk_out == smack_net_ambient ||
- labeled == SMACK_UNLABELED_SOCKET)
- netlbl_sock_delattr(sk);
- else {
- skp = ssp->smk_out;
- rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
- }
+ skp = ssp->smk_out;
+ rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
bh_unlock_sock(sk);
local_bh_enable();
@@ -2368,8 +2358,7 @@ static int smack_netlabel(struct sock *sk, int labeled)
static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
{
struct smack_known *skp;
- int rc;
- int sk_lbl;
+ int rc = 0;
struct smack_known *hkp;
struct socket_smack *ssp = smack_sock(sk);
struct smk_audit_info ad;
@@ -2385,19 +2374,15 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
ad.a.u.net->dport = sap->sin_port;
ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
#endif
- sk_lbl = SMACK_UNLABELED_SOCKET;
skp = ssp->smk_out;
rc = smk_access(skp, hkp, MAY_WRITE, &ad);
rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc);
- } else {
- sk_lbl = SMACK_CIPSO_SOCKET;
- rc = 0;
}
rcu_read_unlock();
if (rc != 0)
return rc;
- return smack_netlabel(sk, sk_lbl);
+ return smack_netlabel(sk);
}
#if IS_ENABLED(CONFIG_IPV6)
@@ -2635,7 +2620,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
ssp->smk_out = skp;
if (sock->sk->sk_family == PF_INET) {
- rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
+ rc = smack_netlabel(sock->sk);
if (rc != 0)
printk(KERN_WARNING
"Smack: \"%s\" netlbl error %d.\n",
@@ -2686,7 +2671,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
/*
* Set the outbound netlbl.
*/
- return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
+ return smack_netlabel(sock->sk);
}
/**
--
2.17.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox