diff options
-rw-r--r-- | drivers/net/tun.c | 22 | ||||
-rw-r--r-- | include/linux/security.h | 31 | ||||
-rw-r--r-- | security/capability.c | 19 | ||||
-rw-r--r-- | security/security.c | 18 |
4 files changed, 83 insertions, 7 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 42b6c6319bc2..87214a257d2a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -130,17 +130,10 @@ static inline struct tun_sock *tun_sk(struct sock *sk) | |||
130 | static int tun_attach(struct tun_struct *tun, struct file *file) | 130 | static int tun_attach(struct tun_struct *tun, struct file *file) |
131 | { | 131 | { |
132 | struct tun_file *tfile = file->private_data; | 132 | struct tun_file *tfile = file->private_data; |
133 | const struct cred *cred = current_cred(); | ||
134 | int err; | 133 | int err; |
135 | 134 | ||
136 | ASSERT_RTNL(); | 135 | ASSERT_RTNL(); |
137 | 136 | ||
138 | /* Check permissions */ | ||
139 | if (((tun->owner != -1 && cred->euid != tun->owner) || | ||
140 | (tun->group != -1 && !in_egroup_p(tun->group))) && | ||
141 | !capable(CAP_NET_ADMIN)) | ||
142 | return -EPERM; | ||
143 | |||
144 | netif_tx_lock_bh(tun->dev); | 137 | netif_tx_lock_bh(tun->dev); |
145 | 138 | ||
146 | err = -EINVAL; | 139 | err = -EINVAL; |
@@ -926,6 +919,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
926 | 919 | ||
927 | dev = __dev_get_by_name(net, ifr->ifr_name); | 920 | dev = __dev_get_by_name(net, ifr->ifr_name); |
928 | if (dev) { | 921 | if (dev) { |
922 | const struct cred *cred = current_cred(); | ||
923 | |||
929 | if (ifr->ifr_flags & IFF_TUN_EXCL) | 924 | if (ifr->ifr_flags & IFF_TUN_EXCL) |
930 | return -EBUSY; | 925 | return -EBUSY; |
931 | if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) | 926 | if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) |
@@ -935,6 +930,14 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
935 | else | 930 | else |
936 | return -EINVAL; | 931 | return -EINVAL; |
937 | 932 | ||
933 | if (((tun->owner != -1 && cred->euid != tun->owner) || | ||
934 | (tun->group != -1 && !in_egroup_p(tun->group))) && | ||
935 | !capable(CAP_NET_ADMIN)) | ||
936 | return -EPERM; | ||
937 | err = security_tun_dev_attach(tun->sk); | ||
938 | if (err < 0) | ||
939 | return err; | ||
940 | |||
938 | err = tun_attach(tun, file); | 941 | err = tun_attach(tun, file); |
939 | if (err < 0) | 942 | if (err < 0) |
940 | return err; | 943 | return err; |
@@ -947,6 +950,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
947 | 950 | ||
948 | if (!capable(CAP_NET_ADMIN)) | 951 | if (!capable(CAP_NET_ADMIN)) |
949 | return -EPERM; | 952 | return -EPERM; |
953 | err = security_tun_dev_create(); | ||
954 | if (err < 0) | ||
955 | return err; | ||
950 | 956 | ||
951 | /* Set dev type */ | 957 | /* Set dev type */ |
952 | if (ifr->ifr_flags & IFF_TUN) { | 958 | if (ifr->ifr_flags & IFF_TUN) { |
@@ -989,6 +995,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
989 | tun->sk = sk; | 995 | tun->sk = sk; |
990 | container_of(sk, struct tun_sock, sk)->tun = tun; | 996 | container_of(sk, struct tun_sock, sk)->tun = tun; |
991 | 997 | ||
998 | security_tun_dev_post_create(sk); | ||
999 | |||
992 | tun_net_init(dev); | 1000 | tun_net_init(dev); |
993 | 1001 | ||
994 | if (strchr(dev->name, '%')) { | 1002 | if (strchr(dev->name, '%')) { |
diff --git a/include/linux/security.h b/include/linux/security.h index a16d6b7c4ebe..40ba39ea68ce 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -998,6 +998,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
998 | * Sets the connection's peersid to the secmark on skb. | 998 | * Sets the connection's peersid to the secmark on skb. |
999 | * @req_classify_flow: | 999 | * @req_classify_flow: |
1000 | * Sets the flow's sid to the openreq sid. | 1000 | * Sets the flow's sid to the openreq sid. |
1001 | * @tun_dev_create: | ||
1002 | * Check permissions prior to creating a new TUN device. | ||
1003 | * @tun_dev_post_create: | ||
1004 | * This hook allows a module to update or allocate a per-socket security | ||
1005 | * structure. | ||
1006 | * @sk contains the newly created sock structure. | ||
1007 | * @tun_dev_attach: | ||
1008 | * Check permissions prior to attaching to a persistent TUN device. This | ||
1009 | * hook can also be used by the module to update any security state | ||
1010 | * associated with the TUN device's sock structure. | ||
1011 | * @sk contains the existing sock structure. | ||
1001 | * | 1012 | * |
1002 | * Security hooks for XFRM operations. | 1013 | * Security hooks for XFRM operations. |
1003 | * | 1014 | * |
@@ -1597,6 +1608,9 @@ struct security_operations { | |||
1597 | void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req); | 1608 | void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req); |
1598 | void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb); | 1609 | void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb); |
1599 | void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl); | 1610 | void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl); |
1611 | int (*tun_dev_create)(void); | ||
1612 | void (*tun_dev_post_create)(struct sock *sk); | ||
1613 | int (*tun_dev_attach)(struct sock *sk); | ||
1600 | #endif /* CONFIG_SECURITY_NETWORK */ | 1614 | #endif /* CONFIG_SECURITY_NETWORK */ |
1601 | 1615 | ||
1602 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1616 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
@@ -2586,6 +2600,9 @@ void security_inet_csk_clone(struct sock *newsk, | |||
2586 | const struct request_sock *req); | 2600 | const struct request_sock *req); |
2587 | void security_inet_conn_established(struct sock *sk, | 2601 | void security_inet_conn_established(struct sock *sk, |
2588 | struct sk_buff *skb); | 2602 | struct sk_buff *skb); |
2603 | int security_tun_dev_create(void); | ||
2604 | void security_tun_dev_post_create(struct sock *sk); | ||
2605 | int security_tun_dev_attach(struct sock *sk); | ||
2589 | 2606 | ||
2590 | #else /* CONFIG_SECURITY_NETWORK */ | 2607 | #else /* CONFIG_SECURITY_NETWORK */ |
2591 | static inline int security_unix_stream_connect(struct socket *sock, | 2608 | static inline int security_unix_stream_connect(struct socket *sock, |
@@ -2736,6 +2753,20 @@ static inline void security_inet_conn_established(struct sock *sk, | |||
2736 | struct sk_buff *skb) | 2753 | struct sk_buff *skb) |
2737 | { | 2754 | { |
2738 | } | 2755 | } |
2756 | |||
2757 | static inline int security_tun_dev_create(void) | ||
2758 | { | ||
2759 | return 0; | ||
2760 | } | ||
2761 | |||
2762 | static inline void security_tun_dev_post_create(struct sock *sk) | ||
2763 | { | ||
2764 | } | ||
2765 | |||
2766 | static inline int security_tun_dev_attach(struct sock *sk) | ||
2767 | { | ||
2768 | return 0; | ||
2769 | } | ||
2739 | #endif /* CONFIG_SECURITY_NETWORK */ | 2770 | #endif /* CONFIG_SECURITY_NETWORK */ |
2740 | 2771 | ||
2741 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 2772 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
diff --git a/security/capability.c b/security/capability.c index 1b943f54b2ea..06400cf07757 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -706,10 +706,26 @@ static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb) | |||
706 | { | 706 | { |
707 | } | 707 | } |
708 | 708 | ||
709 | |||
710 | |||
709 | static void cap_req_classify_flow(const struct request_sock *req, | 711 | static void cap_req_classify_flow(const struct request_sock *req, |
710 | struct flowi *fl) | 712 | struct flowi *fl) |
711 | { | 713 | { |
712 | } | 714 | } |
715 | |||
716 | static int cap_tun_dev_create(void) | ||
717 | { | ||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | static void cap_tun_dev_post_create(struct sock *sk) | ||
722 | { | ||
723 | } | ||
724 | |||
725 | static int cap_tun_dev_attach(struct sock *sk) | ||
726 | { | ||
727 | return 0; | ||
728 | } | ||
713 | #endif /* CONFIG_SECURITY_NETWORK */ | 729 | #endif /* CONFIG_SECURITY_NETWORK */ |
714 | 730 | ||
715 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 731 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
@@ -1026,6 +1042,9 @@ void security_fixup_ops(struct security_operations *ops) | |||
1026 | set_to_cap_if_null(ops, inet_csk_clone); | 1042 | set_to_cap_if_null(ops, inet_csk_clone); |
1027 | set_to_cap_if_null(ops, inet_conn_established); | 1043 | set_to_cap_if_null(ops, inet_conn_established); |
1028 | set_to_cap_if_null(ops, req_classify_flow); | 1044 | set_to_cap_if_null(ops, req_classify_flow); |
1045 | set_to_cap_if_null(ops, tun_dev_create); | ||
1046 | set_to_cap_if_null(ops, tun_dev_post_create); | ||
1047 | set_to_cap_if_null(ops, tun_dev_attach); | ||
1029 | #endif /* CONFIG_SECURITY_NETWORK */ | 1048 | #endif /* CONFIG_SECURITY_NETWORK */ |
1030 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1049 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
1031 | set_to_cap_if_null(ops, xfrm_policy_alloc_security); | 1050 | set_to_cap_if_null(ops, xfrm_policy_alloc_security); |
diff --git a/security/security.c b/security/security.c index 0e993f42ce3d..f88eaf6b14cc 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -1117,6 +1117,24 @@ void security_inet_conn_established(struct sock *sk, | |||
1117 | security_ops->inet_conn_established(sk, skb); | 1117 | security_ops->inet_conn_established(sk, skb); |
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | int security_tun_dev_create(void) | ||
1121 | { | ||
1122 | return security_ops->tun_dev_create(); | ||
1123 | } | ||
1124 | EXPORT_SYMBOL(security_tun_dev_create); | ||
1125 | |||
1126 | void security_tun_dev_post_create(struct sock *sk) | ||
1127 | { | ||
1128 | return security_ops->tun_dev_post_create(sk); | ||
1129 | } | ||
1130 | EXPORT_SYMBOL(security_tun_dev_post_create); | ||
1131 | |||
1132 | int security_tun_dev_attach(struct sock *sk) | ||
1133 | { | ||
1134 | return security_ops->tun_dev_attach(sk); | ||
1135 | } | ||
1136 | EXPORT_SYMBOL(security_tun_dev_attach); | ||
1137 | |||
1120 | #endif /* CONFIG_SECURITY_NETWORK */ | 1138 | #endif /* CONFIG_SECURITY_NETWORK */ |
1121 | 1139 | ||
1122 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1140 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |