From fe33147a58e7d1d3086bf823aabfd491d843be82 Mon Sep 17 00:00:00 2001 From: Alex Lorca Date: Mon, 7 Jun 2010 01:01:22 -0700 Subject: net-caif: Added missing lock validator constants CAIF is using "xxx-AF_MAX" strings for the lock validator. It should use its own strings. Signed-off-by: Alex Lorca Signed-off-by: David S. Miller --- net/core/sock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/core/sock.c') diff --git a/net/core/sock.c b/net/core/sock.c index 2cf7f9f7e77..f9ce0db41cd 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -156,7 +156,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = { "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , - "sk_lock-AF_IEEE802154", + "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_MAX" }; static const char *const af_family_slock_key_strings[AF_MAX+1] = { @@ -172,7 +172,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = { "slock-27" , "slock-28" , "slock-AF_CAN" , "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , - "slock-AF_IEEE802154", + "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_MAX" }; static const char *const af_family_clock_key_strings[AF_MAX+1] = { @@ -188,7 +188,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = { "clock-27" , "clock-28" , "clock-AF_CAN" , "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , - "clock-AF_IEEE802154", + "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_MAX" }; -- cgit v1.2.3 From 3f551f9436c05a3b5eccdd6e94733df5bb98d2a5 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 13 Jun 2010 03:28:59 +0000 Subject: sock: Introduce cred_to_ucred To keep the coming code clear and to allow both the sock code and the scm code to share the logic introduce a fuction to translate from struct cred to struct ucred. Signed-off-by: Eric W. Biederman Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller --- include/linux/socket.h | 5 +++++ net/core/sock.c | 14 ++++++++++++++ 2 files changed, 19 insertions(+) (limited to 'net/core/sock.c') diff --git a/include/linux/socket.h b/include/linux/socket.h index 032a19eb61b..a2fada9becb 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -24,6 +24,9 @@ struct __kernel_sockaddr_storage { #include /* pid_t */ #include /* __user */ +struct pid; +struct cred; + #define __sockaddr_check_size(size) \ BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage))) @@ -309,6 +312,8 @@ struct ucred { #define IPX_TYPE 1 #ifdef __KERNEL__ +extern void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred); + extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, int offset, int len); diff --git a/net/core/sock.c b/net/core/sock.c index f9ce0db41cd..db8335ad755 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -110,6 +110,7 @@ #include #include #include +#include #include #include @@ -749,6 +750,19 @@ set_rcvbuf: EXPORT_SYMBOL(sock_setsockopt); +void cred_to_ucred(struct pid *pid, const struct cred *cred, + struct ucred *ucred) +{ + ucred->pid = pid_vnr(pid); + ucred->uid = ucred->gid = -1; + if (cred) { + struct user_namespace *current_ns = current_user_ns(); + + ucred->uid = user_ns_map_uid(current_ns, cred, cred->euid); + ucred->gid = user_ns_map_gid(current_ns, cred, cred->egid); + } +} + int sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { -- cgit v1.2.3 From 109f6e39fa07c48f580125f531f46cb7c245b528 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 13 Jun 2010 03:30:14 +0000 Subject: af_unix: Allow SO_PEERCRED to work across namespaces. Use struct pid and struct cred to store the peer credentials on struct sock. This gives enough information to convert the peer credential information to a value relative to whatever namespace the socket is in at the time. This removes nasty surprises when using SO_PEERCRED on socket connetions where the processes on either side are in different pid and user namespaces. Signed-off-by: Eric W. Biederman Acked-by: Daniel Lezcano Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller --- include/net/sock.h | 3 ++- net/core/sock.c | 18 ++++++++++++------ net/unix/af_unix.c | 37 ++++++++++++++++++++++++++++--------- 3 files changed, 42 insertions(+), 16 deletions(-) (limited to 'net/core/sock.c') diff --git a/include/net/sock.h b/include/net/sock.h index f8acf38f092..4f26f2f83be 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -295,7 +295,8 @@ struct sock { unsigned short sk_ack_backlog; unsigned short sk_max_ack_backlog; __u32 sk_priority; - struct ucred sk_peercred; + struct pid *sk_peer_pid; + const struct cred *sk_peer_cred; long sk_rcvtimeo; long sk_sndtimeo; struct sk_filter *sk_filter; diff --git a/net/core/sock.c b/net/core/sock.c index db8335ad755..0229d5566a4 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -915,11 +915,15 @@ int sock_getsockopt(struct socket *sock, int level, int optname, break; case SO_PEERCRED: - if (len > sizeof(sk->sk_peercred)) - len = sizeof(sk->sk_peercred); - if (copy_to_user(optval, &sk->sk_peercred, len)) + { + struct ucred peercred; + if (len > sizeof(peercred)) + len = sizeof(peercred); + cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, &peercred); + if (copy_to_user(optval, &peercred, len)) return -EFAULT; goto lenout; + } case SO_PEERNAME: { @@ -1133,6 +1137,9 @@ static void __sk_free(struct sock *sk) printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n", __func__, atomic_read(&sk->sk_omem_alloc)); + if (sk->sk_peer_cred) + put_cred(sk->sk_peer_cred); + put_pid(sk->sk_peer_pid); put_net(sock_net(sk)); sk_prot_free(sk->sk_prot_creator, sk); } @@ -1968,9 +1975,8 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; - sk->sk_peercred.pid = 0; - sk->sk_peercred.uid = -1; - sk->sk_peercred.gid = -1; + sk->sk_peer_pid = NULL; + sk->sk_peer_cred = NULL; sk->sk_write_pending = 0; sk->sk_rcvlowat = 1; sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index fef2cc5e9d2..e1f1349fae8 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -450,11 +450,31 @@ static int unix_release_sock(struct sock *sk, int embrion) return 0; } +static void init_peercred(struct sock *sk) +{ + put_pid(sk->sk_peer_pid); + if (sk->sk_peer_cred) + put_cred(sk->sk_peer_cred); + sk->sk_peer_pid = get_pid(task_tgid(current)); + sk->sk_peer_cred = get_current_cred(); +} + +static void copy_peercred(struct sock *sk, struct sock *peersk) +{ + put_pid(sk->sk_peer_pid); + if (sk->sk_peer_cred) + put_cred(sk->sk_peer_cred); + sk->sk_peer_pid = get_pid(peersk->sk_peer_pid); + sk->sk_peer_cred = get_cred(peersk->sk_peer_cred); +} + static int unix_listen(struct socket *sock, int backlog) { int err; struct sock *sk = sock->sk; struct unix_sock *u = unix_sk(sk); + struct pid *old_pid = NULL; + const struct cred *old_cred = NULL; err = -EOPNOTSUPP; if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) @@ -470,12 +490,14 @@ static int unix_listen(struct socket *sock, int backlog) sk->sk_max_ack_backlog = backlog; sk->sk_state = TCP_LISTEN; /* set credentials so connect can copy them */ - sk->sk_peercred.pid = task_tgid_vnr(current); - current_euid_egid(&sk->sk_peercred.uid, &sk->sk_peercred.gid); + init_peercred(sk); err = 0; out_unlock: unix_state_unlock(sk); + put_pid(old_pid); + if (old_cred) + put_cred(old_cred); out: return err; } @@ -1140,8 +1162,7 @@ restart: unix_peer(newsk) = sk; newsk->sk_state = TCP_ESTABLISHED; newsk->sk_type = sk->sk_type; - newsk->sk_peercred.pid = task_tgid_vnr(current); - current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid); + init_peercred(newsk); newu = unix_sk(newsk); newsk->sk_wq = &newu->peer_wq; otheru = unix_sk(other); @@ -1157,7 +1178,7 @@ restart: } /* Set credentials */ - sk->sk_peercred = other->sk_peercred; + copy_peercred(sk, other); sock->state = SS_CONNECTED; sk->sk_state = TCP_ESTABLISHED; @@ -1199,10 +1220,8 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb) sock_hold(skb); unix_peer(ska) = skb; unix_peer(skb) = ska; - ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current); - current_euid_egid(&skb->sk_peercred.uid, &skb->sk_peercred.gid); - ska->sk_peercred.uid = skb->sk_peercred.uid; - ska->sk_peercred.gid = skb->sk_peercred.gid; + init_peercred(ska); + init_peercred(skb); if (ska->sk_type != SOCK_DGRAM) { ska->sk_state = TCP_ESTABLISHED; -- cgit v1.2.3 From 3924773a5a82622167524bdd48799dc0452c57f8 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 16 Jun 2010 16:18:25 -0700 Subject: net: Export cred_to_ucred to modules. AF_UNIX references this, and can be built as a module, so... Signed-off-by: David S. Miller --- net/core/sock.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/core/sock.c') diff --git a/net/core/sock.c b/net/core/sock.c index 0229d5566a4..fef2434b7c8 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -762,6 +762,7 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred, ucred->gid = user_ns_map_gid(current_ns, cred, cred->egid); } } +EXPORT_SYMBOL_GPL(cred_to_ucred); int sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) -- cgit v1.2.3 From d361fd599a991ff6c1d522a599c635b35d61ef30 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 10 Jul 2010 22:45:17 +0000 Subject: net: sock_free() optimizations Avoid two extra instructions in sock_free(), to reload skb->truesize and skb->sk Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/sock.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net/core/sock.c') diff --git a/net/core/sock.c b/net/core/sock.c index fef2434b7c8..363bc260157 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1339,9 +1339,10 @@ EXPORT_SYMBOL(sock_wfree); void sock_rfree(struct sk_buff *skb) { struct sock *sk = skb->sk; + unsigned int len = skb->truesize; - atomic_sub(skb->truesize, &sk->sk_rmem_alloc); - sk_mem_uncharge(skb->sk, skb->truesize); + atomic_sub(len, &sk->sk_rmem_alloc); + sk_mem_uncharge(sk, len); } EXPORT_SYMBOL(sock_rfree); -- cgit v1.2.3 From d6d9ca0fec6aea0f2e4064474a1c5cdbed873c63 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 19 Jul 2010 10:48:49 +0000 Subject: net: this_cpu_xxx conversions Use modern this_cpu_xxx() api, saving few bytes on x86 Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/sock.c | 5 ++--- net/sched/sch_generic.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'net/core/sock.c') diff --git a/net/core/sock.c b/net/core/sock.c index 363bc260157..b05b9b6ddb8 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2232,8 +2232,7 @@ static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR); #ifdef CONFIG_NET_NS void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) { - int cpu = smp_processor_id(); - per_cpu_ptr(net->core.inuse, cpu)->val[prot->inuse_idx] += val; + __this_cpu_add(net->core.inuse->val[prot->inuse_idx], val); } EXPORT_SYMBOL_GPL(sock_prot_inuse_add); @@ -2279,7 +2278,7 @@ static DEFINE_PER_CPU(struct prot_inuse, prot_inuse); void sock_prot_inuse_add(struct net *net, struct proto *prot, int val) { - __get_cpu_var(prot_inuse).val[prot->inuse_idx] += val; + __this_cpu_add(prot_inuse.val[prot->inuse_idx], val); } EXPORT_SYMBOL_GPL(sock_prot_inuse_add); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index d20fcd2a551..2aeb3a4386a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -96,7 +96,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, * Another cpu is holding lock, requeue & delay xmits for * some time. */ - __get_cpu_var(softnet_data).cpu_collision++; + __this_cpu_inc(softnet_data.cpu_collision); ret = dev_requeue_skb(skb, q); } -- cgit v1.2.3