Commit 2606fd1fa5710205b23ee859563502aa18362447

Authored by Eric Paris
Committed by James Morris
1 parent 15714f7b58

secmark: make secmark object handling generic

Right now secmark has lots of direct selinux calls.  Use all LSM calls and
remove all SELinux specific knowledge.  The only SELinux specific knowledge
we leave is the mode.  The only point is to make sure that other LSMs at
least test this generic code before they assume it works.  (They may also
have to make changes if they do not represent labels as strings)

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Paul Moore <paul.moore@hp.com>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 10 changed files with 104 additions and 141 deletions Side-by-side Diff

include/linux/netfilter/xt_SECMARK.h
... ... @@ -11,18 +11,12 @@
11 11 * packets are being marked for.
12 12 */
13 13 #define SECMARK_MODE_SEL 0x01 /* SELinux */
14   -#define SECMARK_SELCTX_MAX 256
  14 +#define SECMARK_SECCTX_MAX 256
15 15  
16   -struct xt_secmark_target_selinux_info {
17   - __u32 selsid;
18   - char selctx[SECMARK_SELCTX_MAX];
19   -};
20   -
21 16 struct xt_secmark_target_info {
22 17 __u8 mode;
23   - union {
24   - struct xt_secmark_target_selinux_info sel;
25   - } u;
  18 + __u32 secid;
  19 + char secctx[SECMARK_SECCTX_MAX];
26 20 };
27 21  
28 22 #endif /*_XT_SECMARK_H_target */
include/linux/security.h
... ... @@ -959,6 +959,12 @@
959 959 * Sets the new child socket's sid to the openreq sid.
960 960 * @inet_conn_established:
961 961 * Sets the connection's peersid to the secmark on skb.
  962 + * @secmark_relabel_packet:
  963 + * check if the process should be allowed to relabel packets to the given secid
  964 + * @security_secmark_refcount_inc
  965 + * tells the LSM to increment the number of secmark labeling rules loaded
  966 + * @security_secmark_refcount_dec
  967 + * tells the LSM to decrement the number of secmark labeling rules loaded
962 968 * @req_classify_flow:
963 969 * Sets the flow's sid to the openreq sid.
964 970 * @tun_dev_create:
... ... @@ -1593,6 +1599,9 @@
1593 1599 struct request_sock *req);
1594 1600 void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
1595 1601 void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
  1602 + int (*secmark_relabel_packet) (u32 secid);
  1603 + void (*secmark_refcount_inc) (void);
  1604 + void (*secmark_refcount_dec) (void);
1596 1605 void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
1597 1606 int (*tun_dev_create)(void);
1598 1607 void (*tun_dev_post_create)(struct sock *sk);
... ... @@ -2547,6 +2556,9 @@
2547 2556 const struct request_sock *req);
2548 2557 void security_inet_conn_established(struct sock *sk,
2549 2558 struct sk_buff *skb);
  2559 +int security_secmark_relabel_packet(u32 secid);
  2560 +void security_secmark_refcount_inc(void);
  2561 +void security_secmark_refcount_dec(void);
2550 2562 int security_tun_dev_create(void);
2551 2563 void security_tun_dev_post_create(struct sock *sk);
2552 2564 int security_tun_dev_attach(struct sock *sk);
... ... @@ -2698,6 +2710,19 @@
2698 2710  
2699 2711 static inline void security_inet_conn_established(struct sock *sk,
2700 2712 struct sk_buff *skb)
  2713 +{
  2714 +}
  2715 +
  2716 +static inline int security_secmark_relabel_packet(u32 secid)
  2717 +{
  2718 + return 0;
  2719 +}
  2720 +
  2721 +static inline void security_secmark_refcount_inc(void)
  2722 +{
  2723 +}
  2724 +
  2725 +static inline void security_secmark_refcount_dec(void)
2701 2726 {
2702 2727 }
2703 2728  
include/linux/selinux.h
... ... @@ -21,73 +21,10 @@
21 21 #ifdef CONFIG_SECURITY_SELINUX
22 22  
23 23 /**
24   - * selinux_string_to_sid - map a security context string to a security ID
25   - * @str: the security context string to be mapped
26   - * @sid: ID value returned via this.
27   - *
28   - * Returns 0 if successful, with the SID stored in sid. A value
29   - * of zero for sid indicates no SID could be determined (but no error
30   - * occurred).
31   - */
32   -int selinux_string_to_sid(char *str, u32 *sid);
33   -
34   -/**
35   - * selinux_secmark_relabel_packet_permission - secmark permission check
36   - * @sid: SECMARK ID value to be applied to network packet
37   - *
38   - * Returns 0 if the current task is allowed to set the SECMARK label of
39   - * packets with the supplied security ID. Note that it is implicit that
40   - * the packet is always being relabeled from the default unlabeled value,
41   - * and that the access control decision is made in the AVC.
42   - */
43   -int selinux_secmark_relabel_packet_permission(u32 sid);
44   -
45   -/**
46   - * selinux_secmark_refcount_inc - increments the secmark use counter
47   - *
48   - * SELinux keeps track of the current SECMARK targets in use so it knows
49   - * when to apply SECMARK label access checks to network packets. This
50   - * function incements this reference count to indicate that a new SECMARK
51   - * target has been configured.
52   - */
53   -void selinux_secmark_refcount_inc(void);
54   -
55   -/**
56   - * selinux_secmark_refcount_dec - decrements the secmark use counter
57   - *
58   - * SELinux keeps track of the current SECMARK targets in use so it knows
59   - * when to apply SECMARK label access checks to network packets. This
60   - * function decements this reference count to indicate that one of the
61   - * existing SECMARK targets has been removed/flushed.
62   - */
63   -void selinux_secmark_refcount_dec(void);
64   -
65   -/**
66 24 * selinux_is_enabled - is SELinux enabled?
67 25 */
68 26 bool selinux_is_enabled(void);
69 27 #else
70   -
71   -static inline int selinux_string_to_sid(const char *str, u32 *sid)
72   -{
73   - *sid = 0;
74   - return 0;
75   -}
76   -
77   -static inline int selinux_secmark_relabel_packet_permission(u32 sid)
78   -{
79   - return 0;
80   -}
81   -
82   -static inline void selinux_secmark_refcount_inc(void)
83   -{
84   - return;
85   -}
86   -
87   -static inline void selinux_secmark_refcount_dec(void)
88   -{
89   - return;
90   -}
91 28  
92 29 static inline bool selinux_is_enabled(void)
93 30 {
net/netfilter/xt_CT.c
... ... @@ -9,7 +9,6 @@
9 9 #include <linux/module.h>
10 10 #include <linux/gfp.h>
11 11 #include <linux/skbuff.h>
12   -#include <linux/selinux.h>
13 12 #include <linux/netfilter_ipv4/ip_tables.h>
14 13 #include <linux/netfilter_ipv6/ip6_tables.h>
15 14 #include <linux/netfilter/x_tables.h>
net/netfilter/xt_SECMARK.c
... ... @@ -14,8 +14,8 @@
14 14 */
15 15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16 16 #include <linux/module.h>
  17 +#include <linux/security.h>
17 18 #include <linux/skbuff.h>
18   -#include <linux/selinux.h>
19 19 #include <linux/netfilter/x_tables.h>
20 20 #include <linux/netfilter/xt_SECMARK.h>
21 21  
22 22  
... ... @@ -39,9 +39,8 @@
39 39  
40 40 switch (mode) {
41 41 case SECMARK_MODE_SEL:
42   - secmark = info->u.sel.selsid;
  42 + secmark = info->secid;
43 43 break;
44   -
45 44 default:
46 45 BUG();
47 46 }
48 47  
49 48  
50 49  
51 50  
52 51  
53 52  
54 53  
... ... @@ -50,33 +49,33 @@
50 49 return XT_CONTINUE;
51 50 }
52 51  
53   -static int checkentry_selinux(struct xt_secmark_target_info *info)
  52 +static int checkentry_lsm(struct xt_secmark_target_info *info)
54 53 {
55 54 int err;
56   - struct xt_secmark_target_selinux_info *sel = &info->u.sel;
57 55  
58   - sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0';
  56 + info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
  57 + info->secid = 0;
59 58  
60   - err = selinux_string_to_sid(sel->selctx, &sel->selsid);
  59 + err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
  60 + &info->secid);
61 61 if (err) {
62 62 if (err == -EINVAL)
63   - pr_info("invalid SELinux context \'%s\'\n",
64   - sel->selctx);
  63 + pr_info("invalid security context \'%s\'\n", info->secctx);
65 64 return err;
66 65 }
67 66  
68   - if (!sel->selsid) {
69   - pr_info("unable to map SELinux context \'%s\'\n", sel->selctx);
  67 + if (!info->secid) {
  68 + pr_info("unable to map security context \'%s\'\n", info->secctx);
70 69 return -ENOENT;
71 70 }
72 71  
73   - err = selinux_secmark_relabel_packet_permission(sel->selsid);
  72 + err = security_secmark_relabel_packet(info->secid);
74 73 if (err) {
75 74 pr_info("unable to obtain relabeling permission\n");
76 75 return err;
77 76 }
78 77  
79   - selinux_secmark_refcount_inc();
  78 + security_secmark_refcount_inc();
80 79 return 0;
81 80 }
82 81  
83 82  
84 83  
... ... @@ -100,16 +99,16 @@
100 99  
101 100 switch (info->mode) {
102 101 case SECMARK_MODE_SEL:
103   - err = checkentry_selinux(info);
104   - if (err)
105   - return err;
106 102 break;
107   -
108 103 default:
109 104 pr_info("invalid mode: %hu\n", info->mode);
110 105 return -EINVAL;
111 106 }
112 107  
  108 + err = checkentry_lsm(info);
  109 + if (err)
  110 + return err;
  111 +
113 112 if (!mode)
114 113 mode = info->mode;
115 114 return 0;
... ... @@ -119,7 +118,7 @@
119 118 {
120 119 switch (mode) {
121 120 case SECMARK_MODE_SEL:
122   - selinux_secmark_refcount_dec();
  121 + security_secmark_refcount_dec();
123 122 }
124 123 }
125 124  
security/capability.c
... ... @@ -677,8 +677,19 @@
677 677 {
678 678 }
679 679  
  680 +static int cap_secmark_relabel_packet(u32 secid)
  681 +{
  682 + return 0;
  683 +}
680 684  
  685 +static void cap_secmark_refcount_inc(void)
  686 +{
  687 +}
681 688  
  689 +static void cap_secmark_refcount_dec(void)
  690 +{
  691 +}
  692 +
682 693 static void cap_req_classify_flow(const struct request_sock *req,
683 694 struct flowi *fl)
684 695 {
... ... @@ -777,7 +788,8 @@
777 788  
778 789 static int cap_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
779 790 {
780   - return -EOPNOTSUPP;
  791 + *secid = 0;
  792 + return 0;
781 793 }
782 794  
783 795 static void cap_release_secctx(char *secdata, u32 seclen)
... ... @@ -1018,6 +1030,9 @@
1018 1030 set_to_cap_if_null(ops, inet_conn_request);
1019 1031 set_to_cap_if_null(ops, inet_csk_clone);
1020 1032 set_to_cap_if_null(ops, inet_conn_established);
  1033 + set_to_cap_if_null(ops, secmark_relabel_packet);
  1034 + set_to_cap_if_null(ops, secmark_refcount_inc);
  1035 + set_to_cap_if_null(ops, secmark_refcount_dec);
1021 1036 set_to_cap_if_null(ops, req_classify_flow);
1022 1037 set_to_cap_if_null(ops, tun_dev_create);
1023 1038 set_to_cap_if_null(ops, tun_dev_post_create);
... ... @@ -1136,6 +1136,24 @@
1136 1136 security_ops->inet_conn_established(sk, skb);
1137 1137 }
1138 1138  
  1139 +int security_secmark_relabel_packet(u32 secid)
  1140 +{
  1141 + return security_ops->secmark_relabel_packet(secid);
  1142 +}
  1143 +EXPORT_SYMBOL(security_secmark_relabel_packet);
  1144 +
  1145 +void security_secmark_refcount_inc(void)
  1146 +{
  1147 + security_ops->secmark_refcount_inc();
  1148 +}
  1149 +EXPORT_SYMBOL(security_secmark_refcount_inc);
  1150 +
  1151 +void security_secmark_refcount_dec(void)
  1152 +{
  1153 + security_ops->secmark_refcount_dec();
  1154 +}
  1155 +EXPORT_SYMBOL(security_secmark_refcount_dec);
  1156 +
1139 1157 int security_tun_dev_create(void)
1140 1158 {
1141 1159 return security_ops->tun_dev_create();
security/selinux/exports.c
... ... @@ -11,58 +11,9 @@
11 11 * it under the terms of the GNU General Public License version 2,
12 12 * as published by the Free Software Foundation.
13 13 */
14   -#include <linux/types.h>
15   -#include <linux/kernel.h>
16 14 #include <linux/module.h>
17   -#include <linux/selinux.h>
18   -#include <linux/fs.h>
19   -#include <linux/ipc.h>
20   -#include <asm/atomic.h>
21 15  
22 16 #include "security.h"
23   -#include "objsec.h"
24   -
25   -/* SECMARK reference count */
26   -extern atomic_t selinux_secmark_refcount;
27   -
28   -int selinux_string_to_sid(char *str, u32 *sid)
29   -{
30   - if (selinux_enabled)
31   - return security_context_to_sid(str, strlen(str), sid);
32   - else {
33   - *sid = 0;
34   - return 0;
35   - }
36   -}
37   -EXPORT_SYMBOL_GPL(selinux_string_to_sid);
38   -
39   -int selinux_secmark_relabel_packet_permission(u32 sid)
40   -{
41   - if (selinux_enabled) {
42   - const struct task_security_struct *__tsec;
43   - u32 tsid;
44   -
45   - __tsec = current_security();
46   - tsid = __tsec->sid;
47   -
48   - return avc_has_perm(tsid, sid, SECCLASS_PACKET,
49   - PACKET__RELABELTO, NULL);
50   - }
51   - return 0;
52   -}
53   -EXPORT_SYMBOL_GPL(selinux_secmark_relabel_packet_permission);
54   -
55   -void selinux_secmark_refcount_inc(void)
56   -{
57   - atomic_inc(&selinux_secmark_refcount);
58   -}
59   -EXPORT_SYMBOL_GPL(selinux_secmark_refcount_inc);
60   -
61   -void selinux_secmark_refcount_dec(void)
62   -{
63   - atomic_dec(&selinux_secmark_refcount);
64   -}
65   -EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec);
66 17  
67 18 bool selinux_is_enabled(void)
68 19 {
security/selinux/hooks.c
... ... @@ -4279,6 +4279,27 @@
4279 4279 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
4280 4280 }
4281 4281  
  4282 +static int selinux_secmark_relabel_packet(u32 sid)
  4283 +{
  4284 + const struct task_security_struct *__tsec;
  4285 + u32 tsid;
  4286 +
  4287 + __tsec = current_security();
  4288 + tsid = __tsec->sid;
  4289 +
  4290 + return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
  4291 +}
  4292 +
  4293 +static void selinux_secmark_refcount_inc(void)
  4294 +{
  4295 + atomic_inc(&selinux_secmark_refcount);
  4296 +}
  4297 +
  4298 +static void selinux_secmark_refcount_dec(void)
  4299 +{
  4300 + atomic_dec(&selinux_secmark_refcount);
  4301 +}
  4302 +
4282 4303 static void selinux_req_classify_flow(const struct request_sock *req,
4283 4304 struct flowi *fl)
4284 4305 {
... ... @@ -5533,6 +5554,9 @@
5533 5554 .inet_conn_request = selinux_inet_conn_request,
5534 5555 .inet_csk_clone = selinux_inet_csk_clone,
5535 5556 .inet_conn_established = selinux_inet_conn_established,
  5557 + .secmark_relabel_packet = selinux_secmark_relabel_packet,
  5558 + .secmark_refcount_inc = selinux_secmark_refcount_inc,
  5559 + .secmark_refcount_dec = selinux_secmark_refcount_dec,
5536 5560 .req_classify_flow = selinux_req_classify_flow,
5537 5561 .tun_dev_create = selinux_tun_dev_create,
5538 5562 .tun_dev_post_create = selinux_tun_dev_post_create,
security/selinux/include/security.h
... ... @@ -9,6 +9,7 @@
9 9 #define _SELINUX_SECURITY_H_
10 10  
11 11 #include <linux/magic.h>
  12 +#include <linux/types.h>
12 13 #include "flask.h"
13 14  
14 15 #define SECSID_NULL 0x00000000 /* unspecified SID */