aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/selinux.h45
-rw-r--r--net/netfilter/xt_SECMARK.c13
-rw-r--r--security/selinux/exports.c20
-rw-r--r--security/selinux/hooks.c46
-rw-r--r--security/selinux/include/xfrm.h12
-rw-r--r--security/selinux/xfrm.c18
6 files changed, 132 insertions, 22 deletions
diff --git a/include/linux/selinux.h b/include/linux/selinux.h
index 6080f73fc85f..8c2cc4c02526 100644
--- a/include/linux/selinux.h
+++ b/include/linux/selinux.h
@@ -120,16 +120,35 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
120int selinux_string_to_sid(char *str, u32 *sid); 120int selinux_string_to_sid(char *str, u32 *sid);
121 121
122/** 122/**
123 * selinux_relabel_packet_permission - check permission to relabel a packet 123 * selinux_secmark_relabel_packet_permission - secmark permission check
124 * @sid: ID value to be applied to network packet (via SECMARK, most likely) 124 * @sid: SECMARK ID value to be applied to network packet
125 * 125 *
126 * Returns 0 if the current task is allowed to label packets with the 126 * Returns 0 if the current task is allowed to set the SECMARK label of
127 * supplied security ID. Note that it is implicit that the packet is always 127 * packets with the supplied security ID. Note that it is implicit that
128 * being relabeled from the default unlabled value, and that the access 128 * the packet is always being relabeled from the default unlabeled value,
129 * control decision is made in the AVC. 129 * and that the access control decision is made in the AVC.
130 */ 130 */
131int selinux_relabel_packet_permission(u32 sid); 131int selinux_secmark_relabel_packet_permission(u32 sid);
132 132
133/**
134 * selinux_secmark_refcount_inc - increments the secmark use counter
135 *
136 * SELinux keeps track of the current SECMARK targets in use so it knows
137 * when to apply SECMARK label access checks to network packets. This
138 * function incements this reference count to indicate that a new SECMARK
139 * target has been configured.
140 */
141void selinux_secmark_refcount_inc(void);
142
143/**
144 * selinux_secmark_refcount_dec - decrements the secmark use counter
145 *
146 * SELinux keeps track of the current SECMARK targets in use so it knows
147 * when to apply SECMARK label access checks to network packets. This
148 * function decements this reference count to indicate that one of the
149 * existing SECMARK targets has been removed/flushed.
150 */
151void selinux_secmark_refcount_dec(void);
133#else 152#else
134 153
135static inline int selinux_audit_rule_init(u32 field, u32 op, 154static inline int selinux_audit_rule_init(u32 field, u32 op,
@@ -184,11 +203,21 @@ static inline int selinux_string_to_sid(const char *str, u32 *sid)
184 return 0; 203 return 0;
185} 204}
186 205
187static inline int selinux_relabel_packet_permission(u32 sid) 206static inline int selinux_secmark_relabel_packet_permission(u32 sid)
188{ 207{
189 return 0; 208 return 0;
190} 209}
191 210
211static inline void selinux_secmark_refcount_inc(void)
212{
213 return;
214}
215
216static inline void selinux_secmark_refcount_dec(void)
217{
218 return;
219}
220
192#endif /* CONFIG_SECURITY_SELINUX */ 221#endif /* CONFIG_SECURITY_SELINUX */
193 222
194#endif /* _LINUX_SELINUX_H */ 223#endif /* _LINUX_SELINUX_H */
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index b11b3ecbb39d..7708e2084ce2 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -72,12 +72,13 @@ static bool checkentry_selinux(struct xt_secmark_target_info *info)
72 return false; 72 return false;
73 } 73 }
74 74
75 err = selinux_relabel_packet_permission(sel->selsid); 75 err = selinux_secmark_relabel_packet_permission(sel->selsid);
76 if (err) { 76 if (err) {
77 printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); 77 printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
78 return false; 78 return false;
79 } 79 }
80 80
81 selinux_secmark_refcount_inc();
81 return true; 82 return true;
82} 83}
83 84
@@ -110,11 +111,20 @@ secmark_tg_check(const char *tablename, const void *entry,
110 return true; 111 return true;
111} 112}
112 113
114void secmark_tg_destroy(const struct xt_target *target, void *targinfo)
115{
116 switch (mode) {
117 case SECMARK_MODE_SEL:
118 selinux_secmark_refcount_dec();
119 }
120}
121
113static struct xt_target secmark_tg_reg[] __read_mostly = { 122static struct xt_target secmark_tg_reg[] __read_mostly = {
114 { 123 {
115 .name = "SECMARK", 124 .name = "SECMARK",
116 .family = AF_INET, 125 .family = AF_INET,
117 .checkentry = secmark_tg_check, 126 .checkentry = secmark_tg_check,
127 .destroy = secmark_tg_destroy,
118 .target = secmark_tg, 128 .target = secmark_tg,
119 .targetsize = sizeof(struct xt_secmark_target_info), 129 .targetsize = sizeof(struct xt_secmark_target_info),
120 .table = "mangle", 130 .table = "mangle",
@@ -124,6 +134,7 @@ static struct xt_target secmark_tg_reg[] __read_mostly = {
124 .name = "SECMARK", 134 .name = "SECMARK",
125 .family = AF_INET6, 135 .family = AF_INET6,
126 .checkentry = secmark_tg_check, 136 .checkentry = secmark_tg_check,
137 .destroy = secmark_tg_destroy,
127 .target = secmark_tg, 138 .target = secmark_tg,
128 .targetsize = sizeof(struct xt_secmark_target_info), 139 .targetsize = sizeof(struct xt_secmark_target_info),
129 .table = "mangle", 140 .table = "mangle",
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
index b6f96943be1f..87d2bb3ea355 100644
--- a/security/selinux/exports.c
+++ b/security/selinux/exports.c
@@ -17,10 +17,14 @@
17#include <linux/selinux.h> 17#include <linux/selinux.h>
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/ipc.h> 19#include <linux/ipc.h>
20#include <asm/atomic.h>
20 21
21#include "security.h" 22#include "security.h"
22#include "objsec.h" 23#include "objsec.h"
23 24
25/* SECMARK reference count */
26extern atomic_t selinux_secmark_refcount;
27
24int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen) 28int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
25{ 29{
26 if (selinux_enabled) 30 if (selinux_enabled)
@@ -74,7 +78,7 @@ int selinux_string_to_sid(char *str, u32 *sid)
74} 78}
75EXPORT_SYMBOL_GPL(selinux_string_to_sid); 79EXPORT_SYMBOL_GPL(selinux_string_to_sid);
76 80
77int selinux_relabel_packet_permission(u32 sid) 81int selinux_secmark_relabel_packet_permission(u32 sid)
78{ 82{
79 if (selinux_enabled) { 83 if (selinux_enabled) {
80 struct task_security_struct *tsec = current->security; 84 struct task_security_struct *tsec = current->security;
@@ -84,4 +88,16 @@ int selinux_relabel_packet_permission(u32 sid)
84 } 88 }
85 return 0; 89 return 0;
86} 90}
87EXPORT_SYMBOL_GPL(selinux_relabel_packet_permission); 91EXPORT_SYMBOL_GPL(selinux_secmark_relabel_packet_permission);
92
93void selinux_secmark_refcount_inc(void)
94{
95 atomic_inc(&selinux_secmark_refcount);
96}
97EXPORT_SYMBOL_GPL(selinux_secmark_refcount_inc);
98
99void selinux_secmark_refcount_dec(void)
100{
101 atomic_dec(&selinux_secmark_refcount);
102}
103EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index bfe9a05db3a2..6156241c8770 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -51,8 +51,10 @@
51#include <net/ip.h> /* for local_port_range[] */ 51#include <net/ip.h> /* for local_port_range[] */
52#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ 52#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
53#include <net/net_namespace.h> 53#include <net/net_namespace.h>
54#include <net/netlabel.h>
54#include <asm/uaccess.h> 55#include <asm/uaccess.h>
55#include <asm/ioctls.h> 56#include <asm/ioctls.h>
57#include <asm/atomic.h>
56#include <linux/bitops.h> 58#include <linux/bitops.h>
57#include <linux/interrupt.h> 59#include <linux/interrupt.h>
58#include <linux/netdevice.h> /* for network interface checks */ 60#include <linux/netdevice.h> /* for network interface checks */
@@ -91,6 +93,9 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
91extern int selinux_compat_net; 93extern int selinux_compat_net;
92extern struct security_operations *security_ops; 94extern struct security_operations *security_ops;
93 95
96/* SECMARK reference count */
97atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
98
94#ifdef CONFIG_SECURITY_SELINUX_DEVELOP 99#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
95int selinux_enforcing = 0; 100int selinux_enforcing = 0;
96 101
@@ -157,6 +162,21 @@ getsecurity_exit:
157 return len; 162 return len;
158} 163}
159 164
165/**
166 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
167 *
168 * Description:
169 * This function checks the SECMARK reference counter to see if any SECMARK
170 * targets are currently configured, if the reference counter is greater than
171 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
172 * enabled, false (0) if SECMARK is disabled.
173 *
174 */
175static int selinux_secmark_enabled(void)
176{
177 return (atomic_read(&selinux_secmark_refcount) > 0);
178}
179
160/* Allocate and free functions for each kind of security blob. */ 180/* Allocate and free functions for each kind of security blob. */
161 181
162static int task_alloc_security(struct task_struct *task) 182static int task_alloc_security(struct task_struct *task)
@@ -3931,7 +3951,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3931 struct sk_security_struct *sksec = sk->sk_security; 3951 struct sk_security_struct *sksec = sk->sk_security;
3932 u16 family = sk->sk_family; 3952 u16 family = sk->sk_family;
3933 u32 sk_sid = sksec->sid; 3953 u32 sk_sid = sksec->sid;
3934 u32 peer_sid;
3935 struct avc_audit_data ad; 3954 struct avc_audit_data ad;
3936 char *addrp; 3955 char *addrp;
3937 3956
@@ -3957,15 +3976,24 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3957 return selinux_sock_rcv_skb_compat(sk, skb, &ad, 3976 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
3958 family, addrp); 3977 family, addrp);
3959 3978
3960 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 3979 if (selinux_secmark_enabled()) {
3961 PACKET__RECV, &ad); 3980 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3962 if (err) 3981 PACKET__RECV, &ad);
3963 return err; 3982 if (err)
3983 return err;
3984 }
3964 3985
3965 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); 3986 if (netlbl_enabled() || selinux_xfrm_enabled()) {
3966 if (err) 3987 u32 peer_sid;
3967 return err; 3988
3968 return avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); 3989 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
3990 if (err)
3991 return err;
3992 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
3993 PEER__RECV, &ad);
3994 }
3995
3996 return err;
3969} 3997}
3970 3998
3971static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval, 3999static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 31929e39f5ca..36b0510efa7b 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -32,6 +32,13 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
32} 32}
33 33
34#ifdef CONFIG_SECURITY_NETWORK_XFRM 34#ifdef CONFIG_SECURITY_NETWORK_XFRM
35extern atomic_t selinux_xfrm_refcount;
36
37static inline int selinux_xfrm_enabled(void)
38{
39 return (atomic_read(&selinux_xfrm_refcount) > 0);
40}
41
35int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, 42int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
36 struct avc_audit_data *ad); 43 struct avc_audit_data *ad);
37int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 44int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
@@ -43,6 +50,11 @@ static inline void selinux_xfrm_notify_policyload(void)
43 atomic_inc(&flow_cache_genid); 50 atomic_inc(&flow_cache_genid);
44} 51}
45#else 52#else
53static inline int selinux_xfrm_enabled(void)
54{
55 return 0;
56}
57
46static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, 58static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
47 struct avc_audit_data *ad) 59 struct avc_audit_data *ad)
48{ 60{
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index e07603969033..7e158205d081 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -46,11 +46,14 @@
46#include <net/checksum.h> 46#include <net/checksum.h>
47#include <net/udp.h> 47#include <net/udp.h>
48#include <asm/semaphore.h> 48#include <asm/semaphore.h>
49#include <asm/atomic.h>
49 50
50#include "avc.h" 51#include "avc.h"
51#include "objsec.h" 52#include "objsec.h"
52#include "xfrm.h" 53#include "xfrm.h"
53 54
55/* Labeled XFRM instance counter */
56atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
54 57
55/* 58/*
56 * Returns true if an LSM/SELinux context 59 * Returns true if an LSM/SELinux context
@@ -293,6 +296,9 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
293 BUG_ON(!uctx); 296 BUG_ON(!uctx);
294 297
295 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0); 298 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
299 if (err == 0)
300 atomic_inc(&selinux_xfrm_refcount);
301
296 return err; 302 return err;
297} 303}
298 304
@@ -340,10 +346,13 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
340 struct xfrm_sec_ctx *ctx = xp->security; 346 struct xfrm_sec_ctx *ctx = xp->security;
341 int rc = 0; 347 int rc = 0;
342 348
343 if (ctx) 349 if (ctx) {
344 rc = avc_has_perm(tsec->sid, ctx->ctx_sid, 350 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
345 SECCLASS_ASSOCIATION, 351 SECCLASS_ASSOCIATION,
346 ASSOCIATION__SETCONTEXT, NULL); 352 ASSOCIATION__SETCONTEXT, NULL);
353 if (rc == 0)
354 atomic_dec(&selinux_xfrm_refcount);
355 }
347 356
348 return rc; 357 return rc;
349} 358}
@@ -360,6 +369,8 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
360 BUG_ON(!x); 369 BUG_ON(!x);
361 370
362 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid); 371 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
372 if (err == 0)
373 atomic_inc(&selinux_xfrm_refcount);
363 return err; 374 return err;
364} 375}
365 376
@@ -382,10 +393,13 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
382 struct xfrm_sec_ctx *ctx = x->security; 393 struct xfrm_sec_ctx *ctx = x->security;
383 int rc = 0; 394 int rc = 0;
384 395
385 if (ctx) 396 if (ctx) {
386 rc = avc_has_perm(tsec->sid, ctx->ctx_sid, 397 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
387 SECCLASS_ASSOCIATION, 398 SECCLASS_ASSOCIATION,
388 ASSOCIATION__SETCONTEXT, NULL); 399 ASSOCIATION__SETCONTEXT, NULL);
400 if (rc == 0)
401 atomic_dec(&selinux_xfrm_refcount);
402 }
389 403
390 return rc; 404 return rc;
391} 405}