Skip to content

Commit 7361c36

Browse files
ebiedermdavem330
authored andcommitted
af_unix: Allow credentials to work across user and pid namespaces.
In unix_skb_parms store pointers to struct pid and struct cred instead of raw uid, gid, and pid values, then translate the credentials on reception into values that are meaningful in the receiving processes namespaces. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 257b535 commit 7361c36

File tree

2 files changed

+33
-24
lines changed

2 files changed

+33
-24
lines changed

include/net/af_unix.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ struct unix_address {
2323
};
2424

2525
struct unix_skb_parms {
26-
struct ucred creds; /* Skb credentials */
26+
struct pid *pid; /* Skb credentials */
27+
const struct cred *cred;
2728
struct scm_fp_list *fp; /* Passed files */
2829
#ifdef CONFIG_SECURITY_NETWORK
2930
u32 secid; /* Security ID */
3031
#endif
3132
};
3233

3334
#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb))
34-
#define UNIXCREDS(skb) (&UNIXCB((skb)).creds)
3535
#define UNIXSID(skb) (&UNIXCB((skb)).secid)
3636

3737
#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)

net/unix/af_unix.c

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,18 +1316,20 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
13161316
int i;
13171317

13181318
scm->fp = UNIXCB(skb).fp;
1319-
skb->destructor = sock_wfree;
13201319
UNIXCB(skb).fp = NULL;
13211320

13221321
for (i = scm->fp->count-1; i >= 0; i--)
13231322
unix_notinflight(scm->fp->fp[i]);
13241323
}
13251324

1326-
static void unix_destruct_fds(struct sk_buff *skb)
1325+
static void unix_destruct_scm(struct sk_buff *skb)
13271326
{
13281327
struct scm_cookie scm;
13291328
memset(&scm, 0, sizeof(scm));
1330-
unix_detach_fds(&scm, skb);
1329+
scm.pid = UNIXCB(skb).pid;
1330+
scm.cred = UNIXCB(skb).cred;
1331+
if (UNIXCB(skb).fp)
1332+
unix_detach_fds(&scm, skb);
13311333

13321334
/* Alas, it calls VFS */
13331335
/* So fscking what? fput() had been SMP-safe since the last Summer */
@@ -1350,10 +1352,22 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
13501352

13511353
for (i = scm->fp->count-1; i >= 0; i--)
13521354
unix_inflight(scm->fp->fp[i]);
1353-
skb->destructor = unix_destruct_fds;
13541355
return 0;
13551356
}
13561357

1358+
static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
1359+
{
1360+
int err = 0;
1361+
UNIXCB(skb).pid = get_pid(scm->pid);
1362+
UNIXCB(skb).cred = get_cred(scm->cred);
1363+
UNIXCB(skb).fp = NULL;
1364+
if (scm->fp && send_fds)
1365+
err = unix_attach_fds(scm, skb);
1366+
1367+
skb->destructor = unix_destruct_scm;
1368+
return err;
1369+
}
1370+
13571371
/*
13581372
* Send AF_UNIX data.
13591373
*/
@@ -1410,12 +1424,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
14101424
if (skb == NULL)
14111425
goto out;
14121426

1413-
memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
1414-
if (siocb->scm->fp) {
1415-
err = unix_attach_fds(siocb->scm, skb);
1416-
if (err)
1417-
goto out_free;
1418-
}
1427+
err = unix_scm_to_skb(siocb->scm, skb, true);
1428+
if (err)
1429+
goto out_free;
14191430
unix_get_secdata(siocb->scm, skb);
14201431

14211432
skb_reset_transport_header(skb);
@@ -1585,16 +1596,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
15851596
*/
15861597
size = min_t(int, size, skb_tailroom(skb));
15871598

1588-
memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
1599+
15891600
/* Only send the fds in the first buffer */
1590-
if (siocb->scm->fp && !fds_sent) {
1591-
err = unix_attach_fds(siocb->scm, skb);
1592-
if (err) {
1593-
kfree_skb(skb);
1594-
goto out_err;
1595-
}
1596-
fds_sent = true;
1601+
err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
1602+
if (err) {
1603+
kfree_skb(skb);
1604+
goto out_err;
15971605
}
1606+
fds_sent = true;
15981607

15991608
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
16001609
if (err) {
@@ -1711,7 +1720,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
17111720
siocb->scm = &tmp_scm;
17121721
memset(&tmp_scm, 0, sizeof(tmp_scm));
17131722
}
1714-
siocb->scm->creds = *UNIXCREDS(skb);
1723+
scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
17151724
unix_set_secdata(siocb->scm, skb);
17161725

17171726
if (!(flags & MSG_PEEK)) {
@@ -1860,14 +1869,14 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
18601869

18611870
if (check_creds) {
18621871
/* Never glue messages from different writers */
1863-
if (memcmp(UNIXCREDS(skb), &siocb->scm->creds,
1864-
sizeof(siocb->scm->creds)) != 0) {
1872+
if ((UNIXCB(skb).pid != siocb->scm->pid) ||
1873+
(UNIXCB(skb).cred != siocb->scm->cred)) {
18651874
skb_queue_head(&sk->sk_receive_queue, skb);
18661875
break;
18671876
}
18681877
} else {
18691878
/* Copy credentials */
1870-
siocb->scm->creds = *UNIXCREDS(skb);
1879+
scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
18711880
check_creds = 1;
18721881
}
18731882

0 commit comments

Comments
 (0)