diff options
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 2cf7f9f7e775..b05b9b6ddb87 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -110,6 +110,7 @@ | |||
110 | #include <linux/tcp.h> | 110 | #include <linux/tcp.h> |
111 | #include <linux/init.h> | 111 | #include <linux/init.h> |
112 | #include <linux/highmem.h> | 112 | #include <linux/highmem.h> |
113 | #include <linux/user_namespace.h> | ||
113 | 114 | ||
114 | #include <asm/uaccess.h> | 115 | #include <asm/uaccess.h> |
115 | #include <asm/system.h> | 116 | #include <asm/system.h> |
@@ -156,7 +157,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = { | |||
156 | "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , | 157 | "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , |
157 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , | 158 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , |
158 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , | 159 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , |
159 | "sk_lock-AF_IEEE802154", | 160 | "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , |
160 | "sk_lock-AF_MAX" | 161 | "sk_lock-AF_MAX" |
161 | }; | 162 | }; |
162 | static const char *const af_family_slock_key_strings[AF_MAX+1] = { | 163 | static const char *const af_family_slock_key_strings[AF_MAX+1] = { |
@@ -172,7 +173,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = { | |||
172 | "slock-27" , "slock-28" , "slock-AF_CAN" , | 173 | "slock-27" , "slock-28" , "slock-AF_CAN" , |
173 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , | 174 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , |
174 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , | 175 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , |
175 | "slock-AF_IEEE802154", | 176 | "slock-AF_IEEE802154", "slock-AF_CAIF" , |
176 | "slock-AF_MAX" | 177 | "slock-AF_MAX" |
177 | }; | 178 | }; |
178 | static const char *const af_family_clock_key_strings[AF_MAX+1] = { | 179 | static const char *const af_family_clock_key_strings[AF_MAX+1] = { |
@@ -188,7 +189,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = { | |||
188 | "clock-27" , "clock-28" , "clock-AF_CAN" , | 189 | "clock-27" , "clock-28" , "clock-AF_CAN" , |
189 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , | 190 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , |
190 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , | 191 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , |
191 | "clock-AF_IEEE802154", | 192 | "clock-AF_IEEE802154", "clock-AF_CAIF" , |
192 | "clock-AF_MAX" | 193 | "clock-AF_MAX" |
193 | }; | 194 | }; |
194 | 195 | ||
@@ -749,6 +750,20 @@ set_rcvbuf: | |||
749 | EXPORT_SYMBOL(sock_setsockopt); | 750 | EXPORT_SYMBOL(sock_setsockopt); |
750 | 751 | ||
751 | 752 | ||
753 | void cred_to_ucred(struct pid *pid, const struct cred *cred, | ||
754 | struct ucred *ucred) | ||
755 | { | ||
756 | ucred->pid = pid_vnr(pid); | ||
757 | ucred->uid = ucred->gid = -1; | ||
758 | if (cred) { | ||
759 | struct user_namespace *current_ns = current_user_ns(); | ||
760 | |||
761 | ucred->uid = user_ns_map_uid(current_ns, cred, cred->euid); | ||
762 | ucred->gid = user_ns_map_gid(current_ns, cred, cred->egid); | ||
763 | } | ||
764 | } | ||
765 | EXPORT_SYMBOL_GPL(cred_to_ucred); | ||
766 | |||
752 | int sock_getsockopt(struct socket *sock, int level, int optname, | 767 | int sock_getsockopt(struct socket *sock, int level, int optname, |
753 | char __user *optval, int __user *optlen) | 768 | char __user *optval, int __user *optlen) |
754 | { | 769 | { |
@@ -901,11 +916,15 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | |||
901 | break; | 916 | break; |
902 | 917 | ||
903 | case SO_PEERCRED: | 918 | case SO_PEERCRED: |
904 | if (len > sizeof(sk->sk_peercred)) | 919 | { |
905 | len = sizeof(sk->sk_peercred); | 920 | struct ucred peercred; |
906 | if (copy_to_user(optval, &sk->sk_peercred, len)) | 921 | if (len > sizeof(peercred)) |
922 | len = sizeof(peercred); | ||
923 | cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, &peercred); | ||
924 | if (copy_to_user(optval, &peercred, len)) | ||
907 | return -EFAULT; | 925 | return -EFAULT; |
908 | goto lenout; | 926 | goto lenout; |
927 | } | ||
909 | 928 | ||
910 | case SO_PEERNAME: | 929 | case SO_PEERNAME: |
911 | { | 930 | { |
@@ -1119,6 +1138,9 @@ static void __sk_free(struct sock *sk) | |||
1119 | printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n", | 1138 | printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n", |
1120 | __func__, atomic_read(&sk->sk_omem_alloc)); | 1139 | __func__, atomic_read(&sk->sk_omem_alloc)); |
1121 | 1140 | ||
1141 | if (sk->sk_peer_cred) | ||
1142 | put_cred(sk->sk_peer_cred); | ||
1143 | put_pid(sk->sk_peer_pid); | ||
1122 | put_net(sock_net(sk)); | 1144 | put_net(sock_net(sk)); |
1123 | sk_prot_free(sk->sk_prot_creator, sk); | 1145 | sk_prot_free(sk->sk_prot_creator, sk); |
1124 | } | 1146 | } |
@@ -1317,9 +1339,10 @@ EXPORT_SYMBOL(sock_wfree); | |||
1317 | void sock_rfree(struct sk_buff *skb) | 1339 | void sock_rfree(struct sk_buff *skb) |
1318 | { | 1340 | { |
1319 | struct sock *sk = skb->sk; | 1341 | struct sock *sk = skb->sk; |
1342 | unsigned int len = skb->truesize; | ||
1320 | 1343 | ||
1321 | atomic_sub(skb->truesize, &sk->sk_rmem_alloc); | 1344 | atomic_sub(len, &sk->sk_rmem_alloc); |
1322 | sk_mem_uncharge(skb->sk, skb->truesize); | 1345 | sk_mem_uncharge(sk, len); |
1323 | } | 1346 | } |
1324 | EXPORT_SYMBOL(sock_rfree); | 1347 | EXPORT_SYMBOL(sock_rfree); |
1325 | 1348 | ||
@@ -1954,9 +1977,8 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1954 | sk->sk_sndmsg_page = NULL; | 1977 | sk->sk_sndmsg_page = NULL; |
1955 | sk->sk_sndmsg_off = 0; | 1978 | sk->sk_sndmsg_off = 0; |
1956 | 1979 | ||
1957 | sk->sk_peercred.pid = 0; | 1980 | sk->sk_peer_pid = NULL; |
1958 | sk->sk_peercred.uid = -1; | 1981 | sk->sk_peer_cred = NULL; |
1959 | sk->sk_peercred.gid = -1; | ||
1960 | sk->sk_write_pending = 0; | 1982 | sk->sk_write_pending = 0; |
1961 | sk->sk_rcvlowat = 1; | 1983 | sk->sk_rcvlowat = 1; |
1962 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; | 1984 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; |
@@ -2210,8 +2232,7 @@ static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR); | |||
2210 | #ifdef CONFIG_NET_NS | 2232 | #ifdef CONFIG_NET_NS |
2211 | void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) | 2233 | void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) |
2212 | { | 2234 | { |
2213 | int cpu = smp_processor_id(); | 2235 | __this_cpu_add(net->core.inuse->val[prot->inuse_idx], val); |
2214 | per_cpu_ptr(net->core.inuse, cpu)->val[prot->inuse_idx] += val; | ||
2215 | } | 2236 | } |
2216 | EXPORT_SYMBOL_GPL(sock_prot_inuse_add); | 2237 | EXPORT_SYMBOL_GPL(sock_prot_inuse_add); |
2217 | 2238 | ||
@@ -2257,7 +2278,7 @@ static DEFINE_PER_CPU(struct prot_inuse, prot_inuse); | |||
2257 | 2278 | ||
2258 | void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) | 2279 | void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) |
2259 | { | 2280 | { |
2260 | __get_cpu_var(prot_inuse).val[prot->inuse_idx] += val; | 2281 | __this_cpu_add(prot_inuse.val[prot->inuse_idx], val); |
2261 | } | 2282 | } |
2262 | EXPORT_SYMBOL_GPL(sock_prot_inuse_add); | 2283 | EXPORT_SYMBOL_GPL(sock_prot_inuse_add); |
2263 | 2284 | ||