Commit fbcb43bd authored by Pavel Emelyanov's avatar Pavel Emelyanov

unix: Fix external socket dumping

Collect all unix sockets in a list while dumping to check
whether we've missed something early (at the restore time
it can be already late for roll-back).

Plus, fix the checks for external stream sockets.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 3b0a8e7c
...@@ -44,7 +44,6 @@ struct socket_desc { ...@@ -44,7 +44,6 @@ struct socket_desc {
unsigned int ino; unsigned int ino;
struct socket_desc *next; struct socket_desc *next;
int already_dumped; int already_dumped;
bool external;
}; };
struct unix_sk_desc { struct unix_sk_desc {
...@@ -58,8 +57,11 @@ struct unix_sk_desc { ...@@ -58,8 +57,11 @@ struct unix_sk_desc {
char *name; char *name;
unsigned int nr_icons; unsigned int nr_icons;
unsigned int *icons; unsigned int *icons;
struct list_head list;
}; };
static LIST_HEAD(unix_sockets);
struct unix_sk_listen_icon { struct unix_sk_listen_icon {
unsigned int peer_ino; unsigned int peer_ino;
struct unix_sk_desc *sk_desc; struct unix_sk_desc *sk_desc;
...@@ -332,7 +334,8 @@ static int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p, ...@@ -332,7 +334,8 @@ static int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
* It can be external socket, so we defer dumping * It can be external socket, so we defer dumping
* until all sockets the program owns are processed. * until all sockets the program owns are processed.
*/ */
peer->sd.external = true; if (!peer->sd.already_dumped)
list_add_tail(&peer->list, &unix_sockets);
} }
} else if (ue.state == TCP_ESTABLISHED) { } else if (ue.state == TCP_ESTABLISHED) {
const struct unix_sk_listen_icon *e; const struct unix_sk_listen_icon *e;
...@@ -379,6 +382,7 @@ static int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p, ...@@ -379,6 +382,7 @@ static int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
show_one_unix("Dumping", sk); show_one_unix("Dumping", sk);
show_one_unix_img("Dumped", &ue); show_one_unix_img("Dumped", &ue);
list_del_init(&sk->list);
sk->sd.already_dumped = 1; sk->sd.already_dumped = 1;
return 0; return 0;
...@@ -482,6 +486,7 @@ static int unix_collect_one(const struct unix_diag_msg *m, ...@@ -482,6 +486,7 @@ static int unix_collect_one(const struct unix_diag_msg *m,
d->type = m->udiag_type; d->type = m->udiag_type;
d->state= m->udiag_state; d->state= m->udiag_state;
INIT_LIST_HEAD(&d->list);
if (tb[UNIX_DIAG_PEER]) if (tb[UNIX_DIAG_PEER])
d->peer_ino = *(int *)RTA_DATA(tb[UNIX_DIAG_PEER]); d->peer_ino = *(int *)RTA_DATA(tb[UNIX_DIAG_PEER]);
...@@ -673,34 +678,27 @@ err: ...@@ -673,34 +678,27 @@ err:
int dump_external_sockets(void) int dump_external_sockets(void)
{ {
struct socket_desc *head, *sd; struct unix_sk_desc *sk;
int i, ret = -1; int i, ret = -1;
if (!opts.ext_unix_sk)
return 0;
pr_debug("Dumping external sockets\n"); pr_debug("Dumping external sockets\n");
for (i = 0; i < SK_HASH_SIZE; i++) { list_for_each_entry(sk, &unix_sockets, list) {
head = sockets[i];
if (!head)
continue;
for (sd = head; sd; sd = sd->next) {
struct unix_sk_entry e = { }; struct unix_sk_entry e = { };
struct unix_sk_desc *sk;
if (sd->already_dumped || BUG_ON(sk->sd.already_dumped);
sd->external == false ||
sd->family != AF_UNIX)
continue;
sk = container_of(sd, struct unix_sk_desc, sd); if (!opts.ext_unix_sk) {
show_one_unix("Runaway socket", sk);
goto err;
}
if (sk->type != SOCK_DGRAM) if (sk->type != SOCK_DGRAM) {
continue; show_one_unix("Ext stream not supported", sk);
goto err;
}
e.id = sd->ino; e.id = sk->sd.ino;
e.type = SOCK_DGRAM; e.type = SOCK_DGRAM;
e.state = TCP_LISTEN; e.state = TCP_LISTEN;
e.namelen = sk->namelen; e.namelen = sk->namelen;
...@@ -716,9 +714,6 @@ int dump_external_sockets(void) ...@@ -716,9 +714,6 @@ int dump_external_sockets(void)
goto err; goto err;
show_one_unix_img("Dumped extern", &e); show_one_unix_img("Dumped extern", &e);
sd->already_dumped = 1;
}
} }
return 0; return 0;
...@@ -833,8 +828,6 @@ struct unix_sk_info { ...@@ -833,8 +828,6 @@ struct unix_sk_info {
#define USK_PAIR_MASTER 0x1 #define USK_PAIR_MASTER 0x1
#define USK_PAIR_SLAVE 0x2 #define USK_PAIR_SLAVE 0x2
static LIST_HEAD(unix_sockets);
static struct unix_sk_info *find_unix_sk(int id) static struct unix_sk_info *find_unix_sk(int id)
{ {
struct file_desc *d; struct file_desc *d;
......
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