summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorYiyang Chen <cyyzero16@gmail.com>2026-03-29 22:00:41 +0300
committerAndrew Morton <akpm@linux-foundation.org>2026-04-15 12:15:02 +0300
commitcc82b3dcc6a8fa259fbda12ab00d6fc00908a49e (patch)
tree606b8e5fecb2798b14b51d61a129aa586add2ef8 /tools
parent16c4f0211aaa1ec1422b11b59f64f1abe9009fc0 (diff)
downloadlinux-cc82b3dcc6a8fa259fbda12ab00d6fc00908a49e.tar.xz
tools/accounting: handle truncated taskstats netlink messages
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>
Diffstat (limited to 'tools')
-rw-r--r--tools/accounting/getdelays.c41
-rw-r--r--tools/accounting/procacct.c40
2 files changed, 73 insertions, 8 deletions
diff --git a/tools/accounting/getdelays.c b/tools/accounting/getdelays.c
index 50792df27707..368a622ca027 100644
--- a/tools/accounting/getdelays.c
+++ b/tools/accounting/getdelays.c
@@ -60,7 +60,7 @@ int print_task_context_switch_counts;
}
/* Maximum size of response requested or message sent */
-#define MAX_MSG_SIZE 1024
+#define MAX_MSG_SIZE 2048
/* Maximum number of cpus expected to be specified in a cpumask */
#define MAX_CPUS 32
@@ -115,6 +115,32 @@ error:
return -1;
}
+static int recv_taskstats_msg(int sd, struct msgtemplate *msg)
+{
+ struct sockaddr_nl nladdr;
+ struct iovec iov = {
+ .iov_base = msg,
+ .iov_len = sizeof(*msg),
+ };
+ struct msghdr hdr = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+ int ret;
+
+ ret = recvmsg(sd, &hdr, 0);
+ if (ret < 0)
+ return -1;
+ if (hdr.msg_flags & MSG_TRUNC) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ return ret;
+}
+
static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
__u8 genl_cmd, __u16 nla_type,
@@ -633,12 +659,16 @@ int main(int argc, char *argv[])
}
do {
- rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
+ rep_len = recv_taskstats_msg(nl_sd, &msg);
PRINTF("received %d bytes\n", rep_len);
if (rep_len < 0) {
- fprintf(stderr, "nonfatal reply error: errno %d\n",
- errno);
+ if (errno == EMSGSIZE)
+ fprintf(stderr,
+ "dropped truncated taskstats netlink message, please increase MAX_MSG_SIZE\n");
+ else
+ fprintf(stderr, "nonfatal reply error: errno %d\n",
+ errno);
continue;
}
if (msg.n.nlmsg_type == NLMSG_ERROR ||
@@ -680,6 +710,9 @@ int main(int argc, char *argv[])
printf("TGID\t%d\n", rtid);
break;
case TASKSTATS_TYPE_STATS:
+ PRINTF("version %u\n",
+ ((struct taskstats *)
+ NLA_DATA(na))->version);
if (print_delays)
print_delayacct((struct taskstats *) NLA_DATA(na));
if (print_io_accounting)
diff --git a/tools/accounting/procacct.c b/tools/accounting/procacct.c
index e8dee05a6264..46e5986ad927 100644
--- a/tools/accounting/procacct.c
+++ b/tools/accounting/procacct.c
@@ -71,7 +71,7 @@ int print_task_context_switch_counts;
}
/* Maximum size of response requested or message sent */
-#define MAX_MSG_SIZE 1024
+#define MAX_MSG_SIZE 2048
/* Maximum number of cpus expected to be specified in a cpumask */
#define MAX_CPUS 32
@@ -121,6 +121,32 @@ error:
return -1;
}
+static int recv_taskstats_msg(int sd, struct msgtemplate *msg)
+{
+ struct sockaddr_nl nladdr;
+ struct iovec iov = {
+ .iov_base = msg,
+ .iov_len = sizeof(*msg),
+ };
+ struct msghdr hdr = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+ int ret;
+
+ ret = recvmsg(sd, &hdr, 0);
+ if (ret < 0)
+ return -1;
+ if (hdr.msg_flags & MSG_TRUNC) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ return ret;
+}
+
static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
__u8 genl_cmd, __u16 nla_type,
@@ -239,6 +265,8 @@ void handle_aggr(int mother, struct nlattr *na, int fd)
PRINTF("TGID\t%d\n", rtid);
break;
case TASKSTATS_TYPE_STATS:
+ PRINTF("version %u\n",
+ ((struct taskstats *)NLA_DATA(na))->version);
if (mother == TASKSTATS_TYPE_AGGR_PID)
print_procacct((struct taskstats *) NLA_DATA(na));
if (fd) {
@@ -347,12 +375,16 @@ int main(int argc, char *argv[])
}
do {
- rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
+ rep_len = recv_taskstats_msg(nl_sd, &msg);
PRINTF("received %d bytes\n", rep_len);
if (rep_len < 0) {
- fprintf(stderr, "nonfatal reply error: errno %d\n",
- errno);
+ if (errno == EMSGSIZE)
+ fprintf(stderr,
+ "dropped truncated taskstats netlink message, please increase MAX_MSG_SIZE\n");
+ else
+ fprintf(stderr, "nonfatal reply error: errno %d\n",
+ errno);
continue;
}
if (msg.n.nlmsg_type == NLMSG_ERROR ||