|
@@ -530,6 +530,16 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
|
|
static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
|
|
static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
|
|
struct msghdr *, size_t, int);
|
|
struct msghdr *, size_t, int);
|
|
|
|
|
|
|
|
+static void unix_set_peek_off(struct sock *sk, int val)
|
|
|
|
+{
|
|
|
|
+ struct unix_sock *u = unix_sk(sk);
|
|
|
|
+
|
|
|
|
+ mutex_lock(&u->readlock);
|
|
|
|
+ sk->sk_peek_off = val;
|
|
|
|
+ mutex_unlock(&u->readlock);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
static const struct proto_ops unix_stream_ops = {
|
|
static const struct proto_ops unix_stream_ops = {
|
|
.family = PF_UNIX,
|
|
.family = PF_UNIX,
|
|
.owner = THIS_MODULE,
|
|
.owner = THIS_MODULE,
|
|
@@ -570,6 +580,7 @@ static const struct proto_ops unix_dgram_ops = {
|
|
.recvmsg = unix_dgram_recvmsg,
|
|
.recvmsg = unix_dgram_recvmsg,
|
|
.mmap = sock_no_mmap,
|
|
.mmap = sock_no_mmap,
|
|
.sendpage = sock_no_sendpage,
|
|
.sendpage = sock_no_sendpage,
|
|
|
|
+ .set_peek_off = unix_set_peek_off,
|
|
};
|
|
};
|
|
|
|
|
|
static const struct proto_ops unix_seqpacket_ops = {
|
|
static const struct proto_ops unix_seqpacket_ops = {
|
|
@@ -591,6 +602,7 @@ static const struct proto_ops unix_seqpacket_ops = {
|
|
.recvmsg = unix_seqpacket_recvmsg,
|
|
.recvmsg = unix_seqpacket_recvmsg,
|
|
.mmap = sock_no_mmap,
|
|
.mmap = sock_no_mmap,
|
|
.sendpage = sock_no_sendpage,
|
|
.sendpage = sock_no_sendpage,
|
|
|
|
+ .set_peek_off = unix_set_peek_off,
|
|
};
|
|
};
|
|
|
|
|
|
static struct proto unix_proto = {
|
|
static struct proto unix_proto = {
|
|
@@ -1756,6 +1768,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
int noblock = flags & MSG_DONTWAIT;
|
|
int noblock = flags & MSG_DONTWAIT;
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
int err;
|
|
int err;
|
|
|
|
+ int peeked, skip;
|
|
|
|
|
|
err = -EOPNOTSUPP;
|
|
err = -EOPNOTSUPP;
|
|
if (flags&MSG_OOB)
|
|
if (flags&MSG_OOB)
|
|
@@ -1769,7 +1782,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- skb = skb_recv_datagram(sk, flags, noblock, &err);
|
|
|
|
|
|
+ skip = sk_peek_offset(sk, flags);
|
|
|
|
+
|
|
|
|
+ skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err);
|
|
if (!skb) {
|
|
if (!skb) {
|
|
unix_state_lock(sk);
|
|
unix_state_lock(sk);
|
|
/* Signal EOF on disconnected non-blocking SEQPACKET socket. */
|
|
/* Signal EOF on disconnected non-blocking SEQPACKET socket. */
|
|
@@ -1786,12 +1801,12 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (msg->msg_name)
|
|
if (msg->msg_name)
|
|
unix_copy_addr(msg, skb->sk);
|
|
unix_copy_addr(msg, skb->sk);
|
|
|
|
|
|
- if (size > skb->len)
|
|
|
|
- size = skb->len;
|
|
|
|
- else if (size < skb->len)
|
|
|
|
|
|
+ if (size > skb->len - skip)
|
|
|
|
+ size = skb->len - skip;
|
|
|
|
+ else if (size < skb->len - skip)
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
|
|
|
|
- err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size);
|
|
|
|
|
|
+ err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size);
|
|
if (err)
|
|
if (err)
|
|
goto out_free;
|
|
goto out_free;
|
|
|
|
|
|
@@ -1808,6 +1823,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
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(siocb->scm, skb);
|
|
|
|
+
|
|
|
|
+ sk_peek_offset_bwd(sk, skb->len);
|
|
} else {
|
|
} else {
|
|
/* It is questionable: on PEEK we could:
|
|
/* It is questionable: on PEEK we could:
|
|
- do not return fds - good, but too simple 8)
|
|
- do not return fds - good, but too simple 8)
|
|
@@ -1821,6 +1838,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
clearly however!
|
|
clearly however!
|
|
|
|
|
|
*/
|
|
*/
|
|
|
|
+
|
|
|
|
+ sk_peek_offset_fwd(sk, size);
|
|
|
|
+
|
|
if (UNIXCB(skb).fp)
|
|
if (UNIXCB(skb).fp)
|
|
siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
|
|
siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
|
|
}
|
|
}
|