All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] Support unix domain sockets across namespaces
@ 2010-06-13 13:25 ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:25 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


This patchset takes a addressing all of the issues that crop up with
unix domain sockets when the senders and receivers are in separate
namespaces.

Without this patchset we can report the wrong pid and uid
values in our unix domain credentials.

As a finally this patchset removes the now unnecessary restriction
that we only allow unix domain sockets between processes in the
same network namespace.

Eric W. Biederman (8):
      scm: Reorder scm_cookie.
      user_ns: Introduce user_nsmap_uid and user_ns_map_gid.
      sock: Introduce cred_to_ucred
      af_unix: Allow SO_PEERCRED to work across namespaces.
      af_netlink: Add needed scm_destroy after scm_send.
      scm: Capture the full credentials of the scm sender.
      af_unix: Allow credentials to work across user and pid namespaces.
      af_unix: Allow connecting to sockets in other network namespaces.

---
 include/linux/socket.h         |    5 ++
 include/linux/user_namespace.h |   14 ++++++
 include/net/af_unix.h          |    4 +-
 include/net/scm.h              |   30 ++++++++++--
 include/net/sock.h             |    3 +-
 kernel/user_namespace.c        |   44 ++++++++++++++++++
 net/core/scm.c                 |   24 ++++++++++
 net/core/sock.c                |   32 +++++++++++---
 net/netlink/af_netlink.c       |   11 +++-
 net/unix/af_unix.c             |   97 +++++++++++++++++++++++++---------------
 10 files changed, 211 insertions(+), 53 deletions(-)

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 0/8] Support unix domain sockets across namespaces
@ 2010-06-13 13:25 ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:25 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


This patchset takes a addressing all of the issues that crop up with
unix domain sockets when the senders and receivers are in separate
namespaces.

Without this patchset we can report the wrong pid and uid
values in our unix domain credentials.

As a finally this patchset removes the now unnecessary restriction
that we only allow unix domain sockets between processes in the
same network namespace.

Eric W. Biederman (8):
      scm: Reorder scm_cookie.
      user_ns: Introduce user_nsmap_uid and user_ns_map_gid.
      sock: Introduce cred_to_ucred
      af_unix: Allow SO_PEERCRED to work across namespaces.
      af_netlink: Add needed scm_destroy after scm_send.
      scm: Capture the full credentials of the scm sender.
      af_unix: Allow credentials to work across user and pid namespaces.
      af_unix: Allow connecting to sockets in other network namespaces.

---
 include/linux/socket.h         |    5 ++
 include/linux/user_namespace.h |   14 ++++++
 include/net/af_unix.h          |    4 +-
 include/net/scm.h              |   30 ++++++++++--
 include/net/sock.h             |    3 +-
 kernel/user_namespace.c        |   44 ++++++++++++++++++
 net/core/scm.c                 |   24 ++++++++++
 net/core/sock.c                |   32 +++++++++++---
 net/netlink/af_netlink.c       |   11 +++-
 net/unix/af_unix.c             |   97 +++++++++++++++++++++++++---------------
 10 files changed, 211 insertions(+), 53 deletions(-)

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 1/8] scm: Reorder scm_cookie.
  2010-06-13 13:25 ` Eric W. Biederman
@ 2010-06-13 13:27   ` Eric W. Biederman
  -1 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:27 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


Reorder the fields in scm_cookie so they pack better on 64bit.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 include/net/scm.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/net/scm.h b/include/net/scm.h
index 8360e47..17d9d2e 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -19,8 +19,8 @@ struct scm_fp_list {
 };
 
 struct scm_cookie {
-	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
+	struct ucred		creds;		/* Skb credentials	*/
 #ifdef CONFIG_SECURITY_NETWORK
 	u32			secid;		/* Passed security ID 	*/
 #endif
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 1/8] scm: Reorder scm_cookie.
@ 2010-06-13 13:27   ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:27 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


Reorder the fields in scm_cookie so they pack better on 64bit.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 include/net/scm.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/net/scm.h b/include/net/scm.h
index 8360e47..17d9d2e 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -19,8 +19,8 @@ struct scm_fp_list {
 };
 
 struct scm_cookie {
-	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
+	struct ucred		creds;		/* Skb credentials	*/
 #ifdef CONFIG_SECURITY_NETWORK
 	u32			secid;		/* Passed security ID 	*/
 #endif
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 2/8] user_ns: Introduce user_nsmap_uid and user_ns_map_gid.
  2010-06-13 13:27   ` Eric W. Biederman
@ 2010-06-13 13:28     ` Eric W. Biederman
  -1 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:28 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


Define what happens when a we view a uid from one user_namespace
in another user_namepece.

- If the user namespaces are the same no mapping is necessary.

- For most cases of difference use overflowuid and overflowgid,
  the uid and gid currently used for 16bit apis when we have a 32bit uid
  that does fit in 16bits.  Effectively the situation is the same,
  we want to return a uid or gid that is not assigned to any user.

- For the case when we happen to be mapping the uid or gid of the
  creator of the target user namespace use uid 0 and gid as confusing
  that user with root is not a problem.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 include/linux/user_namespace.h |   14 ++++++++++++
 kernel/user_namespace.c        |   44 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index cc4f453..8178156 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -36,6 +36,9 @@ static inline void put_user_ns(struct user_namespace *ns)
 		kref_put(&ns->kref, free_user_ns);
 }
 
+uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid);
+gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid);
+
 #else
 
 static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
@@ -52,6 +55,17 @@ static inline void put_user_ns(struct user_namespace *ns)
 {
 }
 
+static inline uid_t user_ns_map_uid(struct user_namespace *to,
+	const struct cred *cred, uid_t uid)
+{
+	return uid;
+}
+static inline gid_t user_ns_map_gid(struct user_namespace *to,
+	const struct cred *cred, gid_t gid)
+{
+	return gid;
+}
+
 #endif
 
 #endif /* _LINUX_USER_H */
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 076c7c8..825abfb 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -9,6 +9,7 @@
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
 #include <linux/user_namespace.h>
+#include <linux/highuid.h>
 #include <linux/cred.h>
 
 /*
@@ -82,3 +83,46 @@ void free_user_ns(struct kref *kref)
 	schedule_work(&ns->destroyer);
 }
 EXPORT_SYMBOL(free_user_ns);
+
+uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid)
+{
+	struct user_namespace *tmp;
+
+	if (likely(to == cred->user->user_ns))
+		return uid;
+
+
+	/* Is cred->user the creator of the target user_ns
+	 * or the creator of one of it's parents?
+	 */
+	for ( tmp = to; tmp != &init_user_ns;
+	      tmp = tmp->creator->user_ns ) {
+		if (cred->user == tmp->creator) {
+			return (uid_t)0;
+		}
+	}
+
+	/* No useful relationship so no mapping */
+	return overflowuid;
+}
+
+gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid)
+{
+	struct user_namespace *tmp;
+
+	if (likely(to == cred->user->user_ns))
+		return gid;
+
+	/* Is cred->user the creator of the target user_ns
+	 * or the creator of one of it's parents?
+	 */
+	for ( tmp = to; tmp != &init_user_ns;
+	      tmp = tmp->creator->user_ns ) {
+		if (cred->user == tmp->creator) {
+			return (gid_t)0;
+		}
+	}
+
+	/* No useful relationship so no mapping */
+	return overflowgid;
+}
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 2/8] user_ns: Introduce user_nsmap_uid and user_ns_map_gid.
@ 2010-06-13 13:28     ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:28 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


Define what happens when a we view a uid from one user_namespace
in another user_namepece.

- If the user namespaces are the same no mapping is necessary.

- For most cases of difference use overflowuid and overflowgid,
  the uid and gid currently used for 16bit apis when we have a 32bit uid
  that does fit in 16bits.  Effectively the situation is the same,
  we want to return a uid or gid that is not assigned to any user.

- For the case when we happen to be mapping the uid or gid of the
  creator of the target user namespace use uid 0 and gid as confusing
  that user with root is not a problem.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 include/linux/user_namespace.h |   14 ++++++++++++
 kernel/user_namespace.c        |   44 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index cc4f453..8178156 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -36,6 +36,9 @@ static inline void put_user_ns(struct user_namespace *ns)
 		kref_put(&ns->kref, free_user_ns);
 }
 
+uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid);
+gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid);
+
 #else
 
 static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
@@ -52,6 +55,17 @@ static inline void put_user_ns(struct user_namespace *ns)
 {
 }
 
+static inline uid_t user_ns_map_uid(struct user_namespace *to,
+	const struct cred *cred, uid_t uid)
+{
+	return uid;
+}
+static inline gid_t user_ns_map_gid(struct user_namespace *to,
+	const struct cred *cred, gid_t gid)
+{
+	return gid;
+}
+
 #endif
 
 #endif /* _LINUX_USER_H */
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 076c7c8..825abfb 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -9,6 +9,7 @@
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
 #include <linux/user_namespace.h>
+#include <linux/highuid.h>
 #include <linux/cred.h>
 
 /*
@@ -82,3 +83,46 @@ void free_user_ns(struct kref *kref)
 	schedule_work(&ns->destroyer);
 }
 EXPORT_SYMBOL(free_user_ns);
+
+uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid)
+{
+	struct user_namespace *tmp;
+
+	if (likely(to == cred->user->user_ns))
+		return uid;
+
+
+	/* Is cred->user the creator of the target user_ns
+	 * or the creator of one of it's parents?
+	 */
+	for ( tmp = to; tmp != &init_user_ns;
+	      tmp = tmp->creator->user_ns ) {
+		if (cred->user == tmp->creator) {
+			return (uid_t)0;
+		}
+	}
+
+	/* No useful relationship so no mapping */
+	return overflowuid;
+}
+
+gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid)
+{
+	struct user_namespace *tmp;
+
+	if (likely(to == cred->user->user_ns))
+		return gid;
+
+	/* Is cred->user the creator of the target user_ns
+	 * or the creator of one of it's parents?
+	 */
+	for ( tmp = to; tmp != &init_user_ns;
+	      tmp = tmp->creator->user_ns ) {
+		if (cred->user == tmp->creator) {
+			return (gid_t)0;
+		}
+	}
+
+	/* No useful relationship so no mapping */
+	return overflowgid;
+}
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 3/8] sock: Introduce cred_to_ucred
  2010-06-13 13:25 ` Eric W. Biederman
@ 2010-06-13 13:28   ` Eric W. Biederman
  -1 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:28 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


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 <ebiederm@xmission.com>
---
 include/linux/socket.h |    5 +++++
 net/core/sock.c        |   14 ++++++++++++++
 2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 032a19e..a2fada9 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -24,6 +24,9 @@ struct __kernel_sockaddr_storage {
 #include <linux/types.h>		/* pid_t			*/
 #include <linux/compiler.h>		/* __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 7effa1e..9e229d8 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -110,6 +110,7 @@
 #include <linux/tcp.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/user_namespace.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -734,6 +735,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)
 {
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 3/8] sock: Introduce cred_to_ucred
@ 2010-06-13 13:28   ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:28 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


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 <ebiederm@xmission.com>
---
 include/linux/socket.h |    5 +++++
 net/core/sock.c        |   14 ++++++++++++++
 2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 032a19e..a2fada9 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -24,6 +24,9 @@ struct __kernel_sockaddr_storage {
 #include <linux/types.h>		/* pid_t			*/
 #include <linux/compiler.h>		/* __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 7effa1e..9e229d8 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -110,6 +110,7 @@
 #include <linux/tcp.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/user_namespace.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -734,6 +735,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)
 {
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 4/8] af_unix: Allow SO_PEERCRED to work across namespaces.
  2010-06-13 13:25 ` Eric W. Biederman
@ 2010-06-13 13:30   ` Eric W. Biederman
  -1 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:30 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


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 <ebiederm@xmission.com>
---
 include/net/sock.h |    3 ++-
 net/core/sock.c    |   18 ++++++++++++------
 net/unix/af_unix.c |   37 ++++++++++++++++++++++++++++---------
 3 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index 56df440..5b1eb7d 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -290,7 +290,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 9e229d8..9d197a6 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -900,11 +900,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:
 	{
@@ -1105,6 +1109,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);
 }
@@ -1927,9 +1934,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 3d9122e..028fa25 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -449,11 +449,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)
@@ -469,12 +489,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;
 }
@@ -1139,8 +1161,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_sleep		= &newu->peer_wait;
 	otheru = unix_sk(other);
@@ -1156,7 +1177,7 @@ restart:
 	}
 
 	/* Set credentials */
-	sk->sk_peercred = other->sk_peercred;
+	copy_peercred(sk, other);
 
 	sock->state	= SS_CONNECTED;
 	sk->sk_state	= TCP_ESTABLISHED;
@@ -1198,10 +1219,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;
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 4/8] af_unix: Allow SO_PEERCRED to work across namespaces.
@ 2010-06-13 13:30   ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:30 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


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 <ebiederm@xmission.com>
---
 include/net/sock.h |    3 ++-
 net/core/sock.c    |   18 ++++++++++++------
 net/unix/af_unix.c |   37 ++++++++++++++++++++++++++++---------
 3 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index 56df440..5b1eb7d 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -290,7 +290,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 9e229d8..9d197a6 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -900,11 +900,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:
 	{
@@ -1105,6 +1109,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);
 }
@@ -1927,9 +1934,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 3d9122e..028fa25 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -449,11 +449,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)
@@ -469,12 +489,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;
 }
@@ -1139,8 +1161,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_sleep		= &newu->peer_wait;
 	otheru = unix_sk(other);
@@ -1156,7 +1177,7 @@ restart:
 	}
 
 	/* Set credentials */
-	sk->sk_peercred = other->sk_peercred;
+	copy_peercred(sk, other);
 
 	sock->state	= SS_CONNECTED;
 	sk->sk_state	= TCP_ESTABLISHED;
@@ -1198,10 +1219,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;
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 5/8] af_netlink: Add needed scm_destroy after scm_send.
  2010-06-13 13:25 ` Eric W. Biederman
@ 2010-06-13 13:31   ` Eric W. Biederman
  -1 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:31 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


scm_send occasionally allocates state in the scm_cookie, so I have
modified netlink_sendmsg to guarantee that when scm_send succeeds
scm_destory will be called to free that state.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 net/netlink/af_netlink.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 6464a19..35654e7 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1306,19 +1306,23 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	if (msg->msg_flags&MSG_OOB)
 		return -EOPNOTSUPP;
 
-	if (NULL == siocb->scm)
+	if (NULL == siocb->scm) {
 		siocb->scm = &scm;
+		memset(&scm, 0, sizeof(scm));
+	}
 	err = scm_send(sock, msg, siocb->scm);
 	if (err < 0)
 		return err;
 
 	if (msg->msg_namelen) {
+		err = -EINVAL;
 		if (addr->nl_family != AF_NETLINK)
-			return -EINVAL;
+			goto out;
 		dst_pid = addr->nl_pid;
 		dst_group = ffs(addr->nl_groups);
+		err =  -EPERM;
 		if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
-			return -EPERM;
+			goto out;
 	} else {
 		dst_pid = nlk->dst_pid;
 		dst_group = nlk->dst_group;
@@ -1370,6 +1374,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
 
 out:
+	scm_destroy(siocb->scm);
 	return err;
 }
 
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 5/8] af_netlink: Add needed scm_destroy after scm_send.
@ 2010-06-13 13:31   ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:31 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


scm_send occasionally allocates state in the scm_cookie, so I have
modified netlink_sendmsg to guarantee that when scm_send succeeds
scm_destory will be called to free that state.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 net/netlink/af_netlink.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 6464a19..35654e7 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1306,19 +1306,23 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	if (msg->msg_flags&MSG_OOB)
 		return -EOPNOTSUPP;
 
-	if (NULL == siocb->scm)
+	if (NULL == siocb->scm) {
 		siocb->scm = &scm;
+		memset(&scm, 0, sizeof(scm));
+	}
 	err = scm_send(sock, msg, siocb->scm);
 	if (err < 0)
 		return err;
 
 	if (msg->msg_namelen) {
+		err = -EINVAL;
 		if (addr->nl_family != AF_NETLINK)
-			return -EINVAL;
+			goto out;
 		dst_pid = addr->nl_pid;
 		dst_group = ffs(addr->nl_groups);
+		err =  -EPERM;
 		if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
-			return -EPERM;
+			goto out;
 	} else {
 		dst_pid = nlk->dst_pid;
 		dst_group = nlk->dst_group;
@@ -1370,6 +1374,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
 
 out:
+	scm_destroy(siocb->scm);
 	return err;
 }
 
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 6/8] scm: Capture the full credentials of the scm sender.
  2010-06-13 13:25 ` Eric W. Biederman
@ 2010-06-13 13:32   ` Eric W. Biederman
  -1 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:32 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


Start capturing not only the userspace pid, uid and gid values of the
sending process but also the struct pid and struct cred of the sending
process as well.

This is in preparation for properly supporting SCM_CREDENTIALS for
sockets that have different uid and/or pid namespaces at the different
ends.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 include/net/scm.h |   28 ++++++++++++++++++++++++----
 net/core/scm.c    |   24 ++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/include/net/scm.h b/include/net/scm.h
index 17d9d2e..3165650 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -19,6 +19,8 @@ struct scm_fp_list {
 };
 
 struct scm_cookie {
+	struct pid		*pid;		/* Skb credentials */
+	const struct cred	*cred;
 	struct scm_fp_list	*fp;		/* Passed files		*/
 	struct ucred		creds;		/* Skb credentials	*/
 #ifdef CONFIG_SECURITY_NETWORK
@@ -42,8 +44,27 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
 { }
 #endif /* CONFIG_SECURITY_NETWORK */
 
+static __inline__ void scm_set_cred(struct scm_cookie *scm,
+				    struct pid *pid, const struct cred *cred)
+{
+	scm->pid  = get_pid(pid);
+	scm->cred = get_cred(cred);
+	cred_to_ucred(pid, cred, &scm->creds);
+}
+
+static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
+{
+	put_pid(scm->pid);
+	scm->pid  = NULL;
+
+	if (scm->cred)
+		put_cred(scm->cred);
+	scm->cred = NULL;
+}
+
 static __inline__ void scm_destroy(struct scm_cookie *scm)
 {
+	scm_destroy_cred(scm);
 	if (scm && scm->fp)
 		__scm_destroy(scm);
 }
@@ -51,10 +72,7 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
 			       struct scm_cookie *scm)
 {
-	struct task_struct *p = current;
-	scm->creds.uid = current_uid();
-	scm->creds.gid = current_gid();
-	scm->creds.pid = task_tgid_vnr(p);
+	scm_set_cred(scm, task_tgid(current), current_cred());
 	scm->fp = NULL;
 	unix_get_peersec_dgram(sock, scm);
 	if (msg->msg_controllen <= 0)
@@ -96,6 +114,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 	if (test_bit(SOCK_PASSCRED, &sock->flags))
 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
 
+	scm_destroy_cred(scm);
+
 	scm_passec(sock, msg, scm);
 
 	if (!scm->fp)
diff --git a/net/core/scm.c b/net/core/scm.c
index b88f6f9..681c976 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -170,6 +170,30 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
 			err = scm_check_creds(&p->creds);
 			if (err)
 				goto error;
+
+			if (pid_vnr(p->pid) != p->creds.pid) {
+				struct pid *pid;
+				err = -ESRCH;
+				pid = find_get_pid(p->creds.pid);
+				if (!pid)
+					goto error;
+				put_pid(p->pid);
+				p->pid = pid;
+			}
+
+			if ((p->cred->euid != p->creds.uid) ||
+				(p->cred->egid != p->creds.gid)) {
+				struct cred *cred;
+				err = -ENOMEM;
+				cred = prepare_creds();
+				if (!cred)
+					goto error;
+
+				cred->uid = cred->euid = p->creds.uid;
+				cred->gid = cred->egid = p->creds.uid;
+				put_cred(p->cred);
+				p->cred = cred;
+			}
 			break;
 		default:
 			goto error;
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 6/8] scm: Capture the full credentials of the scm sender.
@ 2010-06-13 13:32   ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:32 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


Start capturing not only the userspace pid, uid and gid values of the
sending process but also the struct pid and struct cred of the sending
process as well.

This is in preparation for properly supporting SCM_CREDENTIALS for
sockets that have different uid and/or pid namespaces at the different
ends.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 include/net/scm.h |   28 ++++++++++++++++++++++++----
 net/core/scm.c    |   24 ++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/include/net/scm.h b/include/net/scm.h
index 17d9d2e..3165650 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -19,6 +19,8 @@ struct scm_fp_list {
 };
 
 struct scm_cookie {
+	struct pid		*pid;		/* Skb credentials */
+	const struct cred	*cred;
 	struct scm_fp_list	*fp;		/* Passed files		*/
 	struct ucred		creds;		/* Skb credentials	*/
 #ifdef CONFIG_SECURITY_NETWORK
@@ -42,8 +44,27 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
 { }
 #endif /* CONFIG_SECURITY_NETWORK */
 
+static __inline__ void scm_set_cred(struct scm_cookie *scm,
+				    struct pid *pid, const struct cred *cred)
+{
+	scm->pid  = get_pid(pid);
+	scm->cred = get_cred(cred);
+	cred_to_ucred(pid, cred, &scm->creds);
+}
+
+static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
+{
+	put_pid(scm->pid);
+	scm->pid  = NULL;
+
+	if (scm->cred)
+		put_cred(scm->cred);
+	scm->cred = NULL;
+}
+
 static __inline__ void scm_destroy(struct scm_cookie *scm)
 {
+	scm_destroy_cred(scm);
 	if (scm && scm->fp)
 		__scm_destroy(scm);
 }
@@ -51,10 +72,7 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
 			       struct scm_cookie *scm)
 {
-	struct task_struct *p = current;
-	scm->creds.uid = current_uid();
-	scm->creds.gid = current_gid();
-	scm->creds.pid = task_tgid_vnr(p);
+	scm_set_cred(scm, task_tgid(current), current_cred());
 	scm->fp = NULL;
 	unix_get_peersec_dgram(sock, scm);
 	if (msg->msg_controllen <= 0)
@@ -96,6 +114,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 	if (test_bit(SOCK_PASSCRED, &sock->flags))
 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
 
+	scm_destroy_cred(scm);
+
 	scm_passec(sock, msg, scm);
 
 	if (!scm->fp)
diff --git a/net/core/scm.c b/net/core/scm.c
index b88f6f9..681c976 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -170,6 +170,30 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
 			err = scm_check_creds(&p->creds);
 			if (err)
 				goto error;
+
+			if (pid_vnr(p->pid) != p->creds.pid) {
+				struct pid *pid;
+				err = -ESRCH;
+				pid = find_get_pid(p->creds.pid);
+				if (!pid)
+					goto error;
+				put_pid(p->pid);
+				p->pid = pid;
+			}
+
+			if ((p->cred->euid != p->creds.uid) ||
+				(p->cred->egid != p->creds.gid)) {
+				struct cred *cred;
+				err = -ENOMEM;
+				cred = prepare_creds();
+				if (!cred)
+					goto error;
+
+				cred->uid = cred->euid = p->creds.uid;
+				cred->gid = cred->egid = p->creds.uid;
+				put_cred(p->cred);
+				p->cred = cred;
+			}
 			break;
 		default:
 			goto error;
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 7/8] af_unix: Allow credentials to work across user and pid namespaces.
  2010-06-13 13:25 ` Eric W. Biederman
@ 2010-06-13 13:34   ` Eric W. Biederman
  -1 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:34 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


In unix_skb_parms store pointers to struct pid and struct cred instead
of raw uid, gid, and pid values, then translate the credentials on
reception into values that are meaningful in the receiving processes
namespaces.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 include/net/af_unix.h |    4 +-
 net/unix/af_unix.c    |   53 ++++++++++++++++++++++++++++--------------------
 2 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 1614d78..59d636c 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -23,7 +23,8 @@ struct unix_address {
 };
 
 struct unix_skb_parms {
-	struct ucred		creds;		/* Skb credentials	*/
+	struct pid		*pid;		/* Skb credentials	*/
+	const struct cred	*cred;
 	struct scm_fp_list	*fp;		/* Passed files		*/
 #ifdef CONFIG_SECURITY_NETWORK
 	u32			secid;		/* Security ID		*/
@@ -31,7 +32,6 @@ struct unix_skb_parms {
 };
 
 #define UNIXCB(skb) 	(*(struct unix_skb_parms*)&((skb)->cb))
-#define UNIXCREDS(skb)	(&UNIXCB((skb)).creds)
 #define UNIXSID(skb)	(&UNIXCB((skb)).secid)
 
 #define unix_state_lock(s)	spin_lock(&unix_sk(s)->lock)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 028fa25..78d412a 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1315,18 +1315,20 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 	int i;
 
 	scm->fp = UNIXCB(skb).fp;
-	skb->destructor = sock_wfree;
 	UNIXCB(skb).fp = NULL;
 
 	for (i = scm->fp->count-1; i >= 0; i--)
 		unix_notinflight(scm->fp->fp[i]);
 }
 
-static void unix_destruct_fds(struct sk_buff *skb)
+static void unix_destruct_scm(struct sk_buff *skb)
 {
 	struct scm_cookie scm;
 	memset(&scm, 0, sizeof(scm));
-	unix_detach_fds(&scm, skb);
+	scm.pid  = UNIXCB(skb).pid;
+	scm.cred = UNIXCB(skb).cred;
+	if (UNIXCB(skb).fp)
+		unix_detach_fds(&scm, skb);
 
 	/* Alas, it calls VFS */
 	/* So fscking what? fput() had been SMP-safe since the last Summer */
@@ -1349,10 +1351,22 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 
 	for (i = scm->fp->count-1; i >= 0; i--)
 		unix_inflight(scm->fp->fp[i]);
-	skb->destructor = unix_destruct_fds;
 	return 0;
 }
 
+static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
+{
+	int err = 0;
+	UNIXCB(skb).pid  = get_pid(scm->pid);
+	UNIXCB(skb).cred = get_cred(scm->cred);
+	UNIXCB(skb).fp = NULL;
+ 	if (scm->fp && send_fds)
+ 		err = unix_attach_fds(scm, skb);
+ 
+	skb->destructor = unix_destruct_scm;
+ 	return err;
+}
+
 /*
  *	Send AF_UNIX data.
  */
@@ -1409,12 +1423,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	if (skb == NULL)
 		goto out;
 
-	memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
-	if (siocb->scm->fp) {
-		err = unix_attach_fds(siocb->scm, skb);
-		if (err)
-			goto out_free;
-	}
+	err = unix_scm_to_skb(siocb->scm, skb, true);
+	if (err)
+		goto out_free;
 	unix_get_secdata(siocb->scm, skb);
 
 	skb_reset_transport_header(skb);
@@ -1584,16 +1595,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 		 */
 		size = min_t(int, size, skb_tailroom(skb));
 
-		memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
+		
 		/* Only send the fds in the first buffer */
-		if (siocb->scm->fp && !fds_sent) {
-			err = unix_attach_fds(siocb->scm, skb);
-			if (err) {
-				kfree_skb(skb);
-				goto out_err;
-			}
-			fds_sent = true;
+		err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
+		if (err) {
+			kfree_skb(skb);
+			goto out_err;
 		}
+		fds_sent = true;
 
 		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 		if (err) {
@@ -1710,7 +1719,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 		siocb->scm = &tmp_scm;
 		memset(&tmp_scm, 0, sizeof(tmp_scm));
 	}
-	siocb->scm->creds = *UNIXCREDS(skb);
+	scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
 	unix_set_secdata(siocb->scm, skb);
 
 	if (!(flags & MSG_PEEK)) {
@@ -1859,14 +1868,14 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 
 		if (check_creds) {
 			/* Never glue messages from different writers */
-			if (memcmp(UNIXCREDS(skb), &siocb->scm->creds,
-				   sizeof(siocb->scm->creds)) != 0) {
+			if ((UNIXCB(skb).pid  != siocb->scm->pid) ||
+			    (UNIXCB(skb).cred != siocb->scm->cred)) {
 				skb_queue_head(&sk->sk_receive_queue, skb);
 				break;
 			}
 		} else {
 			/* Copy credentials */
-			siocb->scm->creds = *UNIXCREDS(skb);
+			scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
 			check_creds = 1;
 		}
 
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 7/8] af_unix: Allow credentials to work across user and pid namespaces.
@ 2010-06-13 13:34   ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:34 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


In unix_skb_parms store pointers to struct pid and struct cred instead
of raw uid, gid, and pid values, then translate the credentials on
reception into values that are meaningful in the receiving processes
namespaces.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 include/net/af_unix.h |    4 +-
 net/unix/af_unix.c    |   53 ++++++++++++++++++++++++++++--------------------
 2 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 1614d78..59d636c 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -23,7 +23,8 @@ struct unix_address {
 };
 
 struct unix_skb_parms {
-	struct ucred		creds;		/* Skb credentials	*/
+	struct pid		*pid;		/* Skb credentials	*/
+	const struct cred	*cred;
 	struct scm_fp_list	*fp;		/* Passed files		*/
 #ifdef CONFIG_SECURITY_NETWORK
 	u32			secid;		/* Security ID		*/
@@ -31,7 +32,6 @@ struct unix_skb_parms {
 };
 
 #define UNIXCB(skb) 	(*(struct unix_skb_parms*)&((skb)->cb))
-#define UNIXCREDS(skb)	(&UNIXCB((skb)).creds)
 #define UNIXSID(skb)	(&UNIXCB((skb)).secid)
 
 #define unix_state_lock(s)	spin_lock(&unix_sk(s)->lock)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 028fa25..78d412a 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1315,18 +1315,20 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 	int i;
 
 	scm->fp = UNIXCB(skb).fp;
-	skb->destructor = sock_wfree;
 	UNIXCB(skb).fp = NULL;
 
 	for (i = scm->fp->count-1; i >= 0; i--)
 		unix_notinflight(scm->fp->fp[i]);
 }
 
-static void unix_destruct_fds(struct sk_buff *skb)
+static void unix_destruct_scm(struct sk_buff *skb)
 {
 	struct scm_cookie scm;
 	memset(&scm, 0, sizeof(scm));
-	unix_detach_fds(&scm, skb);
+	scm.pid  = UNIXCB(skb).pid;
+	scm.cred = UNIXCB(skb).cred;
+	if (UNIXCB(skb).fp)
+		unix_detach_fds(&scm, skb);
 
 	/* Alas, it calls VFS */
 	/* So fscking what? fput() had been SMP-safe since the last Summer */
@@ -1349,10 +1351,22 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 
 	for (i = scm->fp->count-1; i >= 0; i--)
 		unix_inflight(scm->fp->fp[i]);
-	skb->destructor = unix_destruct_fds;
 	return 0;
 }
 
+static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
+{
+	int err = 0;
+	UNIXCB(skb).pid  = get_pid(scm->pid);
+	UNIXCB(skb).cred = get_cred(scm->cred);
+	UNIXCB(skb).fp = NULL;
+ 	if (scm->fp && send_fds)
+ 		err = unix_attach_fds(scm, skb);
+ 
+	skb->destructor = unix_destruct_scm;
+ 	return err;
+}
+
 /*
  *	Send AF_UNIX data.
  */
@@ -1409,12 +1423,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	if (skb == NULL)
 		goto out;
 
-	memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
-	if (siocb->scm->fp) {
-		err = unix_attach_fds(siocb->scm, skb);
-		if (err)
-			goto out_free;
-	}
+	err = unix_scm_to_skb(siocb->scm, skb, true);
+	if (err)
+		goto out_free;
 	unix_get_secdata(siocb->scm, skb);
 
 	skb_reset_transport_header(skb);
@@ -1584,16 +1595,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 		 */
 		size = min_t(int, size, skb_tailroom(skb));
 
-		memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
+		
 		/* Only send the fds in the first buffer */
-		if (siocb->scm->fp && !fds_sent) {
-			err = unix_attach_fds(siocb->scm, skb);
-			if (err) {
-				kfree_skb(skb);
-				goto out_err;
-			}
-			fds_sent = true;
+		err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
+		if (err) {
+			kfree_skb(skb);
+			goto out_err;
 		}
+		fds_sent = true;
 
 		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
 		if (err) {
@@ -1710,7 +1719,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 		siocb->scm = &tmp_scm;
 		memset(&tmp_scm, 0, sizeof(tmp_scm));
 	}
-	siocb->scm->creds = *UNIXCREDS(skb);
+	scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
 	unix_set_secdata(siocb->scm, skb);
 
 	if (!(flags & MSG_PEEK)) {
@@ -1859,14 +1868,14 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 
 		if (check_creds) {
 			/* Never glue messages from different writers */
-			if (memcmp(UNIXCREDS(skb), &siocb->scm->creds,
-				   sizeof(siocb->scm->creds)) != 0) {
+			if ((UNIXCB(skb).pid  != siocb->scm->pid) ||
+			    (UNIXCB(skb).cred != siocb->scm->cred)) {
 				skb_queue_head(&sk->sk_receive_queue, skb);
 				break;
 			}
 		} else {
 			/* Copy credentials */
-			siocb->scm->creds = *UNIXCREDS(skb);
+			scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
 			check_creds = 1;
 		}
 
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 8/8] af_unix: Allow connecting to sockets in other network namespaces.
  2010-06-13 13:25 ` Eric W. Biederman
@ 2010-06-13 13:35   ` Eric W. Biederman
  -1 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:35 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


Remove the restriction that only allows connecting to a unix domain
socket identified by unix path that is in the same network namespace.

Crossing network namespaces is always tricky and we did not support
this at first, because of a strict policy of don't mix the namespaces.
Later after Pavel proposed this we did not support this because no one
had performed the audit to make certain using unix domain sockets
across namespaces is safe.

What fundamentally makes connecting to af_unix sockets in other
namespaces is safe is that you have to have the proper permissions on
the unix domain socket inode that lives in the filesystem.  If you
want strict isolation you just don't create inodes where unfriendlys
can get at them, or with permissions that allow unfriendlys to open
them.  All nicely handled for us by the mount namespace and other
standard file system facilities.

I looked through unix domain sockets and they are a very controlled
environment so none of the work that goes on in dev_forward_skb to
make crossing namespaces safe appears needed, we are not loosing
controll of the skb and so do not need to set up the skb to look like
it is comming in fresh from the outside world.  Further the fields in
struct unix_skb_parms should not have any problems crossing network
namespaces.

Now that we handle SCM_CREDENTIALS in a way that gives useable values
across namespaces.  There does not appear to be any operational
problems with encouraging the use of unix domain sockets across
containers either.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 net/unix/af_unix.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 78d412a..4aaff40 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -282,7 +282,7 @@ static inline struct sock *unix_find_socket_byname(struct net *net,
 	return s;
 }
 
-static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
+static struct sock *unix_find_socket_byinode(struct inode *i)
 {
 	struct sock *s;
 	struct hlist_node *node;
@@ -292,9 +292,6 @@ static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
 		    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
 		struct dentry *dentry = unix_sk(s)->dentry;
 
-		if (!net_eq(sock_net(s), net))
-			continue;
-
 		if (dentry && dentry->d_inode == i) {
 			sock_hold(s);
 			goto found;
@@ -757,7 +754,7 @@ static struct sock *unix_find_other(struct net *net,
 		err = -ECONNREFUSED;
 		if (!S_ISSOCK(inode->i_mode))
 			goto put_fail;
-		u = unix_find_socket_byinode(net, inode);
+		u = unix_find_socket_byinode(inode);
 		if (!u)
 			goto put_fail;
 
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 8/8] af_unix: Allow connecting to sockets in other network namespaces.
@ 2010-06-13 13:35   ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-13 13:35 UTC (permalink / raw)
  To: David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev, Pavel Emelyanov


Remove the restriction that only allows connecting to a unix domain
socket identified by unix path that is in the same network namespace.

Crossing network namespaces is always tricky and we did not support
this at first, because of a strict policy of don't mix the namespaces.
Later after Pavel proposed this we did not support this because no one
had performed the audit to make certain using unix domain sockets
across namespaces is safe.

What fundamentally makes connecting to af_unix sockets in other
namespaces is safe is that you have to have the proper permissions on
the unix domain socket inode that lives in the filesystem.  If you
want strict isolation you just don't create inodes where unfriendlys
can get at them, or with permissions that allow unfriendlys to open
them.  All nicely handled for us by the mount namespace and other
standard file system facilities.

I looked through unix domain sockets and they are a very controlled
environment so none of the work that goes on in dev_forward_skb to
make crossing namespaces safe appears needed, we are not loosing
controll of the skb and so do not need to set up the skb to look like
it is comming in fresh from the outside world.  Further the fields in
struct unix_skb_parms should not have any problems crossing network
namespaces.

Now that we handle SCM_CREDENTIALS in a way that gives useable values
across namespaces.  There does not appear to be any operational
problems with encouraging the use of unix domain sockets across
containers either.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 net/unix/af_unix.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 78d412a..4aaff40 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -282,7 +282,7 @@ static inline struct sock *unix_find_socket_byname(struct net *net,
 	return s;
 }
 
-static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
+static struct sock *unix_find_socket_byinode(struct inode *i)
 {
 	struct sock *s;
 	struct hlist_node *node;
@@ -292,9 +292,6 @@ static struct sock *unix_find_socket_byinode(struct net *net, struct inode *i)
 		    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
 		struct dentry *dentry = unix_sk(s)->dentry;
 
-		if (!net_eq(sock_net(s), net))
-			continue;
-
 		if (dentry && dentry->d_inode == i) {
 			sock_hold(s);
 			goto found;
@@ -757,7 +754,7 @@ static struct sock *unix_find_other(struct net *net,
 		err = -ECONNREFUSED;
 		if (!S_ISSOCK(inode->i_mode))
 			goto put_fail;
-		u = unix_find_socket_byinode(net, inode);
+		u = unix_find_socket_byinode(inode);
 		if (!u)
 			goto put_fail;
 
-- 
1.6.5.2.143.g8cc62


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [PATCH 8/8] af_unix: Allow connecting to sockets in other network namespaces.
  2010-06-13 13:35   ` Eric W. Biederman
  (?)
@ 2010-06-14 13:37   ` Daniel Lezcano
  -1 siblings, 0 replies; 38+ messages in thread
From: Daniel Lezcano @ 2010-06-14 13:37 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Serge Hallyn, Linux Containers, netdev, Pavel Emelyanov

On 06/13/2010 03:35 PM, Eric W. Biederman wrote:
> Remove the restriction that only allows connecting to a unix domain
> socket identified by unix path that is in the same network namespace.
>
> Crossing network namespaces is always tricky and we did not support
> this at first, because of a strict policy of don't mix the namespaces.
> Later after Pavel proposed this we did not support this because no one
> had performed the audit to make certain using unix domain sockets
> across namespaces is safe.
>
> What fundamentally makes connecting to af_unix sockets in other
> namespaces is safe is that you have to have the proper permissions on
> the unix domain socket inode that lives in the filesystem.  If you
> want strict isolation you just don't create inodes where unfriendlys
> can get at them, or with permissions that allow unfriendlys to open
> them.  All nicely handled for us by the mount namespace and other
> standard file system facilities.
>
> I looked through unix domain sockets and they are a very controlled
> environment so none of the work that goes on in dev_forward_skb to
> make crossing namespaces safe appears needed, we are not loosing
> controll of the skb and so do not need to set up the skb to look like
> it is comming in fresh from the outside world.  Further the fields in
> struct unix_skb_parms should not have any problems crossing network
> namespaces.
>
> Now that we handle SCM_CREDENTIALS in a way that gives useable values
> across namespaces.  There does not appear to be any operational
> problems with encouraging the use of unix domain sockets across
> containers either.
>
> Signed-off-by: Eric W. Biederman<ebiederm@xmission.com>
>    

Acked-by: Daniel Lezcano <daniel.lezcano@free.fr>


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 5/8] af_netlink: Add needed scm_destroy after scm_send.
  2010-06-13 13:31   ` Eric W. Biederman
  (?)
@ 2010-06-14 13:37   ` Daniel Lezcano
  -1 siblings, 0 replies; 38+ messages in thread
From: Daniel Lezcano @ 2010-06-14 13:37 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Serge Hallyn, Linux Containers, netdev, Pavel Emelyanov

On 06/13/2010 03:31 PM, Eric W. Biederman wrote:
> scm_send occasionally allocates state in the scm_cookie, so I have
> modified netlink_sendmsg to guarantee that when scm_send succeeds
> scm_destory will be called to free that state.
>
> Signed-off-by: Eric W. Biederman<ebiederm@xmission.com>
> ---
>    

Reviewed-by: Daniel Lezcano <daniel.lezcano@free.fr>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/8] af_unix: Allow SO_PEERCRED to work across namespaces.
  2010-06-13 13:30   ` Eric W. Biederman
  (?)
@ 2010-06-14 13:37   ` Daniel Lezcano
  -1 siblings, 0 replies; 38+ messages in thread
From: Daniel Lezcano @ 2010-06-14 13:37 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Serge Hallyn, Linux Containers, netdev, Pavel Emelyanov

On 06/13/2010 03:30 PM, Eric W. Biederman wrote:
> 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<ebiederm@xmission.com>
>    

Acked-by: Daniel Lezcano <daniel.lezcano@free.fr>


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 1/8] scm: Reorder scm_cookie.
  2010-06-13 13:27   ` Eric W. Biederman
  (?)
  (?)
@ 2010-06-15  8:00   ` Pavel Emelyanov
  -1 siblings, 0 replies; 38+ messages in thread
From: Pavel Emelyanov @ 2010-06-15  8:00 UTC (permalink / raw)
  To: Eric W. Biederman, David Miller
  Cc: Serge Hallyn, Linux Containers, Daniel Lezcano, netdev

On 06/13/2010 05:27 PM, Eric W. Biederman wrote:
> 
> Reorder the fields in scm_cookie so they pack better on 64bit.
> 
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

Acked-by: Pavel Emelyanov <xemul@openvz.org>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 2/8] user_ns: Introduce user_nsmap_uid and user_ns_map_gid.
       [not found]     ` <m17hm3hxjw.fsf_-_-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>
@ 2010-06-15  8:02       ` Pavel Emelyanov
  2010-06-15 22:37         ` Eric W. Biederman
  0 siblings, 1 reply; 38+ messages in thread
From: Pavel Emelyanov @ 2010-06-15  8:02 UTC (permalink / raw)
  To: Eric W. Biederman, David Miller
  Cc: Linux Containers, Serge Hallyn, netdev-u79uwXL29TY76Z2rM5mHXA

On 06/13/2010 05:28 PM, Eric W. Biederman wrote:
> 
> Define what happens when a we view a uid from one user_namespace
> in another user_namepece.
> 
> - If the user namespaces are the same no mapping is necessary.
> 
> - For most cases of difference use overflowuid and overflowgid,
>   the uid and gid currently used for 16bit apis when we have a 32bit uid
>   that does fit in 16bits.  Effectively the situation is the same,
>   we want to return a uid or gid that is not assigned to any user.
> 
> - For the case when we happen to be mapping the uid or gid of the
>   creator of the target user namespace use uid 0 and gid as confusing
>   that user with root is not a problem.
> 
> Signed-off-by: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

I suppose this one should go via Andrew, not Dave.

Anyway, Acked-by: Pavel Emelyanov <xemul-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 3/8] sock: Introduce cred_to_ucred
  2010-06-13 13:28   ` Eric W. Biederman
  (?)
@ 2010-06-15  8:03   ` Pavel Emelyanov
  -1 siblings, 0 replies; 38+ messages in thread
From: Pavel Emelyanov @ 2010-06-15  8:03 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Serge Hallyn, Linux Containers, Daniel Lezcano, netdev

On 06/13/2010 05:28 PM, Eric W. Biederman wrote:
> 
> 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 <ebiederm@xmission.com>

Acked-by: Pavel Emelyanov <xemul@openvz.org>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/8] af_unix: Allow SO_PEERCRED to work across namespaces.
  2010-06-13 13:30   ` Eric W. Biederman
  (?)
  (?)
@ 2010-06-15  8:04   ` Pavel Emelyanov
  -1 siblings, 0 replies; 38+ messages in thread
From: Pavel Emelyanov @ 2010-06-15  8:04 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Serge Hallyn, Linux Containers, Daniel Lezcano, netdev

On 06/13/2010 05:30 PM, Eric W. Biederman wrote:
> 
> 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 <ebiederm@xmission.com>

Acked-by: Pavel Emelyanov <xemul@openvz.org>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 5/8] af_netlink: Add needed scm_destroy after scm_send.
  2010-06-13 13:31   ` Eric W. Biederman
  (?)
  (?)
@ 2010-06-15  8:06   ` Pavel Emelyanov
  -1 siblings, 0 replies; 38+ messages in thread
From: Pavel Emelyanov @ 2010-06-15  8:06 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Serge Hallyn, Linux Containers, Daniel Lezcano, netdev

On 06/13/2010 05:31 PM, Eric W. Biederman wrote:
> 
> scm_send occasionally allocates state in the scm_cookie, so I have
> modified netlink_sendmsg to guarantee that when scm_send succeeds
> scm_destory will be called to free that state.
> 
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

Acked-by: Pavel Emelyanov <xemul@openvz.org>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 6/8] scm: Capture the full credentials of the scm sender.
  2010-06-13 13:32   ` Eric W. Biederman
  (?)
@ 2010-06-15  8:08   ` Pavel Emelyanov
  2010-06-15  9:53     ` Eric W. Biederman
  -1 siblings, 1 reply; 38+ messages in thread
From: Pavel Emelyanov @ 2010-06-15  8:08 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Serge Hallyn, Linux Containers, Daniel Lezcano, netdev

> +static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
> +{
> +	put_pid(scm->pid);
> +	scm->pid  = NULL;
> +
> +	if (scm->cred)
> +		put_cred(scm->cred);
> +	scm->cred = NULL;
> +}
> +
>  static __inline__ void scm_destroy(struct scm_cookie *scm)
>  {
> +	scm_destroy_cred(scm);
>  	if (scm && scm->fp)
>  		__scm_destroy(scm);
>  }

I'm a bit worried by the "if (scm" check. It makes me think scm can
be NULL here and thus scm_destroy_cred can oops.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 7/8] af_unix: Allow credentials to work across user and pid namespaces.
       [not found]   ` <m17hm3giom.fsf-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>
@ 2010-06-15  8:11     ` Pavel Emelyanov
  0 siblings, 0 replies; 38+ messages in thread
From: Pavel Emelyanov @ 2010-06-15  8:11 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Linux Containers, Serge Hallyn, netdev-u79uwXL29TY76Z2rM5mHXA,
	David Miller

On 06/13/2010 05:34 PM, Eric W. Biederman wrote:
> 
> In unix_skb_parms store pointers to struct pid and struct cred instead
> of raw uid, gid, and pid values, then translate the credentials on
> reception into values that are meaningful in the receiving processes
> namespaces.
> 
> Signed-off-by: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

Acked-by: Pavel Emelyanov <xemul-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 8/8] af_unix: Allow connecting to sockets in other network namespaces.
       [not found]   ` <m11vcbgimj.fsf-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>
@ 2010-06-15  8:12     ` Pavel Emelyanov
  0 siblings, 0 replies; 38+ messages in thread
From: Pavel Emelyanov @ 2010-06-15  8:12 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Linux Containers, Serge Hallyn, netdev-u79uwXL29TY76Z2rM5mHXA,
	David Miller

> [snip]
> 
> Signed-off-by: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

Acked-by: Pavel Emelyanov <xemul-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 6/8] scm: Capture the full credentials of the scm sender.
  2010-06-15  8:08   ` Pavel Emelyanov
@ 2010-06-15  9:53     ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-15  9:53 UTC (permalink / raw)
  To: Pavel Emelyanov
  Cc: David Miller, Serge Hallyn, Linux Containers, Daniel Lezcano, netdev

Pavel Emelyanov <xemul@openvz.org> writes:

>> +static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
>> +{
>> +	put_pid(scm->pid);
>> +	scm->pid  = NULL;
>> +
>> +	if (scm->cred)
>> +		put_cred(scm->cred);
>> +	scm->cred = NULL;
>> +}
>> +
>>  static __inline__ void scm_destroy(struct scm_cookie *scm)
>>  {
>> +	scm_destroy_cred(scm);
>>  	if (scm && scm->fp)
>>  		__scm_destroy(scm);
>>  }
>
> I'm a bit worried by the "if (scm" check. It makes me think scm can
> be NULL here and thus scm_destroy_cred can oops.

Interesting point.  I just looked at all of the callers and scm
appears to always be valid.

Eric


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 2/8] user_ns: Introduce user_nsmap_uid and user_ns_map_gid.
  2010-06-13 13:28     ` Eric W. Biederman
  (?)
  (?)
@ 2010-06-15 20:58     ` Serge E. Hallyn
  -1 siblings, 0 replies; 38+ messages in thread
From: Serge E. Hallyn @ 2010-06-15 20:58 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Linux Containers, Serge Hallyn, Pavel Emelyanov, netdev

Quoting Eric W. Biederman (ebiederm@xmission.com):
> 
> Define what happens when a we view a uid from one user_namespace
> in another user_namepece.
> 
> - If the user namespaces are the same no mapping is necessary.
> 
> - For most cases of difference use overflowuid and overflowgid,
>   the uid and gid currently used for 16bit apis when we have a 32bit uid
>   that does fit in 16bits.  Effectively the situation is the same,
>   we want to return a uid or gid that is not assigned to any user.
> 
> - For the case when we happen to be mapping the uid or gid of the
>   creator of the target user namespace use uid 0 and gid as confusing

Looks good, except for 'uid 0 and gid' in commit msg will be confusing.
Just "use uid and gid 0".

>   that user with root is not a problem.
> 
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

Acked-by: Serge E. Hallyn <serue@us.ibm.com>

Mind you, like you I *am* still conflicted.

I believe the ideal behavior for the case where we're looking up a mapping
for a uid in a namespace created by ns, would be to return the creator's
uid, but then also support returning the POSIX capabilities targeted at
ns, which would be the empty set.

The path leading there is to start with this patch, then support sending
full credentials, and then we can modify this behavior.

(IMO)

thanks for pushing this.

-serge

> ---
>  include/linux/user_namespace.h |   14 ++++++++++++
>  kernel/user_namespace.c        |   44 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
> index cc4f453..8178156 100644
> --- a/include/linux/user_namespace.h
> +++ b/include/linux/user_namespace.h
> @@ -36,6 +36,9 @@ static inline void put_user_ns(struct user_namespace *ns)
>  		kref_put(&ns->kref, free_user_ns);
>  }
>  
> +uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid);
> +gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid);
> +
>  #else
>  
>  static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
> @@ -52,6 +55,17 @@ static inline void put_user_ns(struct user_namespace *ns)
>  {
>  }
>  
> +static inline uid_t user_ns_map_uid(struct user_namespace *to,
> +	const struct cred *cred, uid_t uid)
> +{
> +	return uid;
> +}
> +static inline gid_t user_ns_map_gid(struct user_namespace *to,
> +	const struct cred *cred, gid_t gid)
> +{
> +	return gid;
> +}
> +
>  #endif
>  
>  #endif /* _LINUX_USER_H */
> diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
> index 076c7c8..825abfb 100644
> --- a/kernel/user_namespace.c
> +++ b/kernel/user_namespace.c
> @@ -9,6 +9,7 @@
>  #include <linux/nsproxy.h>
>  #include <linux/slab.h>
>  #include <linux/user_namespace.h>
> +#include <linux/highuid.h>
>  #include <linux/cred.h>
>  
>  /*
> @@ -82,3 +83,46 @@ void free_user_ns(struct kref *kref)
>  	schedule_work(&ns->destroyer);
>  }
>  EXPORT_SYMBOL(free_user_ns);
> +
> +uid_t user_ns_map_uid(struct user_namespace *to, const struct cred *cred, uid_t uid)
> +{
> +	struct user_namespace *tmp;
> +
> +	if (likely(to == cred->user->user_ns))
> +		return uid;
> +
> +
> +	/* Is cred->user the creator of the target user_ns
> +	 * or the creator of one of it's parents?
> +	 */
> +	for ( tmp = to; tmp != &init_user_ns;
> +	      tmp = tmp->creator->user_ns ) {
> +		if (cred->user == tmp->creator) {
> +			return (uid_t)0;
> +		}
> +	}
> +
> +	/* No useful relationship so no mapping */
> +	return overflowuid;
> +}
> +
> +gid_t user_ns_map_gid(struct user_namespace *to, const struct cred *cred, gid_t gid)
> +{
> +	struct user_namespace *tmp;
> +
> +	if (likely(to == cred->user->user_ns))
> +		return gid;
> +
> +	/* Is cred->user the creator of the target user_ns
> +	 * or the creator of one of it's parents?
> +	 */
> +	for ( tmp = to; tmp != &init_user_ns;
> +	      tmp = tmp->creator->user_ns ) {
> +		if (cred->user == tmp->creator) {
> +			return (gid_t)0;
> +		}
> +	}
> +
> +	/* No useful relationship so no mapping */
> +	return overflowgid;
> +}
> -- 
> 1.6.5.2.143.g8cc62
> 
> _______________________________________________
> Containers mailing list
> Containers@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/containers

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 6/8] scm: Capture the full credentials of the scm sender.
  2010-06-13 13:32   ` Eric W. Biederman
  (?)
  (?)
@ 2010-06-15 21:45   ` Serge E. Hallyn
  2010-06-15 22:08     ` Eric W. Biederman
  -1 siblings, 1 reply; 38+ messages in thread
From: Serge E. Hallyn @ 2010-06-15 21:45 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Linux Containers, Serge Hallyn, Pavel Emelyanov, netdev

Quoting Eric W. Biederman (ebiederm@xmission.com):
> 
> Start capturing not only the userspace pid, uid and gid values of the
> sending process but also the struct pid and struct cred of the sending
> process as well.
> 
> This is in preparation for properly supporting SCM_CREDENTIALS for
> sockets that have different uid and/or pid namespaces at the different
> ends.
> 
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
> ---
>  include/net/scm.h |   28 ++++++++++++++++++++++++----
>  net/core/scm.c    |   24 ++++++++++++++++++++++++
>  2 files changed, 48 insertions(+), 4 deletions(-)
> 
> diff --git a/include/net/scm.h b/include/net/scm.h
> index 17d9d2e..3165650 100644
> --- a/include/net/scm.h
> +++ b/include/net/scm.h
> @@ -19,6 +19,8 @@ struct scm_fp_list {
>  };
>  
>  struct scm_cookie {
> +	struct pid		*pid;		/* Skb credentials */
> +	const struct cred	*cred;
>  	struct scm_fp_list	*fp;		/* Passed files		*/
>  	struct ucred		creds;		/* Skb credentials	*/
>  #ifdef CONFIG_SECURITY_NETWORK
> @@ -42,8 +44,27 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
>  { }
>  #endif /* CONFIG_SECURITY_NETWORK */
>  
> +static __inline__ void scm_set_cred(struct scm_cookie *scm,
> +				    struct pid *pid, const struct cred *cred)
> +{
> +	scm->pid  = get_pid(pid);
> +	scm->cred = get_cred(cred);
> +	cred_to_ucred(pid, cred, &scm->creds);
> +}
> +
> +static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
> +{
> +	put_pid(scm->pid);
> +	scm->pid  = NULL;
> +
> +	if (scm->cred)
> +		put_cred(scm->cred);
> +	scm->cred = NULL;
> +}
> +
>  static __inline__ void scm_destroy(struct scm_cookie *scm)
>  {
> +	scm_destroy_cred(scm);
>  	if (scm && scm->fp)
>  		__scm_destroy(scm);
>  }
> @@ -51,10 +72,7 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
>  static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
>  			       struct scm_cookie *scm)
>  {
> -	struct task_struct *p = current;
> -	scm->creds.uid = current_uid();
> -	scm->creds.gid = current_gid();
> -	scm->creds.pid = task_tgid_vnr(p);
> +	scm_set_cred(scm, task_tgid(current), current_cred());
>  	scm->fp = NULL;
>  	unix_get_peersec_dgram(sock, scm);
>  	if (msg->msg_controllen <= 0)
> @@ -96,6 +114,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
>  	if (test_bit(SOCK_PASSCRED, &sock->flags))
>  		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
>  
> +	scm_destroy_cred(scm);
> +
>  	scm_passec(sock, msg, scm);
>  
>  	if (!scm->fp)
> diff --git a/net/core/scm.c b/net/core/scm.c
> index b88f6f9..681c976 100644
> --- a/net/core/scm.c
> +++ b/net/core/scm.c
> @@ -170,6 +170,30 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
>  			err = scm_check_creds(&p->creds);
>  			if (err)
>  				goto error;
> +

I think this hunk needs to be documented.  I.e. given that scm_send()
will call scm_set_cred() before calling __scm_send, I don't see how
these conditions could happen?  If the condition can legitimately
happen, then given all of the pid_t vs struct pid and 'cred' vs. 'creds'
in these two hunks, I think a comment over each would be nice.

> +			if (pid_vnr(p->pid) != p->creds.pid) {
> +				struct pid *pid;
> +				err = -ESRCH;
> +				pid = find_get_pid(p->creds.pid);
> +				if (!pid)
> +					goto error;
> +				put_pid(p->pid);
> +				p->pid = pid;
> +			}
> +
> +			if ((p->cred->euid != p->creds.uid) ||
> +				(p->cred->egid != p->creds.gid)) {
> +				struct cred *cred;
> +				err = -ENOMEM;
> +				cred = prepare_creds();
> +				if (!cred)
> +					goto error;
> +
> +				cred->uid = cred->euid = p->creds.uid;
> +				cred->gid = cred->egid = p->creds.uid;
> +				put_cred(p->cred);
> +				p->cred = cred;
> +			}
>  			break;
>  		default:
>  			goto error;
> -- 
> 1.6.5.2.143.g8cc62
> 
> _______________________________________________
> Containers mailing list
> Containers@lists.linux-foundation.org
> https://lists.linux-foundation.org/mailman/listinfo/containers

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 6/8] scm: Capture the full credentials of the scm sender.
  2010-06-15 21:45   ` Serge E. Hallyn
@ 2010-06-15 22:08     ` Eric W. Biederman
  2010-06-16  4:47       ` Serge E. Hallyn
  0 siblings, 1 reply; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-15 22:08 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: David Miller, Linux Containers, Serge Hallyn, Pavel Emelyanov, netdev

"Serge E. Hallyn" <serge@hallyn.com> writes:

> Quoting Eric W. Biederman (ebiederm@xmission.com):
>> 
>> Start capturing not only the userspace pid, uid and gid values of the
>> sending process but also the struct pid and struct cred of the sending
>> process as well.
>> 
>> This is in preparation for properly supporting SCM_CREDENTIALS for
>> sockets that have different uid and/or pid namespaces at the different
>> ends.
>> 
>> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
>> ---
>>  include/net/scm.h |   28 ++++++++++++++++++++++++----
>>  net/core/scm.c    |   24 ++++++++++++++++++++++++
>>  2 files changed, 48 insertions(+), 4 deletions(-)
>> 
>> diff --git a/include/net/scm.h b/include/net/scm.h
>> index 17d9d2e..3165650 100644
>> --- a/include/net/scm.h
>> +++ b/include/net/scm.h
>> @@ -19,6 +19,8 @@ struct scm_fp_list {
>>  };
>>  
>>  struct scm_cookie {
>> +	struct pid		*pid;		/* Skb credentials */
>> +	const struct cred	*cred;
>>  	struct scm_fp_list	*fp;		/* Passed files		*/
>>  	struct ucred		creds;		/* Skb credentials	*/
>>  #ifdef CONFIG_SECURITY_NETWORK
>> @@ -42,8 +44,27 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
>>  { }
>>  #endif /* CONFIG_SECURITY_NETWORK */
>>  
>> +static __inline__ void scm_set_cred(struct scm_cookie *scm,
>> +				    struct pid *pid, const struct cred *cred)
>> +{
>> +	scm->pid  = get_pid(pid);
>> +	scm->cred = get_cred(cred);
>> +	cred_to_ucred(pid, cred, &scm->creds);
>> +}
>> +
>> +static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
>> +{
>> +	put_pid(scm->pid);
>> +	scm->pid  = NULL;
>> +
>> +	if (scm->cred)
>> +		put_cred(scm->cred);
>> +	scm->cred = NULL;
>> +}
>> +
>>  static __inline__ void scm_destroy(struct scm_cookie *scm)
>>  {
>> +	scm_destroy_cred(scm);
>>  	if (scm && scm->fp)
>>  		__scm_destroy(scm);
>>  }
>> @@ -51,10 +72,7 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
>>  static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
>>  			       struct scm_cookie *scm)
>>  {
>> -	struct task_struct *p = current;
>> -	scm->creds.uid = current_uid();
>> -	scm->creds.gid = current_gid();
>> -	scm->creds.pid = task_tgid_vnr(p);
>> +	scm_set_cred(scm, task_tgid(current), current_cred());
>>  	scm->fp = NULL;
>>  	unix_get_peersec_dgram(sock, scm);
>>  	if (msg->msg_controllen <= 0)
>> @@ -96,6 +114,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
>>  	if (test_bit(SOCK_PASSCRED, &sock->flags))
>>  		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
>>  
>> +	scm_destroy_cred(scm);
>> +
>>  	scm_passec(sock, msg, scm);
>>  
>>  	if (!scm->fp)
>> diff --git a/net/core/scm.c b/net/core/scm.c
>> index b88f6f9..681c976 100644
>> --- a/net/core/scm.c
>> +++ b/net/core/scm.c
>> @@ -170,6 +170,30 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
>>  			err = scm_check_creds(&p->creds);
>>  			if (err)
>>  				goto error;
>> +
>
> I think this hunk needs to be documented.  I.e. given that scm_send()
> will call scm_set_cred() before calling __scm_send, I don't see how
> these conditions could happen?  If the condition can legitimately
> happen, then given all of the pid_t vs struct pid and 'cred' vs. 'creds'
> in these two hunks, I think a comment over each would be nice.

I think if you have the full context of __scm_send it becomes pretty obvious.

		case SCM_CREDENTIALS:
			if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
				goto error;
			memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred));
			err = scm_check_creds(&p->creds);
			if (err)
				goto error;

At this point we have just copied ucred from userspace.  We have done
scm_check_creds to ensure we allow the user to send the pid, uid, and
gid they have passed in.

These tests catch the case where the user is legitimately sending
something other than their own credentials.

>> +			if (pid_vnr(p->pid) != p->creds.pid) {
>> +				struct pid *pid;
>> +				err = -ESRCH;
>> +				pid = find_get_pid(p->creds.pid);
>> +				if (!pid)
>> +					goto error;
>> +				put_pid(p->pid);
>> +				p->pid = pid;
>> +			}
>> +
>> +			if ((p->cred->euid != p->creds.uid) ||
>> +				(p->cred->egid != p->creds.gid)) {
>> +				struct cred *cred;
>> +				err = -ENOMEM;
>> +				cred = prepare_creds();
>> +				if (!cred)
>> +					goto error;
>> +
>> +				cred->uid = cred->euid = p->creds.uid;
>> +				cred->gid = cred->egid = p->creds.uid;
>> +				put_cred(p->cred);
>> +				p->cred = cred;
>> +			}
>>  			break;
>>  		default:
>>  			goto error;

Eric

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 2/8] user_ns: Introduce user_nsmap_uid and user_ns_map_gid.
  2010-06-15  8:02       ` Pavel Emelyanov
@ 2010-06-15 22:37         ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-15 22:37 UTC (permalink / raw)
  To: Pavel Emelyanov
  Cc: David Miller, Serge Hallyn, Linux Containers, Daniel Lezcano, netdev

Pavel Emelyanov <xemul@openvz.org> writes:

> On 06/13/2010 05:28 PM, Eric W. Biederman wrote:
>> 
>> Define what happens when a we view a uid from one user_namespace
>> in another user_namepece.
>> 
>> - If the user namespaces are the same no mapping is necessary.
>> 
>> - For most cases of difference use overflowuid and overflowgid,
>>   the uid and gid currently used for 16bit apis when we have a 32bit uid
>>   that does fit in 16bits.  Effectively the situation is the same,
>>   we want to return a uid or gid that is not assigned to any user.
>> 
>> - For the case when we happen to be mapping the uid or gid of the
>>   creator of the target user namespace use uid 0 and gid as confusing
>>   that user with root is not a problem.
>> 
>> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
>
> I suppose this one should go via Andrew, not Dave.

If it was stand alone I would send it that way.

In this case I'm hope Dave will indulge me because this bit is
simple, the only user for now is the network stack, and the people
maintaining the code have already acked the patch.

Eric

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 6/8] scm: Capture the full credentials of the scm sender.
  2010-06-15 22:08     ` Eric W. Biederman
@ 2010-06-16  4:47       ` Serge E. Hallyn
  0 siblings, 0 replies; 38+ messages in thread
From: Serge E. Hallyn @ 2010-06-16  4:47 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David Miller, Linux Containers, Serge Hallyn, Pavel Emelyanov, netdev

Quoting Eric W. Biederman (ebiederm@xmission.com):
> "Serge E. Hallyn" <serge@hallyn.com> writes:
> > I think this hunk needs to be documented.  I.e. given that scm_send()
> > will call scm_set_cred() before calling __scm_send, I don't see how
> > these conditions could happen?  If the condition can legitimately
> > happen, then given all of the pid_t vs struct pid and 'cred' vs. 'creds'
> > in these two hunks, I think a comment over each would be nice.
> 
> I think if you have the full context of __scm_send it becomes pretty obvious.
> 
> 		case SCM_CREDENTIALS:
> 			if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
> 				goto error;
> 			memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred));
> 			err = scm_check_creds(&p->creds);
> 			if (err)
> 				goto error;
> 
> At this point we have just copied ucred from userspace.  We have done
> scm_check_creds to ensure we allow the user to send the pid, uid, and
> gid they have passed in.
> 
> These tests catch the case where the user is legitimately sending
> something other than their own credentials.

Of course.  Sorry.  And I even had the context in the window next to the
email...  So finally,

Acked-by: Serge E. Hallyn <serge@hallyn.com>

to the set, and I'm looking forward to this being in.  And it should solve
the nuisance of containers without private netns rebooting their hosts
when both use upstart.

thanks,
-serge

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 0/8] Support unix domain sockets across namespaces
  2010-06-13 13:25 ` Eric W. Biederman
                   ` (7 preceding siblings ...)
  (?)
@ 2010-06-16 22:15 ` David Miller
  2010-06-16 23:17   ` David Miller
  -1 siblings, 1 reply; 38+ messages in thread
From: David Miller @ 2010-06-16 22:15 UTC (permalink / raw)
  To: ebiederm; +Cc: serue, containers, daniel.lezcano, netdev, xemul

From: ebiederm@xmission.com (Eric W. Biederman)
Date: Sun, 13 Jun 2010 06:25:32 -0700

> This patchset takes a addressing all of the issues that crop up with
> unix domain sockets when the senders and receivers are in separate
> namespaces.
> 
> Without this patchset we can report the wrong pid and uid
> values in our unix domain credentials.
> 
> As a finally this patchset removes the now unnecessary restriction
> that we only allow unix domain sockets between processes in the
> same network namespace.

Looks good, all applied to net-next-2.6, thanks Eric.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 0/8] Support unix domain sockets across namespaces
  2010-06-16 22:15 ` [PATCH 0/8] Support unix domain sockets across namespaces David Miller
@ 2010-06-16 23:17   ` David Miller
  2010-06-16 23:32     ` Eric W. Biederman
  0 siblings, 1 reply; 38+ messages in thread
From: David Miller @ 2010-06-16 23:17 UTC (permalink / raw)
  To: ebiederm; +Cc: serue, containers, daniel.lezcano, netdev, xemul

From: David Miller <davem@davemloft.net>
Date: Wed, 16 Jun 2010 15:15:36 -0700 (PDT)

> From: ebiederm@xmission.com (Eric W. Biederman)
> Date: Sun, 13 Jun 2010 06:25:32 -0700
> 
>> This patchset takes a addressing all of the issues that crop up with
>> unix domain sockets when the senders and receivers are in separate
>> namespaces.
>> 
>> Without this patchset we can report the wrong pid and uid
>> values in our unix domain credentials.
>> 
>> As a finally this patchset removes the now unnecessary restriction
>> that we only allow unix domain sockets between processes in the
>> same network namespace.
> 
> Looks good, all applied to net-next-2.6, thanks Eric.

I had to add a module export of cred_to_ucread to fix the allmodconfig
build since AF_UNIX makes a reference to it.

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 0/8] Support unix domain sockets across namespaces
  2010-06-16 23:17   ` David Miller
@ 2010-06-16 23:32     ` Eric W. Biederman
  0 siblings, 0 replies; 38+ messages in thread
From: Eric W. Biederman @ 2010-06-16 23:32 UTC (permalink / raw)
  To: David Miller; +Cc: serue, containers, daniel.lezcano, netdev, xemul

David Miller <davem@davemloft.net> writes:

> From: David Miller <davem@davemloft.net>
> Date: Wed, 16 Jun 2010 15:15:36 -0700 (PDT)
>
>> From: ebiederm@xmission.com (Eric W. Biederman)
>> Date: Sun, 13 Jun 2010 06:25:32 -0700
>> 
>>> This patchset takes a addressing all of the issues that crop up with
>>> unix domain sockets when the senders and receivers are in separate
>>> namespaces.
>>> 
>>> Without this patchset we can report the wrong pid and uid
>>> values in our unix domain credentials.
>>> 
>>> As a finally this patchset removes the now unnecessary restriction
>>> that we only allow unix domain sockets between processes in the
>>> same network namespace.
>> 
>> Looks good, all applied to net-next-2.6, thanks Eric.
>
> I had to add a module export of cred_to_ucread to fix the allmodconfig
> build since AF_UNIX makes a reference to it.

Doh!  Thank you for catching that.

My apologies for overlooking the allmodconfig case.

Eric


^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2010-06-16 23:32 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-13 13:25 [PATCH 0/8] Support unix domain sockets across namespaces Eric W. Biederman
2010-06-13 13:25 ` Eric W. Biederman
2010-06-13 13:27 ` [PATCH 1/8] scm: Reorder scm_cookie Eric W. Biederman
2010-06-13 13:27   ` Eric W. Biederman
2010-06-13 13:28   ` [PATCH 2/8] user_ns: Introduce user_nsmap_uid and user_ns_map_gid Eric W. Biederman
2010-06-13 13:28     ` Eric W. Biederman
     [not found]     ` <m17hm3hxjw.fsf_-_-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>
2010-06-15  8:02       ` Pavel Emelyanov
2010-06-15 22:37         ` Eric W. Biederman
2010-06-15 20:58     ` Serge E. Hallyn
2010-06-15  8:00   ` [PATCH 1/8] scm: Reorder scm_cookie Pavel Emelyanov
2010-06-13 13:28 ` [PATCH 3/8] sock: Introduce cred_to_ucred Eric W. Biederman
2010-06-13 13:28   ` Eric W. Biederman
2010-06-15  8:03   ` Pavel Emelyanov
2010-06-13 13:30 ` [PATCH 4/8] af_unix: Allow SO_PEERCRED to work across namespaces Eric W. Biederman
2010-06-13 13:30   ` Eric W. Biederman
2010-06-14 13:37   ` Daniel Lezcano
2010-06-15  8:04   ` Pavel Emelyanov
2010-06-13 13:31 ` [PATCH 5/8] af_netlink: Add needed scm_destroy after scm_send Eric W. Biederman
2010-06-13 13:31   ` Eric W. Biederman
2010-06-14 13:37   ` Daniel Lezcano
2010-06-15  8:06   ` Pavel Emelyanov
2010-06-13 13:32 ` [PATCH 6/8] scm: Capture the full credentials of the scm sender Eric W. Biederman
2010-06-13 13:32   ` Eric W. Biederman
2010-06-15  8:08   ` Pavel Emelyanov
2010-06-15  9:53     ` Eric W. Biederman
2010-06-15 21:45   ` Serge E. Hallyn
2010-06-15 22:08     ` Eric W. Biederman
2010-06-16  4:47       ` Serge E. Hallyn
2010-06-13 13:34 ` [PATCH 7/8] af_unix: Allow credentials to work across user and pid namespaces Eric W. Biederman
2010-06-13 13:34   ` Eric W. Biederman
     [not found]   ` <m17hm3giom.fsf-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>
2010-06-15  8:11     ` Pavel Emelyanov
2010-06-13 13:35 ` [PATCH 8/8] af_unix: Allow connecting to sockets in other network namespaces Eric W. Biederman
2010-06-13 13:35   ` Eric W. Biederman
2010-06-14 13:37   ` Daniel Lezcano
     [not found]   ` <m11vcbgimj.fsf-+imSwln9KH6u2/kzUuoCbdi2O/JbrIOy@public.gmane.org>
2010-06-15  8:12     ` Pavel Emelyanov
2010-06-16 22:15 ` [PATCH 0/8] Support unix domain sockets across namespaces David Miller
2010-06-16 23:17   ` David Miller
2010-06-16 23:32     ` Eric W. Biederman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.