Commit fb5a5671 authored by Pavel Emelyanov's avatar Pavel Emelyanov

sock: Do strict socket family checks when looking up collected socket

We hash socket with inode and family, but search only by inode. Well,
yes, family should match, since all sockets are in one sockfs in kernel,
but let's make sure _we_ did things right by checking the family as well.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent da2ebabf
......@@ -47,9 +47,10 @@ extern char *sktype2s(u32 t);
extern char *skproto2s(u32 p);
extern char *skstate2s(u32 state);
extern struct socket_desc *lookup_socket(int ino);
extern struct socket_desc *lookup_socket(int ino, int family);
extern int dump_one_inet(struct fd_parms *p, int lfd, const struct cr_fdset *set);
extern int dump_one_inet6(struct fd_parms *p, int lfd, const struct cr_fdset *set);
extern int dump_one_unix(struct fd_parms *p, int lfd, const struct cr_fdset *set);
extern int inet_collect_one(struct nlmsghdr *h, int family, int type, int proto);
......
......@@ -168,14 +168,14 @@ err:
return NULL;
}
static int dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p)
static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int family)
{
struct inet_sk_desc *sk;
InetSkEntry ie = INET_SK_ENTRY__INIT;
SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
int ret = -1;
sk = (struct inet_sk_desc *)lookup_socket(p->stat.st_ino);
sk = (struct inet_sk_desc *)lookup_socket(p->stat.st_ino, family);
if (!sk) {
sk = gen_uncon_sk(lfd, p);
if (!sk)
......@@ -189,7 +189,7 @@ static int dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p)
ie.id = id;
ie.ino = sk->sd.ino;
ie.family = sk->sd.family;
ie.family = family;
ie.type = sk->type;
ie.proto = sk->proto;
ie.state = sk->state;
......@@ -247,6 +247,11 @@ err:
return ret;
}
static int dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p)
{
return do_dump_one_inet_fd(lfd, id, p, PF_INET);
}
static const struct fdtype_ops inet_dump_ops = {
.type = FD_TYPES__INETSK,
.dump = dump_one_inet_fd,
......@@ -257,6 +262,21 @@ int dump_one_inet(struct fd_parms *p, int lfd, const struct cr_fdset *set)
return do_dump_gen_file(p, lfd, &inet_dump_ops, set);
}
static int dump_one_inet6_fd(int lfd, u32 id, const struct fd_parms *p)
{
return do_dump_one_inet_fd(lfd, id, p, PF_INET6);
}
static const struct fdtype_ops inet6_dump_ops = {
.type = FD_TYPES__INETSK,
.dump = dump_one_inet6_fd,
};
int dump_one_inet6(struct fd_parms *p, int lfd, const struct cr_fdset *set)
{
return do_dump_gen_file(p, lfd, &inet6_dump_ops, set);
}
int inet_collect_one(struct nlmsghdr *h, int family, int type, int proto)
{
struct inet_sk_desc *d;
......
......@@ -39,7 +39,7 @@ static int dump_one_packet_fd(int lfd, u32 id, const struct fd_parms *p)
SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
struct packet_sock_desc *sd;
sd = (struct packet_sock_desc *)lookup_socket(p->stat.st_ino);
sd = (struct packet_sock_desc *)lookup_socket(p->stat.st_ino, PF_PACKET);
if (sd < 0)
return -1;
......
......@@ -115,7 +115,7 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
UnixSkEntry ue = UNIX_SK_ENTRY__INIT;
SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino);
sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino, PF_UNIX);
if (!sk)
goto err;
......@@ -141,7 +141,7 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
if (ue.peer) {
struct unix_sk_desc *peer;
peer = (struct unix_sk_desc *)lookup_socket(ue.peer);
peer = (struct unix_sk_desc *)lookup_socket(ue.peer, PF_UNIX);
if (!peer) {
pr_err("Unix socket %#x without peer %#x\n",
ue.ino, ue.peer);
......
......@@ -31,13 +31,17 @@
static struct socket_desc *sockets[SK_HASH_SIZE];
struct socket_desc *lookup_socket(int ino)
struct socket_desc *lookup_socket(int ino, int family)
{
struct socket_desc *sd;
pr_debug("\tSearching for socket %x (family %d)\n", ino, family);
for (sd = sockets[ino % SK_HASH_SIZE]; sd; sd = sd->next)
if (sd->ino == ino)
if (sd->ino == ino) {
BUG_ON(sd->family != family);
return sd;
}
return NULL;
}
......@@ -133,8 +137,9 @@ int dump_socket(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset)
case AF_UNIX:
return dump_one_unix(p, lfd, cr_fdset);
case AF_INET:
case AF_INET6:
return dump_one_inet(p, lfd, cr_fdset);
case AF_INET6:
return dump_one_inet6(p, lfd, cr_fdset);
case AF_PACKET:
return dump_one_packet_sk(p, lfd, cr_fdset);
default:
......
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