aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2010-06-12 23:32:34 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-16 17:55:56 -0400
commit257b5358b32f17e0603b6ff57b13610b0e02348f (patch)
tree15c4887d45eb6ccfe32f5e67b5c0009e1e8dae6c
parentb47030c71dfd6c8cd5cb6e551b6f7f7cfc96f6a6 (diff)
scm: Capture the full credentials of the scm sender.
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> Acked-by: Serge E. Hallyn <serge@hallyn.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/scm.h28
-rw-r--r--net/core/scm.c24
2 files changed, 48 insertions, 4 deletions
diff --git a/include/net/scm.h b/include/net/scm.h
index 17d9d2e75ff1..31656506d967 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -19,6 +19,8 @@ struct scm_fp_list {
19}; 19};
20 20
21struct scm_cookie { 21struct scm_cookie {
22 struct pid *pid; /* Skb credentials */
23 const struct cred *cred;
22 struct scm_fp_list *fp; /* Passed files */ 24 struct scm_fp_list *fp; /* Passed files */
23 struct ucred creds; /* Skb credentials */ 25 struct ucred creds; /* Skb credentials */
24#ifdef CONFIG_SECURITY_NETWORK 26#ifdef CONFIG_SECURITY_NETWORK
@@ -42,8 +44,27 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
42{ } 44{ }
43#endif /* CONFIG_SECURITY_NETWORK */ 45#endif /* CONFIG_SECURITY_NETWORK */
44 46
47static __inline__ void scm_set_cred(struct scm_cookie *scm,
48 struct pid *pid, const struct cred *cred)
49{
50 scm->pid = get_pid(pid);
51 scm->cred = get_cred(cred);
52 cred_to_ucred(pid, cred, &scm->creds);
53}
54
55static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
56{
57 put_pid(scm->pid);
58 scm->pid = NULL;
59
60 if (scm->cred)
61 put_cred(scm->cred);
62 scm->cred = NULL;
63}
64
45static __inline__ void scm_destroy(struct scm_cookie *scm) 65static __inline__ void scm_destroy(struct scm_cookie *scm)
46{ 66{
67 scm_destroy_cred(scm);
47 if (scm && scm->fp) 68 if (scm && scm->fp)
48 __scm_destroy(scm); 69 __scm_destroy(scm);
49} 70}
@@ -51,10 +72,7 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
51static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, 72static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
52 struct scm_cookie *scm) 73 struct scm_cookie *scm)
53{ 74{
54 struct task_struct *p = current; 75 scm_set_cred(scm, task_tgid(current), current_cred());
55 scm->creds.uid = current_uid();
56 scm->creds.gid = current_gid();
57 scm->creds.pid = task_tgid_vnr(p);
58 scm->fp = NULL; 76 scm->fp = NULL;
59 unix_get_peersec_dgram(sock, scm); 77 unix_get_peersec_dgram(sock, scm);
60 if (msg->msg_controllen <= 0) 78 if (msg->msg_controllen <= 0)
@@ -96,6 +114,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
96 if (test_bit(SOCK_PASSCRED, &sock->flags)) 114 if (test_bit(SOCK_PASSCRED, &sock->flags))
97 put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); 115 put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
98 116
117 scm_destroy_cred(scm);
118
99 scm_passec(sock, msg, scm); 119 scm_passec(sock, msg, scm);
100 120
101 if (!scm->fp) 121 if (!scm->fp)
diff --git a/net/core/scm.c b/net/core/scm.c
index b88f6f9d0b97..681c976307b5 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)
170 err = scm_check_creds(&p->creds); 170 err = scm_check_creds(&p->creds);
171 if (err) 171 if (err)
172 goto error; 172 goto error;
173
174 if (pid_vnr(p->pid) != p->creds.pid) {
175 struct pid *pid;
176 err = -ESRCH;
177 pid = find_get_pid(p->creds.pid);
178 if (!pid)
179 goto error;
180 put_pid(p->pid);
181 p->pid = pid;
182 }
183
184 if ((p->cred->euid != p->creds.uid) ||
185 (p->cred->egid != p->creds.gid)) {
186 struct cred *cred;
187 err = -ENOMEM;
188 cred = prepare_creds();
189 if (!cred)
190 goto error;
191
192 cred->uid = cred->euid = p->creds.uid;
193 cred->gid = cred->egid = p->creds.uid;
194 put_cred(p->cred);
195 p->cred = cred;
196 }
173 break; 197 break;
174 default: 198 default:
175 goto error; 199 goto error;