619 lines
19 KiB
Diff
619 lines
19 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Casey Schaufler <casey@schaufler-ca.com>
|
|
Date: Fri, 31 Aug 2018 17:23:41 -0700
|
|
Subject: [PATCH] Netfilter: Add a selection for Smack
|
|
|
|
If you are running a single security module it's
|
|
fine to tell the netfilter system that your security
|
|
filters are for SELinux, and everything will work just
|
|
fine. If you have Smack and SELinux at the same time
|
|
you need to be able to differentiate. The netfilter
|
|
secmark (xt_SECMARK) code is set up for multiple security
|
|
modules, although as a comment points out, only one at
|
|
a time. The code wasn't set up to pass the information
|
|
about who should process the secmark in the case of
|
|
multiple security modules, so that had to be fixed.
|
|
|
|
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
|
|
---
|
|
include/linux/lsm_hooks.h | 4 +-
|
|
include/linux/security.h | 20 ++++----
|
|
include/uapi/linux/netfilter/xt_SECMARK.h | 1 +
|
|
kernel/audit.c | 2 +
|
|
kernel/auditsc.c | 2 +
|
|
net/netfilter/nf_conntrack_netlink.c | 10 ++++
|
|
net/netfilter/nf_conntrack_standalone.c | 5 ++
|
|
net/netfilter/nfnetlink_queue.c | 5 ++
|
|
net/netfilter/xt_SECMARK.c | 39 +++++++++++++---
|
|
net/netlabel/netlabel_user.c | 2 +-
|
|
net/unix/af_unix.c | 8 +++-
|
|
security/security.c | 37 +++++++++++----
|
|
security/selinux/hooks.c | 13 +++++-
|
|
security/smack/smack_lsm.c | 56 +++++++++++++++++++----
|
|
security/smack/smack_netfilter.c | 11 +++++
|
|
15 files changed, 175 insertions(+), 40 deletions(-)
|
|
|
|
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
|
|
index 1b27b8bcc779..381dae9c3ec5 100644
|
|
--- a/include/linux/lsm_hooks.h
|
|
+++ b/include/linux/lsm_hooks.h
|
|
@@ -1703,8 +1703,8 @@ union security_list_options {
|
|
const struct request_sock *req);
|
|
void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
|
|
int (*secmark_relabel_packet)(struct secids *secid);
|
|
- void (*secmark_refcount_inc)(void);
|
|
- void (*secmark_refcount_dec)(void);
|
|
+ void (*secmark_refcount_inc)(u8 lsm);
|
|
+ void (*secmark_refcount_dec)(u8 lsm);
|
|
void (*req_classify_flow)(const struct request_sock *req,
|
|
struct flowi *fl);
|
|
int (*tun_dev_alloc_security)(void **security);
|
|
diff --git a/include/linux/security.h b/include/linux/security.h
|
|
index ad146916f19b..bb4b8ac9e1b2 100644
|
|
--- a/include/linux/security.h
|
|
+++ b/include/linux/security.h
|
|
@@ -83,15 +83,9 @@ enum lsm_event {
|
|
|
|
struct secids {
|
|
u32 common;
|
|
-#ifdef CONFIG_SECURITY_SELINUX
|
|
u32 selinux;
|
|
-#endif
|
|
-#ifdef CONFIG_SECURITY_SMACK
|
|
u32 smack;
|
|
-#endif
|
|
-#ifdef CONFIG_SECURITY_APPARMOR
|
|
u32 apparmor;
|
|
-#endif
|
|
u32 flags;
|
|
};
|
|
|
|
@@ -1315,8 +1309,9 @@ void security_inet_csk_clone(struct sock *newsk,
|
|
void security_inet_conn_established(struct sock *sk,
|
|
struct sk_buff *skb);
|
|
int security_secmark_relabel_packet(struct secids *secid);
|
|
-void security_secmark_refcount_inc(void);
|
|
-void security_secmark_refcount_dec(void);
|
|
+void security_secmark_refcount_inc(u8 lsm);
|
|
+void security_secmark_refcount_dec(u8 lsm);
|
|
+int security_secmark_mode(u8 lsm);
|
|
int security_tun_dev_alloc_security(void **security);
|
|
void security_tun_dev_free_security(void *security);
|
|
int security_tun_dev_create(void);
|
|
@@ -1494,14 +1489,19 @@ static inline int security_secmark_relabel_packet(struct secids *secid)
|
|
return 0;
|
|
}
|
|
|
|
-static inline void security_secmark_refcount_inc(void)
|
|
+static inline void security_secmark_refcount_inc(u8 lsm)
|
|
{
|
|
}
|
|
|
|
-static inline void security_secmark_refcount_dec(void)
|
|
+static inline void security_secmark_refcount_dec(u8 lsm)
|
|
{
|
|
}
|
|
|
|
+static inline int security_secmark_mode(u8 lsm)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static inline int security_tun_dev_alloc_security(void **security)
|
|
{
|
|
return 0;
|
|
diff --git a/include/uapi/linux/netfilter/xt_SECMARK.h b/include/uapi/linux/netfilter/xt_SECMARK.h
|
|
index beb2cadba8a9..1f9f1b912d22 100644
|
|
--- a/include/uapi/linux/netfilter/xt_SECMARK.h
|
|
+++ b/include/uapi/linux/netfilter/xt_SECMARK.h
|
|
@@ -12,6 +12,7 @@
|
|
* packets are being marked for.
|
|
*/
|
|
#define SECMARK_MODE_SEL 0x01 /* SELinux */
|
|
+#define SECMARK_MODE_SMACK 0x02 /* Smack */
|
|
#define SECMARK_SECCTX_MAX 256
|
|
|
|
struct xt_secmark_target_info {
|
|
diff --git a/kernel/audit.c b/kernel/audit.c
|
|
index fdde19d100eb..4b227a99fc85 100644
|
|
--- a/kernel/audit.c
|
|
+++ b/kernel/audit.c
|
|
@@ -2181,7 +2181,9 @@ void audit_log_name(struct audit_context *context, struct audit_names *n,
|
|
u32 len;
|
|
if (security_secid_to_secctx(
|
|
&n->osid, &ctx, &len)) {
|
|
+#ifndef CONFIG_SECURITY_STACKING
|
|
audit_log_format(ab, " osid=%u", n->osid.common);
|
|
+#endif
|
|
if (call_panic)
|
|
*call_panic = 2;
|
|
} else {
|
|
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
|
|
index 8018f6cbd9be..498d8942c344 100644
|
|
--- a/kernel/auditsc.c
|
|
+++ b/kernel/auditsc.c
|
|
@@ -1214,7 +1214,9 @@ static void show_special(struct audit_context *context, int *call_panic)
|
|
char *ctx = NULL;
|
|
u32 len;
|
|
if (security_secid_to_secctx(&osid, &ctx, &len)) {
|
|
+#ifndef CONFIG_SECURITY_STACKING
|
|
audit_log_format(ab, " osid=%u", osid.common);
|
|
+#endif
|
|
*call_panic = 1;
|
|
} else {
|
|
audit_log_format(ab, " obj=%s", ctx);
|
|
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
|
|
index 157425412d1e..a3c80402f7a8 100644
|
|
--- a/net/netfilter/nf_conntrack_netlink.c
|
|
+++ b/net/netfilter/nf_conntrack_netlink.c
|
|
@@ -335,8 +335,13 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
|
|
char *secctx;
|
|
struct secids secid;
|
|
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
secid_init(&secid);
|
|
+ secid.selinux = ct->secmark;
|
|
+ secid.smack = ct->secmark;
|
|
+#else
|
|
secid.common = ct->secmark;
|
|
+#endif
|
|
|
|
ret = security_secid_to_secctx(&secid, &secctx, &len);
|
|
if (ret)
|
|
@@ -629,8 +634,13 @@ static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
|
|
int len, ret;
|
|
struct secids secid;
|
|
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
secid_init(&secid);
|
|
+ secid.selinux = ct->secmark;
|
|
+ secid.smack = ct->secmark;
|
|
+#else
|
|
secid.common = ct->secmark;
|
|
+#endif
|
|
|
|
ret = security_secid_to_secctx(&secid, NULL, &len);
|
|
if (ret)
|
|
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
|
|
index b9dd474c25de..24df21902d81 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 secids secid;
|
|
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
secid_init(&secid);
|
|
+ secid.selinux = ct->secmark;
|
|
+ secid.smack = ct->secmark;
|
|
+#else
|
|
secid.common = ct->secmark;
|
|
+#endif
|
|
|
|
ret = security_secid_to_secctx(&secid, &secctx, &len);
|
|
if (ret)
|
|
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
|
|
index e91fabdbe9e0..b5fe7f87f180 100644
|
|
--- a/net/netfilter/nfnetlink_queue.c
|
|
+++ b/net/netfilter/nfnetlink_queue.c
|
|
@@ -317,8 +317,13 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
|
|
read_lock_bh(&skb->sk->sk_callback_lock);
|
|
|
|
if (skb->secmark) {
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
secid_init(&secid);
|
|
+ secid.selinux = skb->secmark;
|
|
+ secid.smack = skb->secmark;
|
|
+#else
|
|
secid.common = skb->secmark;
|
|
+#endif
|
|
security_secid_to_secctx(&secid, secdata, &seclen);
|
|
}
|
|
|
|
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
|
|
index 08ad57b503b8..d46fd431e785 100644
|
|
--- a/net/netfilter/xt_SECMARK.c
|
|
+++ b/net/netfilter/xt_SECMARK.c
|
|
@@ -40,6 +40,9 @@ secmark_tg(struct sk_buff *skb, const struct xt_secmark_target_info_v1 *info)
|
|
case SECMARK_MODE_SEL:
|
|
secmark = info->secid;
|
|
break;
|
|
+ case SECMARK_MODE_SMACK:
|
|
+ secmark = info->secid;
|
|
+ break;
|
|
default:
|
|
BUG();
|
|
}
|
|
@@ -58,7 +61,16 @@ static int checkentry_lsm(struct xt_secmark_target_info_v1 *info)
|
|
|
|
err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
|
|
&secid);
|
|
- info->secid = secid.selinux;
|
|
+ switch (info->mode) {
|
|
+ case SECMARK_MODE_SEL:
|
|
+ info->secid = secid.selinux;
|
|
+ break;
|
|
+ case SECMARK_MODE_SMACK:
|
|
+ info->secid = secid.smack;
|
|
+ break;
|
|
+ default:
|
|
+ BUG();
|
|
+ }
|
|
|
|
if (err) {
|
|
if (err == -EINVAL)
|
|
@@ -79,7 +91,8 @@ static int checkentry_lsm(struct xt_secmark_target_info_v1 *info)
|
|
return err;
|
|
}
|
|
|
|
- security_secmark_refcount_inc();
|
|
+ if (mode)
|
|
+ security_secmark_refcount_inc(mode);
|
|
return 0;
|
|
}
|
|
|
|
@@ -95,15 +108,23 @@ secmark_tg_check(const char *table, struct xt_secmark_target_info_v1 *info)
|
|
return -EINVAL;
|
|
}
|
|
|
|
- if (mode && mode != info->mode) {
|
|
- pr_info_ratelimited("mode already set to %hu cannot mix with rules for mode %hu\n",
|
|
- mode, info->mode);
|
|
+ if (mode) {
|
|
+ if (mode != info->mode) {
|
|
+ pr_info("mode already set to %hu cannot mix with "
|
|
+ "rules for mode %hu\n", mode, info->mode);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ } else if (security_secmark_mode(info->mode)) {
|
|
+ pr_info("mode already set and cannot mix with "
|
|
+ "rules for mode %hu\n", info->mode);
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (info->mode) {
|
|
case SECMARK_MODE_SEL:
|
|
break;
|
|
+ case SECMARK_MODE_SMACK:
|
|
+ break;
|
|
default:
|
|
pr_info_ratelimited("invalid mode: %hu\n", info->mode);
|
|
return -EINVAL;
|
|
@@ -122,8 +143,14 @@ static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
|
|
{
|
|
switch (mode) {
|
|
case SECMARK_MODE_SEL:
|
|
- security_secmark_refcount_dec();
|
|
+ break;
|
|
+ case SECMARK_MODE_SMACK:
|
|
+ break;
|
|
+ default:
|
|
+ pr_info("invalid mode: %hu\n", mode);
|
|
+ return;
|
|
}
|
|
+ security_secmark_refcount_dec(mode);
|
|
}
|
|
|
|
static int secmark_tg_check_v0(const struct xt_tgchk_param *par)
|
|
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
|
|
index 22474f5c93d7..42ee220f6940 100644
|
|
--- a/net/netlabel/netlabel_user.c
|
|
+++ b/net/netlabel/netlabel_user.c
|
|
@@ -112,7 +112,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
|
|
from_kuid(&init_user_ns, audit_info->loginuid),
|
|
audit_info->sessionid);
|
|
|
|
- if (audit_info->secid.common != 0 &&
|
|
+ if (secid_valid(&audit_info->secid) &&
|
|
security_secid_to_secctx(&audit_info->secid,
|
|
&secctx,
|
|
&secctx_len) == 0) {
|
|
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
|
|
index 991d3540f50d..a7b3dc16cde6 100644
|
|
--- a/net/unix/af_unix.c
|
|
+++ b/net/unix/af_unix.c
|
|
@@ -141,9 +141,10 @@ 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)
|
|
{
|
|
- UNIXCB(skb).secid = scm->secid.common;
|
|
#ifdef CONFIG_SECURITY_STACKING
|
|
secid_to_skb(&scm->secid, skb);
|
|
+#else
|
|
+ UNIXCB(skb).secid = scm->secid.common;
|
|
#endif
|
|
}
|
|
|
|
@@ -158,7 +159,12 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
|
|
|
|
static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
|
|
{
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
+ return memcmp(&scm->secid, &(UNIXCB(skb).secid),
|
|
+ sizeof(scm->secid)) == 0;
|
|
+#else
|
|
return (scm->secid.common == UNIXCB(skb).secid);
|
|
+#endif
|
|
}
|
|
#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 96e795600adb..5a8047fcb9cd 100644
|
|
--- a/security/security.c
|
|
+++ b/security/security.c
|
|
@@ -351,10 +351,9 @@ void __init security_add_blobs(struct lsm_blob_sizes *needed)
|
|
lsm_set_size(&needed->lbs_key, &blob_sizes.lbs_key);
|
|
#endif
|
|
lsm_set_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
|
|
-#ifdef CONFIG_NETWORK_SECMARK
|
|
+#ifdef CONFIG_SECURITY_NETWORK
|
|
/*
|
|
- * Store the most likely secmark with the socket
|
|
- * so that it doesn't have to be a managed object.
|
|
+ * Store the secids with the socket for UDS.
|
|
*/
|
|
if (needed->lbs_sock && blob_sizes.lbs_sock == 0)
|
|
blob_sizes.lbs_sock = sizeof(struct secids);
|
|
@@ -2238,11 +2237,17 @@ int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb,
|
|
#ifdef CONFIG_SECURITY_STACKING
|
|
struct security_hook_list *hp;
|
|
int rc = -ENOPROTOOPT;
|
|
+ int trc;
|
|
|
|
secid_init(secid);
|
|
hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_dgram,
|
|
- list)
|
|
- rc = hp->hook.socket_getpeersec_dgram(sock, skb, secid);
|
|
+ list) {
|
|
+ trc = hp->hook.socket_getpeersec_dgram(sock, skb, secid);
|
|
+ if (trc == 0)
|
|
+ rc = 0;
|
|
+ else if (trc != -ENOPROTOOPT)
|
|
+ return trc;
|
|
+ }
|
|
|
|
return rc;
|
|
#else
|
|
@@ -2332,18 +2337,32 @@ int security_secmark_relabel_packet(struct secids *secid)
|
|
}
|
|
EXPORT_SYMBOL(security_secmark_relabel_packet);
|
|
|
|
-void security_secmark_refcount_inc(void)
|
|
+void security_secmark_refcount_inc(u8 lsm)
|
|
{
|
|
- call_void_hook(secmark_refcount_inc);
|
|
+ call_void_hook(secmark_refcount_inc, lsm);
|
|
}
|
|
EXPORT_SYMBOL(security_secmark_refcount_inc);
|
|
|
|
-void security_secmark_refcount_dec(void)
|
|
+void security_secmark_refcount_dec(u8 lsm)
|
|
{
|
|
- call_void_hook(secmark_refcount_dec);
|
|
+ call_void_hook(secmark_refcount_dec, lsm);
|
|
}
|
|
EXPORT_SYMBOL(security_secmark_refcount_dec);
|
|
|
|
+static u8 security_secmark_mode_value;
|
|
+
|
|
+int security_secmark_mode(u8 lsm)
|
|
+{
|
|
+ if (security_secmark_mode_value == 0) {
|
|
+ security_secmark_mode_value = lsm;
|
|
+ return 0;
|
|
+ }
|
|
+ if (security_secmark_mode_value == lsm)
|
|
+ return 0;
|
|
+ return -EBUSY;
|
|
+}
|
|
+EXPORT_SYMBOL(security_secmark_mode);
|
|
+
|
|
int security_tun_dev_alloc_security(void **security)
|
|
{
|
|
return call_int_hook(tun_dev_alloc_security, 0, security);
|
|
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
|
|
index 666f2b631614..02a9aab5e901 100644
|
|
--- a/security/selinux/hooks.c
|
|
+++ b/security/selinux/hooks.c
|
|
@@ -50,6 +50,7 @@
|
|
#include <linux/mount.h>
|
|
#include <linux/netfilter_ipv4.h>
|
|
#include <linux/netfilter_ipv6.h>
|
|
+#include <linux/netfilter/xt_SECMARK.h>
|
|
#include <linux/tty.h>
|
|
#include <net/icmp.h>
|
|
#include <net/ip.h> /* for local_port_range[] */
|
|
@@ -5407,13 +5408,21 @@ static int selinux_secmark_relabel_packet(struct secids *secid)
|
|
PACKET__RELABELTO, NULL);
|
|
}
|
|
|
|
-static void selinux_secmark_refcount_inc(void)
|
|
+static void selinux_secmark_refcount_inc(u8 lsm)
|
|
{
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
+ if (lsm != SECMARK_MODE_SEL)
|
|
+ return;
|
|
+#endif
|
|
atomic_inc(&selinux_secmark_refcount);
|
|
}
|
|
|
|
-static void selinux_secmark_refcount_dec(void)
|
|
+static void selinux_secmark_refcount_dec(u8 lsm)
|
|
{
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
+ if (lsm != SECMARK_MODE_SEL)
|
|
+ return;
|
|
+#endif
|
|
atomic_dec(&selinux_secmark_refcount);
|
|
}
|
|
|
|
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
|
|
index dd0313001e5e..bf2e6537dce7 100644
|
|
--- a/security/smack/smack_lsm.c
|
|
+++ b/security/smack/smack_lsm.c
|
|
@@ -35,6 +35,7 @@
|
|
#include <net/cipso_ipv4.h>
|
|
#include <net/ip.h>
|
|
#include <net/ipv6.h>
|
|
+#include <linux/netfilter/xt_SECMARK.h>
|
|
#include <linux/audit.h>
|
|
#include <linux/magic.h>
|
|
#include <linux/dcache.h>
|
|
@@ -52,6 +53,11 @@
|
|
#define SMK_RECEIVING 1
|
|
#define SMK_SENDING 2
|
|
|
|
+/*
|
|
+ * SECMARK reference count
|
|
+ */
|
|
+static atomic_t smack_secmark_refcount = ATOMIC_INIT(0);
|
|
+
|
|
#ifdef SMACK_IPV6_PORT_LABELING
|
|
DEFINE_MUTEX(smack_ipv6_lock);
|
|
static LIST_HEAD(smk_ipv6_port_list);
|
|
@@ -3815,6 +3821,19 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
|
|
}
|
|
#endif /* CONFIG_IPV6 */
|
|
|
|
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
|
|
+static bool smack_owns_secmark(const struct sk_buff *skb)
|
|
+{
|
|
+ if (skb == NULL || skb->secmark == 0)
|
|
+ return false;
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
+ return atomic_read(&smack_secmark_refcount) != 0;
|
|
+#else
|
|
+ return true;
|
|
+#endif
|
|
+}
|
|
+#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
|
|
+
|
|
/**
|
|
* smack_socket_sock_rcv_skb - Smack packet delivery access check
|
|
* @sk: socket
|
|
@@ -3849,7 +3868,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|
* If there is no secmark fall back to CIPSO.
|
|
* The secmark is assumed to reflect policy better.
|
|
*/
|
|
- if (skb && skb->secmark != 0) {
|
|
+ if (smack_owns_secmark(skb)) {
|
|
skp = smack_from_secid(skb->secmark);
|
|
goto access_check;
|
|
}
|
|
@@ -3895,7 +3914,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|
proto != IPPROTO_TCP && proto != IPPROTO_DCCP)
|
|
break;
|
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
|
- if (skb)
|
|
+ if (smack_owns_secmark(skb))
|
|
skp = smack_from_secid(skb->secmark);
|
|
else
|
|
skp = smack_ipv6host_label(&sadd);
|
|
@@ -3997,7 +4016,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
|
|
break;
|
|
case PF_INET:
|
|
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
|
|
- if (skb->secmark) {
|
|
+ if (smack_owns_secmark(skb)) {
|
|
s = skb->secmark;
|
|
if (s != 0)
|
|
break;
|
|
@@ -4018,7 +4037,8 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
|
|
break;
|
|
case PF_INET6:
|
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
|
- s = skb->secmark;
|
|
+ if (smack_owns_secmark(skb))
|
|
+ s = skb->secmark;
|
|
#endif
|
|
break;
|
|
}
|
|
@@ -4096,11 +4116,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
|
* If there is no secmark fall back to CIPSO.
|
|
* The secmark is assumed to reflect policy better.
|
|
*/
|
|
- if (skb) {
|
|
- if (skb->secmark != 0) {
|
|
- skp = smack_from_secid(skb->secmark);
|
|
- goto access_check;
|
|
- }
|
|
+ if (smack_owns_secmark(skb)) {
|
|
+ skp = smack_from_secid(skb->secmark);
|
|
+ goto access_check;
|
|
}
|
|
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
|
|
|
|
@@ -4176,6 +4194,24 @@ static void smack_inet_csk_clone(struct sock *sk,
|
|
ssp->smk_packet = NULL;
|
|
}
|
|
|
|
+static void smack_secmark_refcount_inc(u8 lsm)
|
|
+{
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
+ if (lsm != SECMARK_MODE_SMACK)
|
|
+ return;
|
|
+#endif
|
|
+ atomic_inc(&smack_secmark_refcount);
|
|
+}
|
|
+
|
|
+static void smack_secmark_refcount_dec(u8 lsm)
|
|
+{
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
+ if (lsm != SECMARK_MODE_SMACK)
|
|
+ return;
|
|
+#endif
|
|
+ atomic_dec(&smack_secmark_refcount);
|
|
+}
|
|
+
|
|
/*
|
|
* Key management security hooks
|
|
*
|
|
@@ -4690,6 +4726,8 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
|
|
LSM_HOOK_INIT(sock_graft, smack_sock_graft),
|
|
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
|
|
LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
|
|
+ LSM_HOOK_INIT(secmark_refcount_inc, smack_secmark_refcount_inc),
|
|
+ LSM_HOOK_INIT(secmark_refcount_dec, smack_secmark_refcount_dec),
|
|
|
|
/* key management security hooks */
|
|
#ifdef CONFIG_KEYS
|
|
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
|
|
index 701a1cc1bdcc..596aba2e4d6b 100644
|
|
--- a/security/smack/smack_netfilter.c
|
|
+++ b/security/smack/smack_netfilter.c
|
|
@@ -16,6 +16,7 @@
|
|
|
|
#include <linux/netfilter_ipv4.h>
|
|
#include <linux/netfilter_ipv6.h>
|
|
+#include <linux/netfilter/xt_SECMARK.h>
|
|
#include <linux/netdevice.h>
|
|
#include <net/inet_sock.h>
|
|
#include <net/net_namespace.h>
|
|
@@ -31,6 +32,11 @@ static unsigned int smack_ipv6_output(void *priv,
|
|
struct socket_smack *ssp;
|
|
struct smack_known *skp;
|
|
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
+ if (security_secmark_mode(SECMARK_MODE_SMACK))
|
|
+ return NF_ACCEPT;
|
|
+#endif
|
|
+
|
|
if (sk && smack_sock(sk)) {
|
|
ssp = smack_sock(sk);
|
|
skp = ssp->smk_out;
|
|
@@ -49,6 +55,11 @@ static unsigned int smack_ipv4_output(void *priv,
|
|
struct socket_smack *ssp;
|
|
struct smack_known *skp;
|
|
|
|
+#ifdef CONFIG_SECURITY_STACKING
|
|
+ if (security_secmark_mode(SECMARK_MODE_SMACK))
|
|
+ return NF_ACCEPT;
|
|
+#endif
|
|
+
|
|
if (sk && smack_sock(sk)) {
|
|
ssp = smack_sock(sk);
|
|
skp = ssp->smk_out;
|
|
--
|
|
https://clearlinux.org
|
|
|