static int dump_ipc_msg_queue_messages(int fd, const IpcMsgEntry *msq, unsigned int msg_nr) { struct msgbuf *message = NULL; unsigned int msgmax; int ret, msg_cnt = 0; struct sysctl_req req[] = { { "kernel/msgmax", &msgmax, CTL_U32 }, { }, }; ret = sysctl_op(req, CTL_READ); if (ret < 0) { pr_err("Failed to read max IPC message size\n"); goto err; } msgmax += sizeof(struct msgbuf); message = xmalloc(round_up(msgmax, sizeof(u64))); if (message == NULL) { pr_err("Failed to allocate memory for IPC message\n"); return -ENOMEM; } for (msg_cnt = 0; msg_cnt < msg_nr; msg_cnt++) { IpcMsg msg = IPC_MSG__INIT; size_t rounded; ret = msgrcv(msq->desc->id, message, msgmax, msg_cnt, IPC_NOWAIT | MSG_COPY); if (ret < 0) { pr_perror("Failed to copy IPC message"); goto err; } msg.msize = ret; msg.mtype = message->mtype; pr_info_ipc_msg(msg_cnt, &msg); ret = pb_write_one(fd, &msg, PB_IPCNS_MSG); if (ret < 0) { pr_err("Failed to write IPC message header\n"); break; } rounded = round_up(msg.msize, sizeof(u64)); memzero(((void *)message->mtext + msg.msize), rounded - msg.msize); ret = write_img_buf(fd, message->mtext, rounded); if (ret < 0) { pr_err("Failed to write IPC message data\n"); break; } } ret = 0; err: xfree(message); return ret; }
static int prepare_ipc_msg_queue_messages(struct cr_img *img, const IpcMsgEntry *msq) { IpcMsg *msg = NULL; int msg_nr = 0; int ret = 0; while (msg_nr < msq->qnum) { struct msgbuf { long mtype; char mtext[MSGMAX]; } data; ret = pb_read_one(img, &msg, PB_IPCNS_MSG); if (ret <= 0) return -EIO; pr_info_ipc_msg(msg_nr, msg); if (msg->msize > MSGMAX) { ret = -1; pr_err("Unsupported message size: %d (MAX: %d)\n", msg->msize, MSGMAX); break; } ret = read_img_buf(img, data.mtext, round_up(msg->msize, sizeof(u64))); if (ret < 0) { pr_err("Failed to read IPC message data\n"); break; } data.mtype = msg->mtype; ret = msgsnd(msq->desc->id, &data, msg->msize, IPC_NOWAIT); if (ret < 0) { pr_perror("Failed to send IPC message"); ret = -errno; break; } msg_nr++; } if (msg) ipc_msg__free_unpacked(msg, NULL); return ret; }