Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f78a5fda authored by David S. Miller's avatar David S. Miller
Browse files

Revert "Scm: Remove unnecessary pid & credential references in Unix socket's send and receive path"



This reverts commit 0856a304.

As requested by Eric Dumazet, it has various ref-counting
problems and has introduced regressions.  Eric will add
a more suitable version of this performance fix.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 473e64ee
Loading
Loading
Loading
Loading
+3 −19
Original line number Diff line number Diff line
@@ -53,14 +53,6 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,
	cred_to_ucred(pid, cred, &scm->creds);
}

static __inline__ void scm_set_cred_noref(struct scm_cookie *scm,
				    struct pid *pid, const struct cred *cred)
{
	scm->pid  = pid;
	scm->cred = cred;
	cred_to_ucred(pid, cred, &scm->creds);
}

static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
{
	put_pid(scm->pid);
@@ -78,15 +70,6 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
		__scm_destroy(scm);
}

static __inline__ void scm_release(struct scm_cookie *scm)
{
	/* keep ref on pid and cred */
	scm->pid = NULL;
	scm->cred = NULL;
	if (scm->fp)
		__scm_destroy(scm);
}

static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
			       struct scm_cookie *scm)
{
@@ -125,14 +108,15 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
	if (!msg->msg_control) {
		if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
			msg->msg_flags |= MSG_CTRUNC;
		if (scm && scm->fp)
			__scm_destroy(scm);
		scm_destroy(scm);
		return;
	}

	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)
+16 −29
Original line number Diff line number Diff line
@@ -1378,17 +1378,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
	return max_level;
}

static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb,
			   bool send_fds, bool ref)
static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
{
	int err = 0;
	if (ref) {
	UNIXCB(skb).pid  = get_pid(scm->pid);
	UNIXCB(skb).cred = get_cred(scm->cred);
	} else {
		UNIXCB(skb).pid  = scm->pid;
		UNIXCB(skb).cred = scm->cred;
	}
	UNIXCB(skb).fp = NULL;
	if (scm->fp && send_fds)
		err = unix_attach_fds(scm, skb);
@@ -1413,7 +1407,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
	int namelen = 0; /* fake GCC */
	int err;
	unsigned hash;
	struct sk_buff *skb = NULL;
	struct sk_buff *skb;
	long timeo;
	struct scm_cookie tmp_scm;
	int max_level;
@@ -1454,7 +1448,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
	if (skb == NULL)
		goto out;

	err = unix_scm_to_skb(siocb->scm, skb, true, false);
	err = unix_scm_to_skb(siocb->scm, skb, true);
	if (err < 0)
		goto out_free;
	max_level = err + 1;
@@ -1550,7 +1544,7 @@ restart:
	unix_state_unlock(other);
	other->sk_data_ready(other, len);
	sock_put(other);
	scm_release(siocb->scm);
	scm_destroy(siocb->scm);
	return len;

out_unlock:
@@ -1560,7 +1554,6 @@ out_free:
out:
	if (other)
		sock_put(other);
	if (skb == NULL)
	scm_destroy(siocb->scm);
	return err;
}
@@ -1573,7 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
	struct sock *sk = sock->sk;
	struct sock *other = NULL;
	int err, size;
	struct sk_buff *skb = NULL;
	struct sk_buff *skb;
	int sent = 0;
	struct scm_cookie tmp_scm;
	bool fds_sent = false;
@@ -1638,11 +1631,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
		size = min_t(int, size, skb_tailroom(skb));


		/* Only send the fds and no ref to pid in the first buffer */
		err = unix_scm_to_skb(siocb->scm, skb, !fds_sent, fds_sent);
		/* Only send the fds in the first buffer */
		err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
		if (err < 0) {
			kfree_skb(skb);
			goto out;
			goto out_err;
		}
		max_level = err + 1;
		fds_sent = true;
@@ -1650,7 +1643,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
		err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
		if (err) {
			kfree_skb(skb);
			goto out;
			goto out_err;
		}

		unix_state_lock(other);
@@ -1667,9 +1660,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
		sent += size;
	}

	if (skb)
		scm_release(siocb->scm);
	else
	scm_destroy(siocb->scm);
	siocb->scm = NULL;

@@ -1683,9 +1673,7 @@ pipe_err:
		send_sig(SIGPIPE, current, 0);
	err = -EPIPE;
out_err:
	if (skb == NULL)
	scm_destroy(siocb->scm);
out:
	siocb->scm = NULL;
	return sent ? : err;
}
@@ -1789,7 +1777,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
		siocb->scm = &tmp_scm;
		memset(&tmp_scm, 0, sizeof(tmp_scm));
	}
	scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
	scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
	unix_set_secdata(siocb->scm, skb);

	if (!(flags & MSG_PEEK)) {
@@ -1951,8 +1939,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
			}
		} else {
			/* Copy credentials */
			scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid,
					   UNIXCB(skb).cred);
			scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
			check_creds = 1;
		}