mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
Revert "Scm: Remove unnecessary pid & credential references in Unix socket's send and receive path"
This reverts commit 0856a30409
.
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
473e64ee46
commit
f78a5fda91
@ -53,14 +53,6 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,
|
|||||||
cred_to_ucred(pid, cred, &scm->creds);
|
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)
|
static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
|
||||||
{
|
{
|
||||||
put_pid(scm->pid);
|
put_pid(scm->pid);
|
||||||
@ -78,15 +70,6 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
|
|||||||
__scm_destroy(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,
|
static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
|
||||||
struct scm_cookie *scm)
|
struct scm_cookie *scm)
|
||||||
{
|
{
|
||||||
@ -125,14 +108,15 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
|
|||||||
if (!msg->msg_control) {
|
if (!msg->msg_control) {
|
||||||
if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
|
if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
|
||||||
msg->msg_flags |= MSG_CTRUNC;
|
msg->msg_flags |= MSG_CTRUNC;
|
||||||
if (scm && scm->fp)
|
scm_destroy(scm);
|
||||||
__scm_destroy(scm);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(SOCK_PASSCRED, &sock->flags))
|
if (test_bit(SOCK_PASSCRED, &sock->flags))
|
||||||
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
|
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
|
||||||
|
|
||||||
|
scm_destroy_cred(scm);
|
||||||
|
|
||||||
scm_passec(sock, msg, scm);
|
scm_passec(sock, msg, scm);
|
||||||
|
|
||||||
if (!scm->fp)
|
if (!scm->fp)
|
||||||
|
@ -1378,17 +1378,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
|
|||||||
return max_level;
|
return max_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb,
|
static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
|
||||||
bool send_fds, bool ref)
|
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if (ref) {
|
|
||||||
UNIXCB(skb).pid = get_pid(scm->pid);
|
UNIXCB(skb).pid = get_pid(scm->pid);
|
||||||
UNIXCB(skb).cred = get_cred(scm->cred);
|
UNIXCB(skb).cred = get_cred(scm->cred);
|
||||||
} else {
|
|
||||||
UNIXCB(skb).pid = scm->pid;
|
|
||||||
UNIXCB(skb).cred = scm->cred;
|
|
||||||
}
|
|
||||||
UNIXCB(skb).fp = NULL;
|
UNIXCB(skb).fp = NULL;
|
||||||
if (scm->fp && send_fds)
|
if (scm->fp && send_fds)
|
||||||
err = unix_attach_fds(scm, skb);
|
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 namelen = 0; /* fake GCC */
|
||||||
int err;
|
int err;
|
||||||
unsigned hash;
|
unsigned hash;
|
||||||
struct sk_buff *skb = NULL;
|
struct sk_buff *skb;
|
||||||
long timeo;
|
long timeo;
|
||||||
struct scm_cookie tmp_scm;
|
struct scm_cookie tmp_scm;
|
||||||
int max_level;
|
int max_level;
|
||||||
@ -1454,7 +1448,7 @@ 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, false);
|
err = unix_scm_to_skb(siocb->scm, skb, true);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
max_level = err + 1;
|
max_level = err + 1;
|
||||||
@ -1550,7 +1544,7 @@ restart:
|
|||||||
unix_state_unlock(other);
|
unix_state_unlock(other);
|
||||||
other->sk_data_ready(other, len);
|
other->sk_data_ready(other, len);
|
||||||
sock_put(other);
|
sock_put(other);
|
||||||
scm_release(siocb->scm);
|
scm_destroy(siocb->scm);
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
@ -1560,7 +1554,6 @@ out_free:
|
|||||||
out:
|
out:
|
||||||
if (other)
|
if (other)
|
||||||
sock_put(other);
|
sock_put(other);
|
||||||
if (skb == NULL)
|
|
||||||
scm_destroy(siocb->scm);
|
scm_destroy(siocb->scm);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1573,7 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
|||||||
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 = NULL;
|
struct sk_buff *skb;
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
struct scm_cookie tmp_scm;
|
struct scm_cookie tmp_scm;
|
||||||
bool fds_sent = false;
|
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));
|
size = min_t(int, size, skb_tailroom(skb));
|
||||||
|
|
||||||
|
|
||||||
/* Only send the fds and no ref to pid in the first buffer */
|
/* Only send the fds in the first buffer */
|
||||||
err = unix_scm_to_skb(siocb->scm, skb, !fds_sent, fds_sent);
|
err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
goto out;
|
goto out_err;
|
||||||
}
|
}
|
||||||
max_level = err + 1;
|
max_level = err + 1;
|
||||||
fds_sent = true;
|
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);
|
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
|
||||||
if (err) {
|
if (err) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
goto out;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
unix_state_lock(other);
|
unix_state_lock(other);
|
||||||
@ -1667,9 +1660,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
|||||||
sent += size;
|
sent += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skb)
|
|
||||||
scm_release(siocb->scm);
|
|
||||||
else
|
|
||||||
scm_destroy(siocb->scm);
|
scm_destroy(siocb->scm);
|
||||||
siocb->scm = NULL;
|
siocb->scm = NULL;
|
||||||
|
|
||||||
@ -1683,9 +1673,7 @@ pipe_err:
|
|||||||
send_sig(SIGPIPE, current, 0);
|
send_sig(SIGPIPE, current, 0);
|
||||||
err = -EPIPE;
|
err = -EPIPE;
|
||||||
out_err:
|
out_err:
|
||||||
if (skb == NULL)
|
|
||||||
scm_destroy(siocb->scm);
|
scm_destroy(siocb->scm);
|
||||||
out:
|
|
||||||
siocb->scm = NULL;
|
siocb->scm = NULL;
|
||||||
return sent ? : err;
|
return sent ? : err;
|
||||||
}
|
}
|
||||||
@ -1789,7 +1777,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|||||||
siocb->scm = &tmp_scm;
|
siocb->scm = &tmp_scm;
|
||||||
memset(&tmp_scm, 0, sizeof(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);
|
unix_set_secdata(siocb->scm, skb);
|
||||||
|
|
||||||
if (!(flags & MSG_PEEK)) {
|
if (!(flags & MSG_PEEK)) {
|
||||||
@ -1951,8 +1939,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Copy credentials */
|
/* Copy credentials */
|
||||||
scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid,
|
scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
|
||||||
UNIXCB(skb).cred);
|
|
||||||
check_creds = 1;
|
check_creds = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user