Skip to content

Commit 4069329

Browse files
cyyzerogregkh
authored andcommitted
tools/accounting: handle truncated taskstats netlink messages
commit cc82b3d upstream. procacct and getdelays use a fixed receive buffer for taskstats generic netlink messages. A multi-threaded process exit can emit a single PID+TGID notification large enough to exceed that buffer on newer kernels. Switch to recvmsg() so MSG_TRUNC is detected explicitly, increase the message buffer size, and report truncated datagrams clearly instead of misparsing them as fatal netlink errors. Also print the taskstats version in debug output to make version mismatches easier to diagnose while inspecting taskstats traffic. Link: https://lkml.kernel.org/r/520308bb4cbbaf8dc2c7296b5f60f11e12fb30a5.1774810498.git.cyyzero16@gmail.com Signed-off-by: Yiyang Chen <cyyzero16@gmail.com> Cc: Balbir Singh <bsingharora@gmail.com> Cc: Dr. Thomas Orgis <thomas.orgis@uni-hamburg.de> Cc: Fan Yu <fan.yu9@zte.com.cn> Cc: Wang Yaxin <wang.yaxin@zte.com.cn> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent d61482b commit 4069329

2 files changed

Lines changed: 73 additions & 8 deletions

File tree

tools/accounting/getdelays.c

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ int print_task_context_switch_counts;
5959
}
6060

6161
/* Maximum size of response requested or message sent */
62-
#define MAX_MSG_SIZE 1024
62+
#define MAX_MSG_SIZE 2048
6363
/* Maximum number of cpus expected to be specified in a cpumask */
6464
#define MAX_CPUS 32
6565

@@ -114,6 +114,32 @@ static int create_nl_socket(int protocol)
114114
return -1;
115115
}
116116

117+
static int recv_taskstats_msg(int sd, struct msgtemplate *msg)
118+
{
119+
struct sockaddr_nl nladdr;
120+
struct iovec iov = {
121+
.iov_base = msg,
122+
.iov_len = sizeof(*msg),
123+
};
124+
struct msghdr hdr = {
125+
.msg_name = &nladdr,
126+
.msg_namelen = sizeof(nladdr),
127+
.msg_iov = &iov,
128+
.msg_iovlen = 1,
129+
};
130+
int ret;
131+
132+
ret = recvmsg(sd, &hdr, 0);
133+
if (ret < 0)
134+
return -1;
135+
if (hdr.msg_flags & MSG_TRUNC) {
136+
errno = EMSGSIZE;
137+
return -1;
138+
}
139+
140+
return ret;
141+
}
142+
117143

118144
static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
119145
__u8 genl_cmd, __u16 nla_type,
@@ -465,12 +491,16 @@ int main(int argc, char *argv[])
465491
}
466492

467493
do {
468-
rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
494+
rep_len = recv_taskstats_msg(nl_sd, &msg);
469495
PRINTF("received %d bytes\n", rep_len);
470496

471497
if (rep_len < 0) {
472-
fprintf(stderr, "nonfatal reply error: errno %d\n",
473-
errno);
498+
if (errno == EMSGSIZE)
499+
fprintf(stderr,
500+
"dropped truncated taskstats netlink message, please increase MAX_MSG_SIZE\n");
501+
else
502+
fprintf(stderr, "nonfatal reply error: errno %d\n",
503+
errno);
474504
continue;
475505
}
476506
if (msg.n.nlmsg_type == NLMSG_ERROR ||
@@ -512,6 +542,9 @@ int main(int argc, char *argv[])
512542
printf("TGID\t%d\n", rtid);
513543
break;
514544
case TASKSTATS_TYPE_STATS:
545+
PRINTF("version %u\n",
546+
((struct taskstats *)
547+
NLA_DATA(na))->version);
515548
if (print_delays)
516549
print_delayacct((struct taskstats *) NLA_DATA(na));
517550
if (print_io_accounting)

tools/accounting/procacct.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ int print_task_context_switch_counts;
7171
}
7272

7373
/* Maximum size of response requested or message sent */
74-
#define MAX_MSG_SIZE 1024
74+
#define MAX_MSG_SIZE 2048
7575
/* Maximum number of cpus expected to be specified in a cpumask */
7676
#define MAX_CPUS 32
7777

@@ -121,6 +121,32 @@ static int create_nl_socket(int protocol)
121121
return -1;
122122
}
123123

124+
static int recv_taskstats_msg(int sd, struct msgtemplate *msg)
125+
{
126+
struct sockaddr_nl nladdr;
127+
struct iovec iov = {
128+
.iov_base = msg,
129+
.iov_len = sizeof(*msg),
130+
};
131+
struct msghdr hdr = {
132+
.msg_name = &nladdr,
133+
.msg_namelen = sizeof(nladdr),
134+
.msg_iov = &iov,
135+
.msg_iovlen = 1,
136+
};
137+
int ret;
138+
139+
ret = recvmsg(sd, &hdr, 0);
140+
if (ret < 0)
141+
return -1;
142+
if (hdr.msg_flags & MSG_TRUNC) {
143+
errno = EMSGSIZE;
144+
return -1;
145+
}
146+
147+
return ret;
148+
}
149+
124150

125151
static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
126152
__u8 genl_cmd, __u16 nla_type,
@@ -239,6 +265,8 @@ void handle_aggr(int mother, struct nlattr *na, int fd)
239265
PRINTF("TGID\t%d\n", rtid);
240266
break;
241267
case TASKSTATS_TYPE_STATS:
268+
PRINTF("version %u\n",
269+
((struct taskstats *)NLA_DATA(na))->version);
242270
if (mother == TASKSTATS_TYPE_AGGR_PID)
243271
print_procacct((struct taskstats *) NLA_DATA(na));
244272
if (fd) {
@@ -348,12 +376,16 @@ int main(int argc, char *argv[])
348376
}
349377

350378
do {
351-
rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
379+
rep_len = recv_taskstats_msg(nl_sd, &msg);
352380
PRINTF("received %d bytes\n", rep_len);
353381

354382
if (rep_len < 0) {
355-
fprintf(stderr, "nonfatal reply error: errno %d\n",
356-
errno);
383+
if (errno == EMSGSIZE)
384+
fprintf(stderr,
385+
"dropped truncated taskstats netlink message, please increase MAX_MSG_SIZE\n");
386+
else
387+
fprintf(stderr, "nonfatal reply error: errno %d\n",
388+
errno);
357389
continue;
358390
}
359391
if (msg.n.nlmsg_type == NLMSG_ERROR ||

0 commit comments

Comments
 (0)