Commit 7cc05662 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David S. Miller

net: remove sock_iocb

The sock_iocb structure is allocate on stack for each read/write-like
operation on sockets, and contains various fields of which only the
embedded msghdr and sometimes a pointer to the scm_cookie is ever used.
Get rid of the sock_iocb and put a msghdr directly on the stack and pass
the scm_cookie explicitly to netlink_mmap_sendmsg.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a154e6f6
...@@ -1374,29 +1374,6 @@ void sk_prot_clear_portaddr_nulls(struct sock *sk, int size); ...@@ -1374,29 +1374,6 @@ void sk_prot_clear_portaddr_nulls(struct sock *sk, int size);
#define SOCK_BINDADDR_LOCK 4 #define SOCK_BINDADDR_LOCK 4
#define SOCK_BINDPORT_LOCK 8 #define SOCK_BINDPORT_LOCK 8
/* sock_iocb: used to kick off async processing of socket ios */
struct sock_iocb {
struct list_head list;
int flags;
int size;
struct socket *sock;
struct sock *sk;
struct scm_cookie *scm;
struct msghdr *msg, async_msg;
struct kiocb *kiocb;
};
static inline struct sock_iocb *kiocb_to_siocb(struct kiocb *iocb)
{
return (struct sock_iocb *)iocb->private;
}
static inline struct kiocb *siocb_to_kiocb(struct sock_iocb *si)
{
return si->kiocb;
}
struct socket_alloc { struct socket_alloc {
struct socket socket; struct socket socket;
struct inode vfs_inode; struct inode vfs_inode;
......
...@@ -695,7 +695,7 @@ static void netlink_ring_setup_skb(struct sk_buff *skb, struct sock *sk, ...@@ -695,7 +695,7 @@ static void netlink_ring_setup_skb(struct sk_buff *skb, struct sock *sk,
static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg,
u32 dst_portid, u32 dst_group, u32 dst_portid, u32 dst_group,
struct sock_iocb *siocb) struct scm_cookie *scm)
{ {
struct netlink_sock *nlk = nlk_sk(sk); struct netlink_sock *nlk = nlk_sk(sk);
struct netlink_ring *ring; struct netlink_ring *ring;
...@@ -741,7 +741,7 @@ static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg, ...@@ -741,7 +741,7 @@ static int netlink_mmap_sendmsg(struct sock *sk, struct msghdr *msg,
NETLINK_CB(skb).portid = nlk->portid; NETLINK_CB(skb).portid = nlk->portid;
NETLINK_CB(skb).dst_group = dst_group; NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).creds = siocb->scm->creds; NETLINK_CB(skb).creds = scm->creds;
err = security_netlink_send(sk, skb); err = security_netlink_send(sk, skb);
if (err) { if (err) {
...@@ -820,7 +820,7 @@ static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb) ...@@ -820,7 +820,7 @@ static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb)
#define netlink_tx_is_mmaped(sk) false #define netlink_tx_is_mmaped(sk) false
#define netlink_mmap sock_no_mmap #define netlink_mmap sock_no_mmap
#define netlink_poll datagram_poll #define netlink_poll datagram_poll
#define netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, siocb) 0 #define netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, scm) 0
#endif /* CONFIG_NETLINK_MMAP */ #endif /* CONFIG_NETLINK_MMAP */
static void netlink_skb_destructor(struct sk_buff *skb) static void netlink_skb_destructor(struct sk_buff *skb)
...@@ -2259,7 +2259,6 @@ static void netlink_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb) ...@@ -2259,7 +2259,6 @@ static void netlink_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct msghdr *msg, size_t len) struct msghdr *msg, size_t len)
{ {
struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct netlink_sock *nlk = nlk_sk(sk); struct netlink_sock *nlk = nlk_sk(sk);
DECLARE_SOCKADDR(struct sockaddr_nl *, addr, msg->msg_name); DECLARE_SOCKADDR(struct sockaddr_nl *, addr, msg->msg_name);
...@@ -2273,10 +2272,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -2273,10 +2272,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (msg->msg_flags&MSG_OOB) if (msg->msg_flags&MSG_OOB)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (NULL == siocb->scm) err = scm_send(sock, msg, &scm, true);
siocb->scm = &scm;
err = scm_send(sock, msg, siocb->scm, true);
if (err < 0) if (err < 0)
return err; return err;
...@@ -2305,7 +2301,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -2305,7 +2301,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (netlink_tx_is_mmaped(sk) && if (netlink_tx_is_mmaped(sk) &&
msg->msg_iter.iov->iov_base == NULL) { msg->msg_iter.iov->iov_base == NULL) {
err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group,
siocb); &scm);
goto out; goto out;
} }
...@@ -2319,7 +2315,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -2319,7 +2315,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
NETLINK_CB(skb).portid = nlk->portid; NETLINK_CB(skb).portid = nlk->portid;
NETLINK_CB(skb).dst_group = dst_group; NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).creds = siocb->scm->creds; NETLINK_CB(skb).creds = scm.creds;
NETLINK_CB(skb).flags = netlink_skb_flags; NETLINK_CB(skb).flags = netlink_skb_flags;
err = -EFAULT; err = -EFAULT;
...@@ -2341,7 +2337,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -2341,7 +2337,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT); err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT);
out: out:
scm_destroy(siocb->scm); scm_destroy(&scm);
return err; return err;
} }
...@@ -2349,7 +2345,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -2349,7 +2345,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
struct msghdr *msg, size_t len, struct msghdr *msg, size_t len,
int flags) int flags)
{ {
struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
struct scm_cookie scm; struct scm_cookie scm;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct netlink_sock *nlk = nlk_sk(sk); struct netlink_sock *nlk = nlk_sk(sk);
...@@ -2412,11 +2407,8 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -2412,11 +2407,8 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
if (nlk->flags & NETLINK_RECV_PKTINFO) if (nlk->flags & NETLINK_RECV_PKTINFO)
netlink_cmsg_recv_pktinfo(msg, skb); netlink_cmsg_recv_pktinfo(msg, skb);
if (NULL == siocb->scm) { memset(&scm, 0, sizeof(scm));
memset(&scm, 0, sizeof(scm)); scm.creds = *NETLINK_CREDS(skb);
siocb->scm = &scm;
}
siocb->scm->creds = *NETLINK_CREDS(skb);
if (flags & MSG_TRUNC) if (flags & MSG_TRUNC)
copied = data_skb->len; copied = data_skb->len;
...@@ -2431,7 +2423,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -2431,7 +2423,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
} }
} }
scm_recv(sock, msg, siocb->scm, flags); scm_recv(sock, msg, &scm, flags);
out: out:
netlink_rcv_wake(sk); netlink_rcv_wake(sk);
return err ? : copied; return err ? : copied;
......
...@@ -613,13 +613,6 @@ EXPORT_SYMBOL(__sock_tx_timestamp); ...@@ -613,13 +613,6 @@ EXPORT_SYMBOL(__sock_tx_timestamp);
static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock, static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size) struct msghdr *msg, size_t size)
{ {
struct sock_iocb *si = kiocb_to_siocb(iocb);
si->sock = sock;
si->scm = NULL;
si->msg = msg;
si->size = size;
return sock->ops->sendmsg(iocb, sock, msg, size); return sock->ops->sendmsg(iocb, sock, msg, size);
} }
...@@ -635,11 +628,9 @@ static int do_sock_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -635,11 +628,9 @@ static int do_sock_sendmsg(struct socket *sock, struct msghdr *msg,
size_t size, bool nosec) size_t size, bool nosec)
{ {
struct kiocb iocb; struct kiocb iocb;
struct sock_iocb siocb;
int ret; int ret;
init_sync_kiocb(&iocb, NULL); init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
ret = nosec ? __sock_sendmsg_nosec(&iocb, sock, msg, size) : ret = nosec ? __sock_sendmsg_nosec(&iocb, sock, msg, size) :
__sock_sendmsg(&iocb, sock, msg, size); __sock_sendmsg(&iocb, sock, msg, size);
if (-EIOCBQUEUED == ret) if (-EIOCBQUEUED == ret)
...@@ -756,14 +747,6 @@ EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops); ...@@ -756,14 +747,6 @@ EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock, static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags) struct msghdr *msg, size_t size, int flags)
{ {
struct sock_iocb *si = kiocb_to_siocb(iocb);
si->sock = sock;
si->scm = NULL;
si->msg = msg;
si->size = size;
si->flags = flags;
return sock->ops->recvmsg(iocb, sock, msg, size, flags); return sock->ops->recvmsg(iocb, sock, msg, size, flags);
} }
...@@ -779,11 +762,9 @@ int sock_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -779,11 +762,9 @@ int sock_recvmsg(struct socket *sock, struct msghdr *msg,
size_t size, int flags) size_t size, int flags)
{ {
struct kiocb iocb; struct kiocb iocb;
struct sock_iocb siocb;
int ret; int ret;
init_sync_kiocb(&iocb, NULL); init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
ret = __sock_recvmsg(&iocb, sock, msg, size, flags); ret = __sock_recvmsg(&iocb, sock, msg, size, flags);
if (-EIOCBQUEUED == ret) if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb); ret = wait_on_sync_kiocb(&iocb);
...@@ -795,11 +776,9 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg, ...@@ -795,11 +776,9 @@ static int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
size_t size, int flags) size_t size, int flags)
{ {
struct kiocb iocb; struct kiocb iocb;
struct sock_iocb siocb;
int ret; int ret;
init_sync_kiocb(&iocb, NULL); init_sync_kiocb(&iocb, NULL);
iocb.private = &siocb;
ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags); ret = __sock_recvmsg_nosec(&iocb, sock, msg, size, flags);
if (-EIOCBQUEUED == ret) if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&iocb); ret = wait_on_sync_kiocb(&iocb);
...@@ -866,14 +845,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, ...@@ -866,14 +845,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
return sock->ops->splice_read(sock, ppos, pipe, len, flags); return sock->ops->splice_read(sock, ppos, pipe, len, flags);
} }
static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
struct sock_iocb *siocb)
{
siocb->kiocb = iocb;
iocb->private = siocb;
return siocb;
}
static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
struct file *file, const struct iovec *iov, struct file *file, const struct iovec *iov,
unsigned long nr_segs) unsigned long nr_segs)
...@@ -893,7 +864,7 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, ...@@ -893,7 +864,7 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos) unsigned long nr_segs, loff_t pos)
{ {
struct sock_iocb siocb, *x; struct msghdr msg;
if (pos != 0) if (pos != 0)
return -ESPIPE; return -ESPIPE;
...@@ -901,11 +872,7 @@ static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, ...@@ -901,11 +872,7 @@ static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
if (iocb->ki_nbytes == 0) /* Match SYS5 behaviour */ if (iocb->ki_nbytes == 0) /* Match SYS5 behaviour */
return 0; return 0;
return do_sock_read(&msg, iocb, iocb->ki_filp, iov, nr_segs);
x = alloc_sock_iocb(iocb, &siocb);
if (!x)
return -ENOMEM;
return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
} }
static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
...@@ -929,16 +896,12 @@ static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, ...@@ -929,16 +896,12 @@ static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos) unsigned long nr_segs, loff_t pos)
{ {
struct sock_iocb siocb, *x; struct msghdr msg;
if (pos != 0) if (pos != 0)
return -ESPIPE; return -ESPIPE;
x = alloc_sock_iocb(iocb, &siocb); return do_sock_write(&msg, iocb, iocb->ki_filp, iov, nr_segs);
if (!x)
return -ENOMEM;
return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, iov, nr_segs);
} }
/* /*
......
...@@ -1445,7 +1445,6 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock, ...@@ -1445,7 +1445,6 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,
static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct msghdr *msg, size_t len) struct msghdr *msg, size_t len)
{ {
struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
struct unix_sock *u = unix_sk(sk); struct unix_sock *u = unix_sk(sk);
...@@ -1456,14 +1455,12 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1456,14 +1455,12 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
unsigned int hash; unsigned int hash;
struct sk_buff *skb; struct sk_buff *skb;
long timeo; long timeo;
struct scm_cookie tmp_scm; struct scm_cookie scm;
int max_level; int max_level;
int data_len = 0; int data_len = 0;
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
wait_for_unix_gc(); wait_for_unix_gc();
err = scm_send(sock, msg, siocb->scm, false); err = scm_send(sock, msg, &scm, false);
if (err < 0) if (err < 0)
return err; return err;
...@@ -1507,11 +1504,11 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1507,11 +1504,11 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (skb == NULL) if (skb == NULL)
goto out; goto out;
err = unix_scm_to_skb(siocb->scm, skb, true); err = unix_scm_to_skb(&scm, skb, true);
if (err < 0) if (err < 0)
goto out_free; goto out_free;
max_level = err + 1; max_level = err + 1;
unix_get_secdata(siocb->scm, skb); unix_get_secdata(&scm, skb);
skb_put(skb, len - data_len); skb_put(skb, len - data_len);
skb->data_len = data_len; skb->data_len = data_len;
...@@ -1606,7 +1603,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1606,7 +1603,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
unix_state_unlock(other); unix_state_unlock(other);
other->sk_data_ready(other); other->sk_data_ready(other);
sock_put(other); sock_put(other);
scm_destroy(siocb->scm); scm_destroy(&scm);
return len; return len;
out_unlock: out_unlock:
...@@ -1616,7 +1613,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1616,7 +1613,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
out: out:
if (other) if (other)
sock_put(other); sock_put(other);
scm_destroy(siocb->scm); scm_destroy(&scm);
return err; return err;
} }
...@@ -1628,21 +1625,18 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1628,21 +1625,18 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct msghdr *msg, size_t len) struct msghdr *msg, size_t len)
{ {
struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct sock *other = NULL; struct sock *other = NULL;
int err, size; int err, size;
struct sk_buff *skb; struct sk_buff *skb;
int sent = 0; int sent = 0;
struct scm_cookie tmp_scm; struct scm_cookie scm;
bool fds_sent = false; bool fds_sent = false;
int max_level; int max_level;
int data_len; int data_len;
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
wait_for_unix_gc(); wait_for_unix_gc();
err = scm_send(sock, msg, siocb->scm, false); err = scm_send(sock, msg, &scm, false);
if (err < 0) if (err < 0)
return err; return err;
...@@ -1683,7 +1677,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1683,7 +1677,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto out_err; goto out_err;
/* Only send the fds in the first buffer */ /* Only send the fds in the first buffer */
err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); err = unix_scm_to_skb(&scm, skb, !fds_sent);
if (err < 0) { if (err < 0) {
kfree_skb(skb); kfree_skb(skb);
goto out_err; goto out_err;
...@@ -1715,8 +1709,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1715,8 +1709,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
sent += size; sent += size;
} }
scm_destroy(siocb->scm); scm_destroy(&scm);
siocb->scm = NULL;
return sent; return sent;
...@@ -1728,8 +1721,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -1728,8 +1721,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
send_sig(SIGPIPE, current, 0); send_sig(SIGPIPE, current, 0);
err = -EPIPE; err = -EPIPE;
out_err: out_err:
scm_destroy(siocb->scm); scm_destroy(&scm);
siocb->scm = NULL;
return sent ? : err; return sent ? : err;
} }
...@@ -1778,8 +1770,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1778,8 +1770,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, struct msghdr *msg, size_t size,
int flags) int flags)
{ {
struct sock_iocb *siocb = kiocb_to_siocb(iocb); struct scm_cookie scm;
struct scm_cookie tmp_scm;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct unix_sock *u = unix_sk(sk); struct unix_sock *u = unix_sk(sk);
int noblock = flags & MSG_DONTWAIT; int noblock = flags & MSG_DONTWAIT;
...@@ -1831,16 +1822,14 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1831,16 +1822,14 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
if (sock_flag(sk, SOCK_RCVTSTAMP)) if (sock_flag(sk, SOCK_RCVTSTAMP))
__sock_recv_timestamp(msg, sk, skb); __sock_recv_timestamp(msg, sk, skb);
if (!siocb->scm) { memset(&scm, 0, sizeof(scm));
siocb->scm = &tmp_scm;
memset(&tmp_scm, 0, sizeof(tmp_scm)); scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
} unix_set_secdata(&scm, skb);
scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
unix_set_secdata(siocb->scm, skb);
if (!(flags & MSG_PEEK)) { if (!(flags & MSG_PEEK)) {
if (UNIXCB(skb).fp) if (UNIXCB(skb).fp)
unix_detach_fds(siocb->scm, skb); unix_detach_fds(&scm, skb);
sk_peek_offset_bwd(sk, skb->len); sk_peek_offset_bwd(sk, skb->len);
} else { } else {
...@@ -1860,11 +1849,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1860,11 +1849,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
sk_peek_offset_fwd(sk, size); sk_peek_offset_fwd(sk, size);
if (UNIXCB(skb).fp) if (UNIXCB(skb).fp)
siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); scm.fp = scm_fp_dup(UNIXCB(skb).fp);
} }
err = (flags & MSG_TRUNC) ? skb->len - skip : size; err = (flags & MSG_TRUNC) ? skb->len - skip : size;
scm_recv(sock, msg, siocb->scm, flags); scm_recv(sock, msg, &scm, flags);
out_free: out_free:
skb_free_datagram(sk, skb); skb_free_datagram(sk, skb);
...@@ -1915,8 +1904,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1915,8 +1904,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, struct msghdr *msg, size_t size,
int flags) int flags)
{ {
struct sock_iocb *siocb = kiocb_to_siocb(iocb); struct scm_cookie scm;
struct scm_cookie tmp_scm;
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct unix_sock *u = unix_sk(sk); struct unix_sock *u = unix_sk(sk);
DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name); DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);
...@@ -1943,10 +1931,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1943,10 +1931,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
* while sleeps in memcpy_tomsg * while sleeps in memcpy_tomsg
*/ */
if (!siocb->scm) { memset(&scm, 0, sizeof(scm));
siocb->scm = &tmp_scm;
memset(&tmp_scm, 0, sizeof(tmp_scm));
}
err = mutex_lock_interruptible(&u->readlock); err = mutex_lock_interruptible(&u->readlock);
if (unlikely(err)) { if (unlikely(err)) {
...@@ -2012,13 +1997,13 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -2012,13 +1997,13 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
if (check_creds) { if (check_creds) {
/* Never glue messages from different writers */ /* Never glue messages from different writers */
if ((UNIXCB(skb).pid != siocb->scm->pid) || if ((UNIXCB(skb).pid != scm.pid) ||
!uid_eq(UNIXCB(skb).uid, siocb->scm->creds.uid) || !uid_eq(UNIXCB(skb).uid, scm.creds.uid) ||
!gid_eq(UNIXCB(skb).gid, siocb->scm->creds.gid)) !gid_eq(UNIXCB(skb).gid, scm.creds.gid))
break; break;
} else if (test_bit(SOCK_PASSCRED, &sock->flags)) { } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
/* Copy credentials */ /* Copy credentials */
scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
check_creds = 1; check_creds = 1;
} }
...@@ -2045,7 +2030,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -2045,7 +2030,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
sk_peek_offset_bwd(sk, chunk); sk_peek_offset_bwd(sk, chunk);
if (UNIXCB(skb).fp) if (UNIXCB(skb).fp)
unix_detach_fds(siocb->scm, skb); unix_detach_fds(&scm, skb);
if (unix_skb_len(skb)) if (unix_skb_len(skb))
break; break;
...@@ -2053,13 +2038,13 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -2053,13 +2038,13 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
skb_unlink(skb, &sk->sk_receive_queue); skb_unlink(skb, &sk->sk_receive_queue);
consume_skb(skb); consume_skb(skb);
if (siocb->scm->fp) if (scm.fp)
break; break;
} else { } else {
/* It is questionable, see note in unix_dgram_recvmsg. /* It is questionable, see note in unix_dgram_recvmsg.
*/ */
if (UNIXCB(skb).fp) if (UNIXCB(skb).fp)
siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); scm.fp = scm_fp_dup(UNIXCB(skb).fp);
sk_peek_offset_fwd(sk, chunk); sk_peek_offset_fwd(sk, chunk);
...@@ -2068,7 +2053,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -2068,7 +2053,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
} while (size); } while (size);
mutex_unlock(&u->readlock); mutex_unlock(&u->readlock);
scm_recv(sock, msg, siocb->scm, flags); scm_recv(sock, msg, &scm, flags);
out: out:
return copied ? : err; return copied ? : err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment