cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

msgque.c (5431B)


      1// SPDX-License-Identifier: GPL-2.0
      2#define _GNU_SOURCE
      3#include <stdlib.h>
      4#include <stdio.h>
      5#include <string.h>
      6#include <errno.h>
      7#include <sys/msg.h>
      8#include <fcntl.h>
      9
     10#include "../kselftest.h"
     11
     12#define MAX_MSG_SIZE		32
     13
     14struct msg1 {
     15	int msize;
     16	long mtype;
     17	char mtext[MAX_MSG_SIZE];
     18};
     19
     20#define TEST_STRING "Test sysv5 msg"
     21#define MSG_TYPE 1
     22
     23#define ANOTHER_TEST_STRING "Yet another test sysv5 msg"
     24#define ANOTHER_MSG_TYPE 26538
     25
     26struct msgque_data {
     27	key_t key;
     28	int msq_id;
     29	int qbytes;
     30	int qnum;
     31	int mode;
     32	struct msg1 *messages;
     33};
     34
     35int restore_queue(struct msgque_data *msgque)
     36{
     37	int fd, ret, id, i;
     38	char buf[32];
     39
     40	fd = open("/proc/sys/kernel/msg_next_id", O_WRONLY);
     41	if (fd == -1) {
     42		printf("Failed to open /proc/sys/kernel/msg_next_id\n");
     43		return -errno;
     44	}
     45	sprintf(buf, "%d", msgque->msq_id);
     46
     47	ret = write(fd, buf, strlen(buf));
     48	if (ret != strlen(buf)) {
     49		printf("Failed to write to /proc/sys/kernel/msg_next_id\n");
     50		return -errno;
     51	}
     52
     53	id = msgget(msgque->key, msgque->mode | IPC_CREAT | IPC_EXCL);
     54	if (id == -1) {
     55		printf("Failed to create queue\n");
     56		return -errno;
     57	}
     58
     59	if (id != msgque->msq_id) {
     60		printf("Restored queue has wrong id (%d instead of %d)\n",
     61							id, msgque->msq_id);
     62		ret = -EFAULT;
     63		goto destroy;
     64	}
     65
     66	for (i = 0; i < msgque->qnum; i++) {
     67		if (msgsnd(msgque->msq_id, &msgque->messages[i].mtype,
     68			   msgque->messages[i].msize, IPC_NOWAIT) != 0) {
     69			printf("msgsnd failed (%m)\n");
     70			ret = -errno;
     71			goto destroy;
     72		}
     73	}
     74	return 0;
     75
     76destroy:
     77	if (msgctl(id, IPC_RMID, NULL))
     78		printf("Failed to destroy queue: %d\n", -errno);
     79	return ret;
     80}
     81
     82int check_and_destroy_queue(struct msgque_data *msgque)
     83{
     84	struct msg1 message;
     85	int cnt = 0, ret;
     86
     87	while (1) {
     88		ret = msgrcv(msgque->msq_id, &message.mtype, MAX_MSG_SIZE,
     89				0, IPC_NOWAIT);
     90		if (ret < 0) {
     91			if (errno == ENOMSG)
     92				break;
     93			printf("Failed to read IPC message: %m\n");
     94			ret = -errno;
     95			goto err;
     96		}
     97		if (ret != msgque->messages[cnt].msize) {
     98			printf("Wrong message size: %d (expected %d)\n", ret,
     99						msgque->messages[cnt].msize);
    100			ret = -EINVAL;
    101			goto err;
    102		}
    103		if (message.mtype != msgque->messages[cnt].mtype) {
    104			printf("Wrong message type\n");
    105			ret = -EINVAL;
    106			goto err;
    107		}
    108		if (memcmp(message.mtext, msgque->messages[cnt].mtext, ret)) {
    109			printf("Wrong message content\n");
    110			ret = -EINVAL;
    111			goto err;
    112		}
    113		cnt++;
    114	}
    115
    116	if (cnt != msgque->qnum) {
    117		printf("Wrong message number\n");
    118		ret = -EINVAL;
    119		goto err;
    120	}
    121
    122	ret = 0;
    123err:
    124	if (msgctl(msgque->msq_id, IPC_RMID, NULL)) {
    125		printf("Failed to destroy queue: %d\n", -errno);
    126		return -errno;
    127	}
    128	return ret;
    129}
    130
    131int dump_queue(struct msgque_data *msgque)
    132{
    133	struct msqid_ds ds;
    134	int kern_id;
    135	int i, ret;
    136
    137	for (kern_id = 0; kern_id < 256; kern_id++) {
    138		ret = msgctl(kern_id, MSG_STAT, &ds);
    139		if (ret < 0) {
    140			if (errno == EINVAL)
    141				continue;
    142			printf("Failed to get stats for IPC queue with id %d\n",
    143					kern_id);
    144			return -errno;
    145		}
    146
    147		if (ret == msgque->msq_id)
    148			break;
    149	}
    150
    151	msgque->messages = malloc(sizeof(struct msg1) * ds.msg_qnum);
    152	if (msgque->messages == NULL) {
    153		printf("Failed to get stats for IPC queue\n");
    154		return -ENOMEM;
    155	}
    156
    157	msgque->qnum = ds.msg_qnum;
    158	msgque->mode = ds.msg_perm.mode;
    159	msgque->qbytes = ds.msg_qbytes;
    160
    161	for (i = 0; i < msgque->qnum; i++) {
    162		ret = msgrcv(msgque->msq_id, &msgque->messages[i].mtype,
    163				MAX_MSG_SIZE, i, IPC_NOWAIT | MSG_COPY);
    164		if (ret < 0) {
    165			printf("Failed to copy IPC message: %m (%d)\n", errno);
    166			return -errno;
    167		}
    168		msgque->messages[i].msize = ret;
    169	}
    170	return 0;
    171}
    172
    173int fill_msgque(struct msgque_data *msgque)
    174{
    175	struct msg1 msgbuf;
    176
    177	msgbuf.mtype = MSG_TYPE;
    178	memcpy(msgbuf.mtext, TEST_STRING, sizeof(TEST_STRING));
    179	if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(TEST_STRING),
    180				IPC_NOWAIT) != 0) {
    181		printf("First message send failed (%m)\n");
    182		return -errno;
    183	}
    184
    185	msgbuf.mtype = ANOTHER_MSG_TYPE;
    186	memcpy(msgbuf.mtext, ANOTHER_TEST_STRING, sizeof(ANOTHER_TEST_STRING));
    187	if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(ANOTHER_TEST_STRING),
    188				IPC_NOWAIT) != 0) {
    189		printf("Second message send failed (%m)\n");
    190		return -errno;
    191	}
    192	return 0;
    193}
    194
    195int main(int argc, char **argv)
    196{
    197	int msg, pid, err;
    198	struct msgque_data msgque;
    199
    200	if (getuid() != 0)
    201		return ksft_exit_skip(
    202				"Please run the test as root - Exiting.\n");
    203
    204	msgque.key = ftok(argv[0], 822155650);
    205	if (msgque.key == -1) {
    206		printf("Can't make key: %d\n", -errno);
    207		return ksft_exit_fail();
    208	}
    209
    210	msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);
    211	if (msgque.msq_id == -1) {
    212		err = -errno;
    213		printf("Can't create queue: %d\n", err);
    214		goto err_out;
    215	}
    216
    217	err = fill_msgque(&msgque);
    218	if (err) {
    219		printf("Failed to fill queue: %d\n", err);
    220		goto err_destroy;
    221	}
    222
    223	err = dump_queue(&msgque);
    224	if (err) {
    225		printf("Failed to dump queue: %d\n", err);
    226		goto err_destroy;
    227	}
    228
    229	err = check_and_destroy_queue(&msgque);
    230	if (err) {
    231		printf("Failed to check and destroy queue: %d\n", err);
    232		goto err_out;
    233	}
    234
    235	err = restore_queue(&msgque);
    236	if (err) {
    237		printf("Failed to restore queue: %d\n", err);
    238		goto err_destroy;
    239	}
    240
    241	err = check_and_destroy_queue(&msgque);
    242	if (err) {
    243		printf("Failed to test queue: %d\n", err);
    244		goto err_out;
    245	}
    246	return ksft_exit_pass();
    247
    248err_destroy:
    249	if (msgctl(msgque.msq_id, IPC_RMID, NULL)) {
    250		printf("Failed to destroy queue: %d\n", -errno);
    251		return ksft_exit_fail();
    252	}
    253err_out:
    254	return ksft_exit_fail();
    255}