diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-09-06 14:20:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-07 14:42:05 -0400 |
commit | dbe9a4173ea53b72b2c35d19f676a85b69f1c9fe (patch) | |
tree | 49952d501032a2bc303d1d646ec6b1f00773b266 /include | |
parent | d679c5324d9a87c6295f56c2dea52d5f68834f41 (diff) |
scm: Don't use struct ucred in NETLINK_CB and struct scm_cookie.
Passing uids and gids on NETLINK_CB from a process in one user
namespace to a process in another user namespace can result in the
wrong uid or gid being presented to userspace. Avoid that problem by
passing kuids and kgids instead.
- define struct scm_creds for use in scm_cookie and netlink_skb_parms
that holds uid and gid information in kuid_t and kgid_t.
- Modify scm_set_cred to fill out scm_creds by heand instead of using
cred_to_ucred to fill out struct ucred. This conversion ensures
userspace does not get incorrect uid or gid values to look at.
- Modify scm_recv to convert from struct scm_creds to struct ucred
before copying credential values to userspace.
- Modify __scm_send to populate struct scm_creds on in the scm_cookie,
instead of just copying struct ucred from userspace.
- Modify netlink_sendmsg to copy scm_creds instead of struct ucred
into the NETLINK_CB.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/netlink.h | 3 | ||||
-rw-r--r-- | include/net/scm.h | 23 |
2 files changed, 21 insertions, 5 deletions
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index c9fdde2bc73f..df73cf4b0290 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
@@ -153,6 +153,7 @@ struct nlattr { | |||
153 | 153 | ||
154 | #include <linux/capability.h> | 154 | #include <linux/capability.h> |
155 | #include <linux/skbuff.h> | 155 | #include <linux/skbuff.h> |
156 | #include <net/scm.h> | ||
156 | 157 | ||
157 | struct net; | 158 | struct net; |
158 | 159 | ||
@@ -162,7 +163,7 @@ static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb) | |||
162 | } | 163 | } |
163 | 164 | ||
164 | struct netlink_skb_parms { | 165 | struct netlink_skb_parms { |
165 | struct ucred creds; /* Skb credentials */ | 166 | struct scm_creds creds; /* Skb credentials */ |
166 | __u32 pid; | 167 | __u32 pid; |
167 | __u32 dst_group; | 168 | __u32 dst_group; |
168 | struct sock *ssk; | 169 | struct sock *ssk; |
diff --git a/include/net/scm.h b/include/net/scm.h index 7dc0854f0b38..456695f5cbc4 100644 --- a/include/net/scm.h +++ b/include/net/scm.h | |||
@@ -12,6 +12,12 @@ | |||
12 | */ | 12 | */ |
13 | #define SCM_MAX_FD 253 | 13 | #define SCM_MAX_FD 253 |
14 | 14 | ||
15 | struct scm_creds { | ||
16 | u32 pid; | ||
17 | kuid_t uid; | ||
18 | kgid_t gid; | ||
19 | }; | ||
20 | |||
15 | struct scm_fp_list { | 21 | struct scm_fp_list { |
16 | short count; | 22 | short count; |
17 | short max; | 23 | short max; |
@@ -22,7 +28,7 @@ struct scm_cookie { | |||
22 | struct pid *pid; /* Skb credentials */ | 28 | struct pid *pid; /* Skb credentials */ |
23 | const struct cred *cred; | 29 | const struct cred *cred; |
24 | struct scm_fp_list *fp; /* Passed files */ | 30 | struct scm_fp_list *fp; /* Passed files */ |
25 | struct ucred creds; /* Skb credentials */ | 31 | struct scm_creds creds; /* Skb credentials */ |
26 | #ifdef CONFIG_SECURITY_NETWORK | 32 | #ifdef CONFIG_SECURITY_NETWORK |
27 | u32 secid; /* Passed security ID */ | 33 | u32 secid; /* Passed security ID */ |
28 | #endif | 34 | #endif |
@@ -49,7 +55,9 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm, | |||
49 | { | 55 | { |
50 | scm->pid = get_pid(pid); | 56 | scm->pid = get_pid(pid); |
51 | scm->cred = cred ? get_cred(cred) : NULL; | 57 | scm->cred = cred ? get_cred(cred) : NULL; |
52 | cred_to_ucred(pid, cred, &scm->creds); | 58 | scm->creds.pid = pid_vnr(pid); |
59 | scm->creds.uid = cred ? cred->euid : INVALID_UID; | ||
60 | scm->creds.gid = cred ? cred->egid : INVALID_GID; | ||
53 | } | 61 | } |
54 | 62 | ||
55 | static __inline__ void scm_destroy_cred(struct scm_cookie *scm) | 63 | static __inline__ void scm_destroy_cred(struct scm_cookie *scm) |
@@ -112,8 +120,15 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, | |||
112 | return; | 120 | return; |
113 | } | 121 | } |
114 | 122 | ||
115 | if (test_bit(SOCK_PASSCRED, &sock->flags)) | 123 | if (test_bit(SOCK_PASSCRED, &sock->flags)) { |
116 | put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); | 124 | struct user_namespace *current_ns = current_user_ns(); |
125 | struct ucred ucreds = { | ||
126 | .pid = scm->creds.pid, | ||
127 | .uid = from_kuid_munged(current_ns, scm->creds.uid), | ||
128 | .gid = from_kgid_munged(current_ns, scm->creds.gid), | ||
129 | }; | ||
130 | put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds); | ||
131 | } | ||
117 | 132 | ||
118 | scm_destroy_cred(scm); | 133 | scm_destroy_cred(scm); |
119 | 134 | ||