Skip to content

Commit

Permalink
scm: Capture the full credentials of the scm sender.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Serge E. Hallyn <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
ebiederm authored and davem330 committed Jun 16, 2010
1 parent b47030c commit 257b535
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 4 deletions.
28 changes: 24 additions & 4 deletions include/net/scm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -42,19 +44,35 @@ 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);
}

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)
Expand Down Expand Up @@ -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)
Expand Down
24 changes: 24 additions & 0 deletions net/core/scm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 257b535

Please sign in to comment.