Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 202978
b: refs/heads/master
c: 7361c36
h: refs/heads/master
v: v3
  • Loading branch information
Eric W. Biederman authored and David S. Miller committed Jun 16, 2010
1 parent 00e57ac commit 26b4d93
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 25 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 257b5358b32f17e0603b6ff57b13610b0e02348f
refs/heads/master: 7361c36c5224519b258219fe3d0e8abc865d8134
4 changes: 2 additions & 2 deletions trunk/include/net/af_unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ 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 */
#endif
};

#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)
Expand Down
53 changes: 31 additions & 22 deletions trunk/net/unix/af_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -1316,18 +1316,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 */
Expand All @@ -1350,10 +1352,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.
*/
Expand Down Expand Up @@ -1410,12 +1424,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);
Expand Down Expand Up @@ -1585,16 +1596,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) {
Expand Down Expand Up @@ -1711,7 +1720,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)) {
Expand Down Expand Up @@ -1860,14 +1869,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;
}

Expand Down

0 comments on commit 26b4d93

Please sign in to comment.