Skip to content

Commit 257b535

Browse files
ebiedermdavem330
authored andcommitted
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>
1 parent b47030c commit 257b535

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

include/net/scm.h

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ struct scm_fp_list {
1919
};
2020

2121
struct scm_cookie {
22+
struct pid *pid; /* Skb credentials */
23+
const struct cred *cred;
2224
struct scm_fp_list *fp; /* Passed files */
2325
struct ucred creds; /* Skb credentials */
2426
#ifdef CONFIG_SECURITY_NETWORK
@@ -42,19 +44,35 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co
4244
{ }
4345
#endif /* CONFIG_SECURITY_NETWORK */
4446

47+
static __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+
55+
static __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+
4565
static __inline__ void scm_destroy(struct scm_cookie *scm)
4666
{
67+
scm_destroy_cred(scm);
4768
if (scm && scm->fp)
4869
__scm_destroy(scm);
4970
}
5071

5172
static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
5273
struct scm_cookie *scm)
5374
{
54-
struct task_struct *p = current;
55-
scm->creds.uid = current_uid();
56-
scm->creds.gid = current_gid();
57-
scm->creds.pid = task_tgid_vnr(p);
75+
scm_set_cred(scm, task_tgid(current), current_cred());
5876
scm->fp = NULL;
5977
unix_get_peersec_dgram(sock, scm);
6078
if (msg->msg_controllen <= 0)
@@ -96,6 +114,8 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
96114
if (test_bit(SOCK_PASSCRED, &sock->flags))
97115
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
98116

117+
scm_destroy_cred(scm);
118+
99119
scm_passec(sock, msg, scm);
100120

101121
if (!scm->fp)

net/core/scm.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,30 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p)
170170
err = scm_check_creds(&p->creds);
171171
if (err)
172172
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+
}
173197
break;
174198
default:
175199
goto error;

0 commit comments

Comments
 (0)