From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f170.google.com (mail-pg1-f170.google.com [209.85.215.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F24C39EF1E for ; Wed, 8 Apr 2026 09:53:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.170 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775642041; cv=none; b=M32jchaSdU2WtG0r4g+Kvlbp+c66qMALUDwvwqk2puUsFamQDRQAfcVKIxexLoD4XI8mNSq4KH0qIP2T/1YkJ/cp2yGgfeSDQvqTPGbOCFlyIFWF7bP+pT5SI26rVf6LS0CN8gg5ENNNQPUF0104WG8ci5vnQvjaX8a47SUEorA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775642041; c=relaxed/simple; bh=XXxsQRGT7AhIKjdSnsdQYNXtOVqHk2HPayHR1pBd/uM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KaqEA7vh+Ju5nLKPCQzRPFy8wBg1OFHgkgK7F3ttLF49aTBvJlx7MnGWNifhsIC8Y1wUvzVrZ3Cgx7Gor/Tn9tULGkvt6uZCpsQ9TIAuuo86Zg3Y3QJsPmrJ1A2cr5+YklVccMEBwXcn7W5MIVEIRrIK2aLID3UbaMhnqiYJoDk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=AZQ6193n; arc=none smtp.client-ip=209.85.215.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AZQ6193n" Received: by mail-pg1-f170.google.com with SMTP id 41be03b00d2f7-c6dd5b01e14so2166325a12.0 for ; Wed, 08 Apr 2026 02:53:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775642024; x=1776246824; darn=lists.linux.dev; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=X5rOJLHfZN2GLmG0MwzuKGaJWHxEh5Ns8OQAVYaUN+g=; b=AZQ6193nw9N4UmVXl0n6nZ5QFwK8aCK+CZy/CugutABFUSXtUpHVdhkrV85xznZ5EA ijLm6N6SrYYHIcZNY8JUzc0lZsfwmrZzXODW1+wVi2Ploj7H6vY30VUOskJw8H4w1xrd xhjmSCUfiySzFo3jnCl1b0060EIiEhbXf8ip1eDYvrDkFXX2vTADWKOJkp5DC+C55iVY kd3MVFLVK3Dtdt65E8PSHUO3iti0kNffLpHIppNrvjYyEg5KmABrqn01mR4KGXWW+HnP UjqiUTztpY9SAOhmqkljnKJL/I87j27N39G9rG06IZ1g0mKCBO+yCXhqq5ttD/bgRODC m97g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775642024; x=1776246824; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=X5rOJLHfZN2GLmG0MwzuKGaJWHxEh5Ns8OQAVYaUN+g=; b=kvKrf7uG2fgkEAdLO+yrshsxSWLJPXifr+pFg/QbBHr1fKt4IK57+i1gYLfq9lqKm4 BQe8GikW1ea8obNXe1IY8GM4GleuDHNXregg1Byhm1AS48tzkZImkBzrPXDpT6Pg4Q9V qZnP/IJFnEkpy/oBPHrlCgWHCXBwRfEdH/TozRDguqJ0tJxHY0QPS65WLRUkFTNK72JY mQ1E7NCTwh9hpjTpfQAj0ulrul82doqLGjofFosINtof4knqQ55VS6LrnvMtP7GfNdaJ LP5RKvNAR70qSemJh+3udfDbPE/z9PqoPi4UiBICXQ14IZ4pHu2Y3LhwhSejdI0/SnKl 09cA== X-Gm-Message-State: AOJu0YwsREk4kNdGzl/glleAMt+cfF+IQJRCcd5X9A1jlTarjY5/IAHW xyItpzXWoDrNFyLNnf2rGB/t+SSLhIItqiioBy1x0LwL5zlC6PWClblZK2f9sg== X-Gm-Gg: AeBDietHhGnv2+shboddjCNXH67AAQNjm7Ynvj8tjGx9YXT8KV/ZBoUGxSwYv+BYBqZ 6aujNnMKn+93pyQ8pSbD/krTf0Wz5YUH750KnWmODsi1AV9YlduG/yWaCLMgNKBcCgxjxJbPEMA n7aAvtvfnzAClyxnRaLzNW38GHAvkkCfzJ+jBlevnTjIIZYKz/wO2dR9/sKYZvhFGVJI2aPV1TC wvt2AW2pTHvbueaBSmdTWS5MOrpSY0bJ3sSAg8Vas9woT2/H0WZJz6Wh24iA+FkzHaavD3yL3tY +YBtx7cteubsHCvr97fwx9Dtnc3yt2rtrTnF50gFbygZkKGvThMjpS67DN8lKoIQ+sv0jPWT2nU UDbqGp8iVcM5ywWB1WLci2G4Bg4u35DzVobejQ9UtJMAZjelBTklKRecjPdNy0L9mAT7RIZtVcc aLktmSoBXpAC6/baLr7LlDUgb1jfu1dR0YBQ== X-Received: by 2002:a05:6a20:12c5:b0:398:840d:39b3 with SMTP id adf61e73a8af0-39f2f07e7fdmr21201238637.30.1775642024308; Wed, 08 Apr 2026 02:53:44 -0700 (PDT) Received: from Modern-15.. ([2409:40e4:1303:a14e:b7fc:cb55:34aa:99f3]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82cf9b5f1dbsm20848197b3a.27.2026.04.08.02.53.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 02:53:43 -0700 (PDT) From: Mathura_Kumar To: criu@lists.linux.dev Cc: academic1mathura@gmail.com, avagin@gmail.com, ptikhomirov@virtuozzo.com, rstoyanov@fedoraproject.org Subject: [PATCH v3 5/5]Added bitmask flag and user struct argument size as input for extensibility Date: Wed, 8 Apr 2026 15:21:33 +0530 Message-ID: <20260408095219.26350-6-academic1mathura@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260408095219.26350-1-academic1mathura@gmail.com> References: <20260408095219.26350-1-academic1mathura@gmail.com> Precedence: bulk X-Mailing-List: criu@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=yes Content-Transfer-Encoding: 8bit Signed-off-by: Mathura_Kumar --- Documentation/userspace-api/ipc.rst | 24 ++-- include/linux/compat.h | 4 +- include/linux/syscalls.h | 4 +- ipc/mqueue.c | 179 +++++++++++++++----------- kernel/sys_ni.c | 2 + tools/testing/selftests/ipc/mq_peek.c | 54 ++++++-- 6 files changed, 163 insertions(+), 104 deletions(-) diff --git a/Documentation/userspace-api/ipc.rst b/Documentation/userspace-api/ipc.rst index 14a5f0ce7230..3fc46621b5c6 100644 --- a/Documentation/userspace-api/ipc.rst +++ b/Documentation/userspace-api/ipc.rst @@ -54,13 +54,10 @@ SYNOPSIS ssize_t mq_timedreceive2(mqd_t mqdes, struct mq_timedreceive2_args *uargs, - unsigned int flags, + size_t usize, unsigned int flags, unsigned long index, const struct timespec *abs_timeout); -Note: No glibc wrapper exists for this syscall. Callers must invoke it -directly using syscall(2). - DESCRIPTION mq_timedreceive2() receives or peeks at a message from the message queue referred to by the descriptor mqdes. @@ -78,14 +75,19 @@ DESCRIPTION If not NULL, the priority of the received message is stored here. + The usize argument take size of struct to make mq_timedreceive2_args + extensible in future if required. + The flags argument controls receive behavior. The following flag is defined: ``MQ_PEEK`` Copy the message into msg_ptr without removing it from - the queue. The queue is not modified. If this flag is - not set, behavior is identical to mq_timedreceive() and - the message is consumed. + the queue. The queue is not modified. + + ``MQ_RECV`` + Copy the message into msg_ptr and consume a single message by + invoking the existing do_mq_timedreceive() handler. The index argument selects which message to operate on within the priority-ordered queue. index 0 refers to the highest @@ -116,7 +118,7 @@ ERRORS ``EINVAL`` flags contains an unknown value, or index is nonzero - and MQ_PEEK is not set. + and contradictory flag was passed. ``EMSGSIZE`` msg_len is less than the mq_msgsize attribute of @@ -137,7 +139,7 @@ consolidated into struct mq_timedreceive2_args rather than passed as individual syscall arguments. Due to limited six arguments, The original mq_timedreceive() consumes all six slots, leaving no room for extension. Consolidating the buffer parameters -into a struct recovers two argument slots for flags and index while +into a struct recovers three argument slots for flags, size and index while keeping the interface clean and forward-compatible. Future extensions can be made by adding new flag bits without @@ -220,3 +222,7 @@ Tests for mq_timedreceive2() should cover the following: threads returns consistent results and does not corrupt queue state. Verify that a concurrent mq_receive() and mq_peek() do not race. + +9) Contradictory Operation: verify that simultaneous inconsistent flag work as + expected. + diff --git a/include/linux/compat.h b/include/linux/compat.h index 9f5ca26e76d8..837a59559fa5 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -803,8 +803,8 @@ asmlinkage long compat_sys_pwritev64v2(unsigned long fd, unsigned long vlen, loff_t pos, rwf_t flags); #endif asmlinkage long compat_sys_mq_timedreceive2(mqd_t mqdes, struct compat_mq_timedreceive2_args __user *uargs, - unsigned int flags, unsigned long index, - struct old_timespec32 __user *abs_timeout); + size_t usize, unsigned int flags, const unsigned long index, + const struct old_timespec32 __user *abs_timeout); /* * Deprecated system calls which are still defined in * include/uapi/asm-generic/unistd.h and wanted by >= 1 arch diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 993e570c90ab..e5b544464a44 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -750,8 +750,8 @@ asmlinkage long sys_mq_timedsend_time32(mqd_t mqdes, const struct old_timespec32 __user *u_abs_timeout); asmlinkage long sys_mq_timedreceive2(mqd_t mqdes, struct mq_timedreceive2_args __user *uargs, - unsigned int flags, unsigned long index, - struct __kernel_timespec __user *abs_timeout); + size_t usize, unsigned int flags, const unsigned long index, + const struct __kernel_timespec __user *abs_timeout); asmlinkage long sys_msgget(key_t key, int msgflg); asmlinkage long sys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 78dc414967a2..2d4c285e4aa1 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "util.h" @@ -53,7 +54,10 @@ struct mqueue_fs_context { #define SEND 0 #define RECV 1 -#define MQ_PEEK 2 + +#define MQ_PEEK 0x02 +#define MQ_RECV 0x04 +#define MQ_VALID_FLAGS (MQ_PEEK | MQ_RECV) #define STATE_NONE 0 #define STATE_READY 1 @@ -1266,78 +1270,85 @@ static int do_mq_timedreceive2(mqd_t mqdes, struct mq_timedreceive2_args *args, struct inode *inode; struct mqueue_inode_info *info; - if (!(flags & MQ_PEEK)) { - return do_mq_timedreceive(mqdes, args->msg_ptr, args->msg_len, - args->msg_prio, ts); - } - audit_mq_sendrecv(mqdes, args->msg_len, 0, ts); - CLASS(fd, f)(mqdes); - if (fd_empty(f)) - return -EBADF; - - inode = file_inode(fd_file(f)); - if (unlikely(fd_file(f)->f_op != &mqueue_file_operations)) - return -EBADF; - info = MQUEUE_I(inode); - audit_file(fd_file(f)); + if (flags & (~MQ_VALID_FLAGS)) + return -EINVAL; + if ((flags & MQ_RECV) && (flags & MQ_PEEK)) + return -EINVAL; + if (flags & MQ_PEEK) { + audit_mq_sendrecv(mqdes, args->msg_len, 0, ts); + CLASS(fd, f)(mqdes); + if (fd_empty(f)) + return -EBADF; + + inode = file_inode(fd_file(f)); + if (unlikely(fd_file(f)->f_op != &mqueue_file_operations)) + return -EBADF; + info = MQUEUE_I(inode); + audit_file(fd_file(f)); - if (unlikely(!(fd_file(f)->f_mode & FMODE_READ))) - return -EBADF; + if (unlikely(!(fd_file(f)->f_mode & FMODE_READ))) + return -EBADF; - if (unlikely(args->msg_len < info->attr.mq_msgsize)) - return -EMSGSIZE; - if (index >= (unsigned long)info->attr.mq_maxmsg) - return -ENOENT; + if (unlikely(args->msg_len < info->attr.mq_msgsize)) + return -EMSGSIZE; + if (index >= (unsigned long)info->attr.mq_maxmsg) + return -ENOENT; - spin_lock(&info->lock); - if (info->attr.mq_curmsgs == 0) { - spin_unlock(&info->lock); - return -EAGAIN; - } - msg_ptr = mq_peek_index(info, index); - if (!msg_ptr) { + spin_lock(&info->lock); + if (info->attr.mq_curmsgs == 0) { + spin_unlock(&info->lock); + return -EAGAIN; + } + msg_ptr = mq_peek_index(info, index); + if (!msg_ptr) { + spin_unlock(&info->lock); + return -ENOENT; + } + k_m_type = msg_ptr->m_type; + k_m_ts = msg_ptr->m_ts; spin_unlock(&info->lock); - return -ENOENT; - } - k_m_type = msg_ptr->m_type; - k_m_ts = msg_ptr->m_ts; - spin_unlock(&info->lock); - k_msg_buffer = alloc_msg(k_m_ts); - if (!k_msg_buffer) - return -ENOMEM; + k_msg_buffer = alloc_msg(k_m_ts); + if (!k_msg_buffer) + return -ENOMEM; /* * Two spin locks are necessary here. We are avoiding atomic memory * allocation and premature allocation before confirming that * a message actually exists to peek. */ - spin_lock(&info->lock); - msg_ptr = mq_peek_index(info, index); - if (!msg_ptr || msg_ptr->m_type != k_m_type || - msg_ptr->m_ts != k_m_ts) { - spin_unlock(&info->lock); - free_msg(k_msg_buffer); - return -EAGAIN; - } - if (IS_ERR(copy_msg(msg_ptr, k_msg_buffer, k_m_ts))) { + spin_lock(&info->lock); + msg_ptr = mq_peek_index(info, index); + if (!msg_ptr || msg_ptr->m_type != k_m_type || + msg_ptr->m_ts != k_m_ts) { + spin_unlock(&info->lock); + free_msg(k_msg_buffer); + return -EAGAIN; + } + if (IS_ERR(copy_msg(msg_ptr, k_msg_buffer, k_m_ts))) { + spin_unlock(&info->lock); + free_msg(k_msg_buffer); + return -EINVAL; + } spin_unlock(&info->lock); - free_msg(k_msg_buffer); - return -EINVAL; - } - spin_unlock(&info->lock); - ret = k_msg_buffer->m_ts; - if (args->msg_prio && put_user(k_m_type, args->msg_prio)) { + ret = k_msg_buffer->m_ts; + if (args->msg_prio && put_user(k_m_type, args->msg_prio)) { + free_msg(k_msg_buffer); + return -EFAULT; + } + if (store_msg(args->msg_ptr, k_msg_buffer, k_m_ts)) { + free_msg(k_msg_buffer); + return -EFAULT; + } free_msg(k_msg_buffer); - return -EFAULT; + return ret; } - if (store_msg(args->msg_ptr, k_msg_buffer, k_m_ts)) { - free_msg(k_msg_buffer); - return -EFAULT; + if (flags & MQ_RECV) { + return do_mq_timedreceive(mqdes, args->msg_ptr, args->msg_len, args->msg_prio, ts); } - free_msg(k_msg_buffer); - return ret; + + return -EINVAL; } SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, @@ -1368,17 +1379,22 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, return do_mq_timedreceive(mqdes, u_msg_ptr, msg_len, u_msg_prio, p); } -SYSCALL_DEFINE5(mq_timedreceive2, mqd_t, mqdes, - struct mq_timedreceive2_args __user *, uargs, unsigned int, - flags, const unsigned long, index, - const struct __kernel_timespec __user *, u_abs_timeout) +SYSCALL_DEFINE6(mq_timedreceive2, mqd_t, mqdes, + struct mq_timedreceive2_args __user *, uargs, size_t, usize, + unsigned int, flags, const unsigned long, index, + const struct __kernel_timespec __user *, u_abs_timeout) { - struct mq_timedreceive2_args args; + struct mq_timedreceive2_args k_args; struct timespec64 ts, *p = NULL; + int err; - if (copy_from_user(&args, uargs, sizeof(args))) - return -EFAULT; - + if (unlikely(usize < sizeof(struct mq_timedreceive2_args))) + return -EINVAL; + if (unlikely(usize > PAGE_SIZE)) + return -E2BIG; + err = copy_struct_from_user(&k_args, sizeof(k_args), uargs, usize); + if (err) + return err; if (u_abs_timeout) { int res = prepare_timeout(u_abs_timeout, &ts); @@ -1386,7 +1402,7 @@ SYSCALL_DEFINE5(mq_timedreceive2, mqd_t, mqdes, return res; p = &ts; } - return do_mq_timedreceive2(mqdes, &args, flags, index, p); + return do_mq_timedreceive2(mqdes, &k_args, flags, index, p); } /* @@ -1633,12 +1649,18 @@ static inline int put_compat_mq_attr(const struct mq_attr *attr, } static inline int get_compat_mq_args(struct mq_timedreceive2_args *args, - struct compat_mq_timedreceive2_args __user *uargs) + struct compat_mq_timedreceive2_args __user *uargs, size_t usize) { struct compat_mq_timedreceive2_args v; + int err; - if (copy_from_user(&v, uargs, sizeof(v))) - return -EFAULT; + if (unlikely(usize < sizeof(struct compat_mq_timedreceive2_args))) + return -EINVAL; + if (unlikely(usize > PAGE_SIZE)) + return -E2BIG; + err = copy_struct_from_user(&v, sizeof(v), uargs, usize); + if (err) + return err; memset(args, 0, sizeof(*args)); args->msg_len = (size_t)v.msg_len; @@ -1700,17 +1722,18 @@ COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes, return 0; } -COMPAT_SYSCALL_DEFINE5(mq_timedreceive2, mqd_t, mqdes, - struct compat_mq_timedreceive2_args __user *, uargs, - unsigned int, flags, const unsigned long, index, - const struct old_timespec32 __user *, u_abs_timeout) +COMPAT_SYSCALL_DEFINE6(mq_timedreceive2, mqd_t, mqdes, + struct compat_mq_timedreceive2_args __user *, uargs, size_t, usize, + unsigned int, flags, const unsigned long, index, + const struct old_timespec32 __user *, u_abs_timeout) { - struct mq_timedreceive2_args args; + struct mq_timedreceive2_args k_args; struct timespec64 ts, *p = NULL; + int err; - if (get_compat_mq_args(&args, uargs)) - return -EFAULT; - + err = get_compat_mq_args(&k_args, uargs, usize); + if (err) + return err; if (u_abs_timeout) { int res = compat_prepare_timeout(u_abs_timeout, &ts); @@ -1718,7 +1741,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive2, mqd_t, mqdes, return res; p = &ts; } - return do_mq_timedreceive2(mqdes, &args, flags, index, p); + return do_mq_timedreceive2(mqdes, &k_args, flags, index, p); } #endif diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 658d6b8274b3..af956bc4e6fe 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -391,6 +391,8 @@ COND_SYSCALL(setuid16); /* restartable sequence */ COND_SYSCALL(rseq); COND_SYSCALL(rseq_slice_yield); + +/* ipc */ COND_SYSCALL(mq_timedreceive2); COND_SYSCALL(uretprobe); diff --git a/tools/testing/selftests/ipc/mq_peek.c b/tools/testing/selftests/ipc/mq_peek.c index d08596ae6e1c..0ec3f2fca82c 100644 --- a/tools/testing/selftests/ipc/mq_peek.c +++ b/tools/testing/selftests/ipc/mq_peek.c @@ -40,7 +40,8 @@ #endif #endif -#define MQ_PEEK 2U +#define MQ_PEEK 0x02 +#define MQ_RECV 0x04 #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -52,11 +53,13 @@ struct mq_timedreceive2_args { char *msg_ptr; }; -static long mq_timedreceive2(mqd_t mqdes, struct mq_timedreceive2_args *uargs, - unsigned int flags, unsigned long index, +#define u_struct_size sizeof(struct mq_timedreceive2_args) + +static long mq_timedreceive2(mqd_t mqdes, struct mq_timedreceive2_args *uargs, size_t usize, + unsigned int flags, const unsigned long index, const struct timespec *timeout) { - return syscall(__NR_mq_timedreceive2, (long)mqdes, uargs, (long)flags, + return syscall(__NR_mq_timedreceive2, mqdes, uargs, usize, flags, index, timeout); } @@ -109,7 +112,7 @@ static long peek(mqd_t mqd, unsigned long index, char *buf, size_t bufsz, .msg_prio = prio, .msg_ptr = buf, }; - return mq_timedreceive2(mqd, &args, MQ_PEEK, index, NULL); + return mq_timedreceive2(mqd, &args, u_struct_size, MQ_PEEK, index, NULL); } static long queue_depth(mqd_t mqd) @@ -226,7 +229,7 @@ static void test_peek_buffer_too_small(void) send_msg(mqd, PRIO_HIGH, "hello", 5); - ret = mq_timedreceive2(mqd, &args, MQ_PEEK, 0, NULL); + ret = mq_timedreceive2(mqd, &args, u_struct_size, MQ_PEEK, 0, NULL); if (ret == -1 && errno == EMSGSIZE) ksft_test_result_pass("peek with small buf [EMSGSIZE]\n"); else @@ -246,11 +249,10 @@ static void test_peek_bad_msg_ptr(void) .msg_prio = &prio, .msg_ptr = (char *)0x1, }; - long ret; send_msg(mqd, PRIO_HIGH, "payload", 7); - ret = mq_timedreceive2(mqd, &args, MQ_PEEK, 0, NULL); + ret = mq_timedreceive2(mqd, &args, u_struct_size, MQ_PEEK, 0, NULL); if (ret == -1 && errno == EFAULT) ksft_test_result_pass("peek bad msg_ptr [EFAULT]\n"); else @@ -588,7 +590,7 @@ static void test_no_peek_flag_is_receive(void) send_msg(mqd, PRIO_HIGH, "consume-me", 10); - ret = mq_timedreceive2(mqd, &args, 0, 0, NULL); + ret = mq_timedreceive2(mqd, &args, u_struct_size, MQ_RECV, 0, NULL); if (ret < 0) { ksft_test_result_fail("no-peek receive failed: ret=%ld errno=%d\n", ret, errno); mq_close(mqd); @@ -615,8 +617,7 @@ static void *receiver_thread(void *arg) ssize_t r; while ((r = mq_receive(ctx->mqd, buf, sizeof(buf), &prio)) > 0) - ; - + ; return NULL; } @@ -680,7 +681,7 @@ static void test_peek_null_prio_ptr(void) send_msg(mqd, PRIO_MED, "no-prio-needed", 14); - ret = mq_timedreceive2(mqd, &args, MQ_PEEK, 0, NULL); + ret = mq_timedreceive2(mqd, &args, u_struct_size, MQ_PEEK, 0, NULL); if (ret >= 0) ksft_test_result_pass("peek with NULL msg_prio ptr: OK\n"); else @@ -734,6 +735,32 @@ static void test_peek_priority_matches_receive(void) mq_close(mqd); } +static void test_contradictory_operation(void) +{ + mqd_t mqd = open_queue("contra_op", MAX_MSG_SIZE); + char buf[MAX_MSG_SIZE]; + struct mq_timedreceive2_args args = { + .msg_len = sizeof(buf), + .msg_prio = NULL, + .msg_ptr = buf, + }; + long ret; + + send_msg(mqd, PRIO_HIGH, "A", 1); + send_msg(mqd, PRIO_MED, "B", 1); + send_msg(mqd, PRIO_LOW, "C", 1); + + ret = mq_timedreceive2(mqd, &args, u_struct_size, MQ_PEEK | MQ_RECV, 0, 0); + + if (ret == -1 && errno == EINVAL) + ksft_test_result_pass("Handler rejected invalid/contradictory request [EINVAL]\n"); + else + ksft_test_result_fail("Handler did not reject invalid request: ret=%ld errno=%d (%m)\n", + ret, errno); + + mq_close(mqd); +} + static const struct { const char *name; void (*fn)(void); @@ -756,6 +783,7 @@ static const struct { { "NULL msg_prio ptr", test_peek_null_prio_ptr }, { "peeked prio matches mq_receive", test_peek_priority_matches_receive }, + {"two_contradictory_operation_togther", test_contradictory_operation} }; int main(void) @@ -769,7 +797,7 @@ int main(void) { struct mq_timedreceive2_args probe_args = { 0 }; - sc_ret = mq_timedreceive2((mqd_t)-1, &probe_args, MQ_PEEK, 0, + sc_ret = mq_timedreceive2((mqd_t)-1, &probe_args, u_struct_size, MQ_PEEK, 0, NULL); if (sc_ret == -1 && errno == ENOSYS) ksft_exit_skip("mq_timedreceive2 syscall not available (NR=%d ENOSYS) — is the kernel too old?\n", -- 2.43.0