gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/msgqueue.cc (about)

     1  // Copyright 2021 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <errno.h>
    16  #include <signal.h>
    17  #include <sys/ipc.h>
    18  #include <sys/msg.h>
    19  #include <sys/types.h>
    20  
    21  #include "absl/synchronization/notification.h"
    22  #include "absl/time/clock.h"
    23  #include "test/util/capability_util.h"
    24  #include "test/util/signal_util.h"
    25  #include "test/util/temp_path.h"
    26  #include "test/util/test_util.h"
    27  #include "test/util/thread_util.h"
    28  
    29  namespace gvisor {
    30  namespace testing {
    31  namespace {
    32  
    33  // Source: include/uapi/linux/msg.h
    34  constexpr int msgMnb = 16384;  // Maximum number of bytes in a queue.
    35  constexpr int msgMni = 32000;  // Max number of identifiers.
    36  constexpr int msgPool =
    37      (msgMni * msgMnb / 1024);  // Size of buffer pool used to hold message data.
    38  constexpr int msgMap = msgMnb;  // Maximum number of entries in message map.
    39  constexpr int msgMax = 8192;    // Maximum number of bytes in a single message.
    40  constexpr int msgSsz = 16;      // Message segment size.
    41  constexpr int msgTql = msgMnb;  // Maximum number of messages on all queues.
    42  
    43  constexpr int kInterruptSignal = SIGALRM;
    44  
    45  // Queue is a RAII class used to automatically clean message queues.
    46  class Queue {
    47   public:
    48    explicit Queue(int id) : id_(id) {}
    49    Queue(const Queue&) = delete;
    50    Queue& operator=(const Queue&) = delete;
    51  
    52    Queue(Queue&& other) { id_ = other.release(); }
    53  
    54    ~Queue() {
    55      if (id_ >= 0) {
    56        EXPECT_THAT(msgctl(id_, IPC_RMID, nullptr), SyscallSucceeds());
    57      }
    58    }
    59  
    60    int release() {
    61      int old = id_;
    62      id_ = -1;
    63      return old;
    64    }
    65  
    66    int get() { return id_; }
    67  
    68   private:
    69    int id_ = -1;
    70  };
    71  
    72  PosixErrorOr<Queue> Msgget(key_t key, int flags) {
    73    int id = msgget(key, flags);
    74    if (id == -1) {
    75      return PosixError(errno, absl::StrFormat("msgget(%d, %d)", key, flags));
    76    }
    77    return Queue(id);
    78  }
    79  
    80  // Default size for messages.
    81  constexpr size_t msgSize = 50;
    82  
    83  // msgbuf is a simple buffer using to send and receive text messages for
    84  // testing purposes.
    85  struct msgbuf {
    86    int64_t mtype;
    87    char mtext[msgSize];
    88  };
    89  
    90  bool operator==(msgbuf& a, msgbuf& b) {
    91    for (size_t i = 0; i < msgSize; i++) {
    92      if (a.mtext[i] != b.mtext[i]) {
    93        return false;
    94      }
    95    }
    96    return a.mtype == b.mtype;
    97  }
    98  
    99  // msgmax represents a buffer for the largest possible single message.
   100  struct msgmax {
   101    int64_t mtype;
   102    char mtext[msgMax];
   103  };
   104  
   105  // Test simple creation and retrieval for msgget(2).
   106  TEST(MsgqueueTest, MsgGet) {
   107    const TempPath keyfile = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   108    const key_t key = ftok(keyfile.path().c_str(), 1);
   109    ASSERT_THAT(key, SyscallSucceeds());
   110  
   111    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(key, IPC_CREAT));
   112    EXPECT_THAT(msgget(key, 0), SyscallSucceedsWithValue(queue.get()));
   113  }
   114  
   115  // Test simple failure scenarios for msgget(2).
   116  TEST(MsgqueueTest, MsgGetFail) {
   117    const TempPath keyfile = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   118    const key_t key = ftok(keyfile.path().c_str(), 1);
   119    ASSERT_THAT(key, SyscallSucceeds());
   120  
   121    EXPECT_THAT(msgget(key, 0), SyscallFailsWithErrno(ENOENT));
   122  
   123    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(key, IPC_CREAT));
   124    EXPECT_THAT(msgget(key, IPC_CREAT | IPC_EXCL), SyscallFailsWithErrno(EEXIST));
   125  }
   126  
   127  // Test using msgget(2) with IPC_PRIVATE option.
   128  TEST(MsgqueueTest, MsgGetIpcPrivate) {
   129    Queue queue1 = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0));
   130    Queue queue2 = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0));
   131    EXPECT_NE(queue1.get(), queue2.get());
   132  }
   133  
   134  // Test simple msgsnd and msgrcv.
   135  TEST(MsgqueueTest, MsgOpSimple) {
   136    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   137  
   138    msgbuf buf{1, "A message."};
   139    msgbuf rcv;
   140  
   141    ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   142                SyscallSucceeds());
   143  
   144    EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(buf.mtext) + 1, 0, 0),
   145                SyscallSucceedsWithValue(sizeof(buf.mtext)));
   146    EXPECT_TRUE(buf == rcv);
   147  }
   148  
   149  // Test msgsnd and msgrcv of an empty message.
   150  TEST(MsgqueueTest, MsgOpEmpty) {
   151    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   152  
   153    msgbuf buf{1, ""};
   154    msgbuf rcv;
   155  
   156    ASSERT_THAT(msgsnd(queue.get(), &buf, 0, 0), SyscallSucceeds());
   157    EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(buf.mtext) + 1, 0, 0),
   158                SyscallSucceedsWithValue(0));
   159  }
   160  
   161  // Test truncation of message with MSG_NOERROR flag.
   162  TEST(MsgqueueTest, MsgOpTruncate) {
   163    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   164  
   165    msgbuf buf{1, ""};
   166    msgbuf rcv;
   167  
   168    ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   169                SyscallSucceeds());
   170  
   171    EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(buf.mtext) - 1, 0, MSG_NOERROR),
   172                SyscallSucceedsWithValue(sizeof(buf.mtext) - 1));
   173  }
   174  
   175  // Test msgsnd and msgrcv using invalid arguments.
   176  TEST(MsgqueueTest, MsgOpInvalidArgs) {
   177    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   178  
   179    msgbuf buf{1, ""};
   180  
   181    EXPECT_THAT(msgsnd(-1, &buf, 0, 0), SyscallFailsWithErrno(EINVAL));
   182    EXPECT_THAT(msgsnd(queue.get(), &buf, -1, 0), SyscallFailsWithErrno(EINVAL));
   183  
   184    buf.mtype = -1;
   185    EXPECT_THAT(msgsnd(queue.get(), &buf, 1, 0), SyscallFailsWithErrno(EINVAL));
   186  
   187    EXPECT_THAT(msgrcv(-1, &buf, 1, 0, 0), SyscallFailsWithErrno(EINVAL));
   188    EXPECT_THAT(msgrcv(queue.get(), &buf, -1, 0, 0),
   189                SyscallFailsWithErrno(EINVAL));
   190  }
   191  
   192  // Test non-blocking msgrcv with an empty queue.
   193  TEST(MsgqueueTest, MsgOpNoMsg) {
   194    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   195  
   196    msgbuf rcv;
   197    EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(rcv.mtext) + 1, 0, IPC_NOWAIT),
   198                SyscallFailsWithErrno(ENOMSG));
   199  }
   200  
   201  // Test non-blocking msgrcv with a non-empty queue, but no messages of wanted
   202  // type.
   203  TEST(MsgqueueTest, MsgOpNoMsgType) {
   204    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   205  
   206    msgbuf buf{1, ""};
   207    ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   208                SyscallSucceeds());
   209  
   210    EXPECT_THAT(msgrcv(queue.get(), &buf, sizeof(buf.mtext) + 1, 2, IPC_NOWAIT),
   211                SyscallFailsWithErrno(ENOMSG));
   212  }
   213  
   214  // Test msgrcv with a larger size message than wanted, and truncation disabled.
   215  TEST(MsgqueueTest, MsgOpTooBig) {
   216    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   217  
   218    msgbuf buf{1, ""};
   219    ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   220                SyscallSucceeds());
   221  
   222    EXPECT_THAT(msgrcv(queue.get(), &buf, sizeof(buf.mtext) - 1, 0, 0),
   223                SyscallFailsWithErrno(E2BIG));
   224  }
   225  
   226  // Test receiving messages based on type.
   227  TEST(MsgqueueTest, MsgRcvType) {
   228    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   229  
   230    // Send messages in an order and receive them in reverse, based on type,
   231    // which shouldn't block.
   232    std::map<int64_t, msgbuf> typeToBuf = {
   233        {1, msgbuf{1, "Message 1."}}, {2, msgbuf{2, "Message 2."}},
   234        {3, msgbuf{3, "Message 3."}}, {4, msgbuf{4, "Message 4."}},
   235        {5, msgbuf{5, "Message 5."}}, {6, msgbuf{6, "Message 6."}},
   236        {7, msgbuf{7, "Message 7."}}, {8, msgbuf{8, "Message 8."}},
   237        {9, msgbuf{9, "Message 9."}}};
   238  
   239    for (auto const& [type, buf] : typeToBuf) {
   240      ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   241                  SyscallSucceeds());
   242    }
   243  
   244    for (int64_t i = typeToBuf.size(); i > 0; i--) {
   245      msgbuf rcv;
   246      EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(typeToBuf[i].mtext) + 1, i, 0),
   247                  SyscallSucceedsWithValue(sizeof(typeToBuf[i].mtext)));
   248      EXPECT_TRUE(typeToBuf[i] == rcv);
   249    }
   250  }
   251  
   252  // Test using MSG_EXCEPT to receive a different-type message.
   253  TEST(MsgqueueTest, MsgExcept) {
   254    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   255  
   256    std::map<int64_t, msgbuf> typeToBuf = {
   257        {1, msgbuf{1, "Message 1."}},
   258        {2, msgbuf{2, "Message 2."}},
   259    };
   260  
   261    for (auto const& [type, buf] : typeToBuf) {
   262      ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   263                  SyscallSucceeds());
   264    }
   265  
   266    for (int64_t i = typeToBuf.size(); i > 0; i--) {
   267      msgbuf actual = typeToBuf[i == 1 ? 2 : 1];
   268      msgbuf rcv;
   269  
   270      EXPECT_THAT(
   271          msgrcv(queue.get(), &rcv, sizeof(actual.mtext) + 1, i, MSG_EXCEPT),
   272          SyscallSucceedsWithValue(sizeof(actual.mtext)));
   273      EXPECT_TRUE(actual == rcv);
   274    }
   275  }
   276  
   277  // Test msgrcv with a negative type.
   278  TEST(MsgqueueTest, MsgRcvTypeNegative) {
   279    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   280  
   281    //  When msgtyp is negative, msgrcv returns the first message with mtype less
   282    //  than or equal to the absolute value.
   283    msgbuf buf{2, "A message."};
   284    msgbuf rcv;
   285  
   286    ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   287                SyscallSucceeds());
   288  
   289    // Nothing is less than or equal to 1.
   290    EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(buf.mtext) + 1, -1, IPC_NOWAIT),
   291                SyscallFailsWithErrno(ENOMSG));
   292  
   293    EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(buf.mtext) + 1, -3, 0),
   294                SyscallSucceedsWithValue(sizeof(buf.mtext)));
   295    EXPECT_TRUE(buf == rcv);
   296  }
   297  
   298  // Test permission-related failure scenarios.
   299  TEST(MsgqueueTest, MsgOpPermissions) {
   300    AutoCapability cap(CAP_IPC_OWNER, false);
   301  
   302    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0000));
   303  
   304    msgbuf buf{1, ""};
   305  
   306    EXPECT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   307                SyscallFailsWithErrno(EACCES));
   308    EXPECT_THAT(msgrcv(queue.get(), &buf, sizeof(buf.mtext), 0, 0),
   309                SyscallFailsWithErrno(EACCES));
   310  }
   311  
   312  // Test limits for messages and queues.
   313  TEST(MsgqueueTest, MsgOpLimits) {
   314    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   315  
   316    msgbuf buf{1, "A message."};
   317  
   318    // Limit for one message.
   319    EXPECT_THAT(msgsnd(queue.get(), &buf, msgMax + 1, 0),
   320                SyscallFailsWithErrno(EINVAL));
   321  
   322    // Limit for queue.
   323    msgmax limit{1, ""};
   324    for (size_t i = 0, msgCount = msgMnb / msgMax; i < msgCount; i++) {
   325      EXPECT_THAT(msgsnd(queue.get(), &limit, sizeof(limit.mtext), 0),
   326                  SyscallSucceeds());
   327    }
   328    EXPECT_THAT(msgsnd(queue.get(), &limit, sizeof(limit.mtext), IPC_NOWAIT),
   329                SyscallFailsWithErrno(EAGAIN));
   330  }
   331  
   332  // MsgCopySupported returns true if MSG_COPY is supported.
   333  bool MsgCopySupported() {
   334    // msgrcv(2) man page states that MSG_COPY flag is available only if the
   335    // kernel was built with the CONFIG_CHECKPOINT_RESTORE option. If MSG_COPY
   336    // is used when the kernel was configured without the option, msgrcv produces
   337    // a ENOSYS error.
   338    // To avoid test failure, we perform a small test using msgrcv, and skip the
   339    // test if errno == ENOSYS. This means that the test will always run on
   340    // gVisor, but may be skipped on native linux.
   341  
   342    auto maybe_id = Msgget(IPC_PRIVATE, 0600);
   343    if (!maybe_id.ok()) {
   344      return false;
   345    }
   346    Queue queue(std::move(maybe_id.ValueOrDie()));
   347    msgbuf buf{1, "Test message."};
   348  
   349    msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0);
   350    return !(msgrcv(queue.get(), &buf, sizeof(buf.mtext) + 1, 0,
   351                    MSG_COPY | IPC_NOWAIT) == -1 &&
   352             errno == ENOSYS);
   353  }
   354  
   355  // Test msgrcv using MSG_COPY.
   356  TEST(MsgqueueTest, MsgCopy) {
   357    SKIP_IF(!MsgCopySupported());
   358  
   359    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   360    msgbuf bufs[5] = {
   361        msgbuf{1, "Message 1."}, msgbuf{2, "Message 2."}, msgbuf{3, "Message 3."},
   362        msgbuf{4, "Message 4."}, msgbuf{5, "Message 5."},
   363    };
   364  
   365    for (auto& buf : bufs) {
   366      ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   367                  SyscallSucceeds());
   368    }
   369  
   370    // Receive a copy of the messages.
   371    for (size_t i = 0, size = sizeof(bufs) / sizeof(bufs[0]); i < size; i++) {
   372      msgbuf buf = bufs[i];
   373      msgbuf rcv;
   374      EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(buf.mtext) + 1, i,
   375                         MSG_COPY | IPC_NOWAIT),
   376                  SyscallSucceedsWithValue(sizeof(buf.mtext)));
   377      EXPECT_TRUE(buf == rcv);
   378    }
   379  
   380    // Re-receive the messages normally.
   381    for (auto& buf : bufs) {
   382      msgbuf rcv;
   383      EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(buf.mtext) + 1, 0, 0),
   384                  SyscallSucceedsWithValue(sizeof(buf.mtext)));
   385      EXPECT_TRUE(buf == rcv);
   386    }
   387  }
   388  
   389  // Test msgrcv using MSG_COPY with invalid arguments.
   390  TEST(MsgqueueTest, MsgCopyInvalidArgs) {
   391    SKIP_IF(!MsgCopySupported());
   392  
   393    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   394    msgbuf rcv;
   395    EXPECT_THAT(msgrcv(queue.get(), &rcv, msgSize, 1, MSG_COPY),
   396                SyscallFailsWithErrno(EINVAL));
   397  
   398    EXPECT_THAT(
   399        msgrcv(queue.get(), &rcv, msgSize, 5, MSG_COPY | MSG_EXCEPT | IPC_NOWAIT),
   400        SyscallFailsWithErrno(EINVAL));
   401  }
   402  
   403  // Test msgrcv using MSG_COPY with invalid indices.
   404  TEST(MsgqueueTest, MsgCopyInvalidIndex) {
   405    SKIP_IF(!MsgCopySupported());
   406  
   407    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   408    msgbuf rcv;
   409    EXPECT_THAT(msgrcv(queue.get(), &rcv, msgSize, -3, MSG_COPY | IPC_NOWAIT),
   410                SyscallFailsWithErrno(ENOMSG));
   411  
   412    EXPECT_THAT(msgrcv(queue.get(), &rcv, msgSize, 5, MSG_COPY | IPC_NOWAIT),
   413                SyscallFailsWithErrno(ENOMSG));
   414  }
   415  
   416  // Test msgrcv (most probably) blocking on an empty queue.
   417  TEST(MsgqueueTest, MsgRcvBlocking) {
   418    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   419    msgbuf buf{1, "A message."};
   420  
   421    ScopedThread t([&] {
   422      msgbuf rcv;
   423      ASSERT_THAT(
   424          RetryEINTR(msgrcv)(queue.get(), &rcv, sizeof(buf.mtext) + 1, 0, 0),
   425          SyscallSucceedsWithValue(sizeof(buf.mtext)));
   426      EXPECT_TRUE(rcv == buf);
   427    });
   428  
   429    // Sleep to try and make msgrcv block before sending a message.
   430    absl::SleepFor(absl::Milliseconds(150));
   431  
   432    EXPECT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   433                SyscallSucceeds());
   434  }
   435  
   436  // Test msgrcv (most probably) waiting for a specific-type message.
   437  TEST(MsgqueueTest, MsgRcvTypeBlocking) {
   438    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   439    msgbuf bufs[5] = {{1, "A message."},
   440                      {1, "A message."},
   441                      {1, "A message."},
   442                      {1, "A message."},
   443                      {2, "A different message."}};
   444  
   445    ScopedThread t([&] {
   446      msgbuf buf = bufs[4];  // Buffer that should be received.
   447      msgbuf rcv;
   448      ASSERT_THAT(
   449          RetryEINTR(msgrcv)(queue.get(), &rcv, sizeof(buf.mtext) + 1, 2, 0),
   450          SyscallSucceedsWithValue(sizeof(buf.mtext)));
   451      EXPECT_TRUE(rcv == buf);
   452    });
   453  
   454    // Sleep to try and make msgrcv block before sending messages.
   455    absl::SleepFor(absl::Milliseconds(150));
   456  
   457    // Send all buffers in order, only last one should be received.
   458    for (auto& buf : bufs) {
   459      EXPECT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   460                  SyscallSucceeds());
   461    }
   462  }
   463  
   464  // Test msgsnd (most probably) blocking on a full queue.
   465  TEST(MsgqueueTest, MsgSndBlocking) {
   466    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   467    msgmax buf{1, ""};  // Has max amount of bytes.
   468  
   469    const size_t msgCount = msgMnb / msgMax;  // Number of messages that can be
   470                                              // sent without blocking.
   471  
   472    ScopedThread t([&] {
   473      // Fill the queue.
   474      for (size_t i = 0; i < msgCount; i++) {
   475        ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   476                    SyscallSucceeds());
   477      }
   478  
   479      // Next msgsnd should block.
   480      ASSERT_THAT(RetryEINTR(msgsnd)(queue.get(), &buf, sizeof(buf.mtext), 0),
   481                  SyscallSucceeds());
   482    });
   483  
   484    const DisableSave ds;  // Too many syscalls.
   485  
   486    // To increase the chance of the last msgsnd blocking before doing a msgrcv,
   487    // we use MSG_COPY option to copy the last index in the queue. As long as
   488    // MSG_COPY fails, the queue hasn't yet been filled. When MSG_COPY succeeds,
   489    // the queue is filled, and most probably, a blocking msgsnd has been made.
   490    msgmax rcv;
   491    while (msgrcv(queue.get(), &rcv, msgMax, msgCount - 1,
   492                  MSG_COPY | IPC_NOWAIT) == -1 &&
   493           errno == ENOMSG) {
   494    }
   495  
   496    // Delay a bit more for the blocking msgsnd.
   497    absl::SleepFor(absl::Milliseconds(100));
   498  
   499    EXPECT_THAT(msgrcv(queue.get(), &rcv, sizeof(buf.mtext), 0, 0),
   500                SyscallSucceedsWithValue(sizeof(buf.mtext)));
   501  }
   502  
   503  // Test removing a queue while a blocking msgsnd is executing.
   504  TEST(MsgqueueTest, MsgSndRmWhileBlocking) {
   505    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   506  
   507    // Number of messages that can be sent without blocking.
   508    const size_t msgCount = msgMnb / msgMax;
   509  
   510    ScopedThread t([&] {
   511      // Fill the queue.
   512      msgmax buf{1, ""};
   513      for (size_t i = 0; i < msgCount; i++) {
   514        EXPECT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   515                    SyscallSucceeds());
   516      }
   517  
   518      // Next msgsnd should block. Because we're repeating on EINTR, msgsnd may
   519      // race with msgctl(IPC_RMID) and return EINVAL.
   520      EXPECT_THAT(RetryEINTR(msgsnd)(queue.get(), &buf, sizeof(buf.mtext), 0),
   521                  SyscallFails());
   522      EXPECT_TRUE((errno == EIDRM || errno == EINVAL));
   523    });
   524  
   525    const DisableSave ds;  // Too many syscalls.
   526  
   527    // Similar to MsgSndBlocking, we do this to increase the chance of msgsnd
   528    // blocking before removing the queue.
   529    msgmax rcv;
   530    while (msgrcv(queue.get(), &rcv, msgMax, msgCount - 1,
   531                  MSG_COPY | IPC_NOWAIT) == -1 &&
   532           errno == ENOMSG) {
   533    }
   534    absl::SleepFor(absl::Milliseconds(100));
   535  
   536    EXPECT_THAT(msgctl(queue.release(), IPC_RMID, nullptr), SyscallSucceeds());
   537  }
   538  
   539  // Test removing a queue while a blocking msgrcv is executing.
   540  TEST(MsgqueueTest, MsgRcvRmWhileBlocking) {
   541    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   542  
   543    ScopedThread t([&] {
   544      // Because we're repeating on EINTR, msgsnd may race with msgctl(IPC_RMID)
   545      // and return EINVAL.
   546      msgbuf rcv;
   547      EXPECT_THAT(RetryEINTR(msgrcv)(queue.get(), &rcv, 1, 2, 0), SyscallFails());
   548      EXPECT_TRUE(errno == EIDRM || errno == EINVAL);
   549    });
   550  
   551    // Sleep to try and make msgrcv block before sending messages.
   552    absl::SleepFor(absl::Milliseconds(150));
   553  
   554    EXPECT_THAT(msgctl(queue.release(), IPC_RMID, nullptr), SyscallSucceeds());
   555  }
   556  
   557  // Test a collection of msgsnd/msgrcv operations in different processes.
   558  TEST(MsgqueueTest, MsgOpGeneral) {
   559    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   560  
   561    // Create multiple sending/receiving threads that send messages back and
   562    // forth. There's a matching recv for each send, so by the end of the test,
   563    // all threads should succeed and return.
   564    const std::vector<msgbuf> msgs = {
   565        msgbuf{1, "Message 1."}, msgbuf{2, "Message 2."}, msgbuf{3, "Message 3."},
   566        msgbuf{4, "Message 4."}, msgbuf{5, "Message 5."}};
   567  
   568    auto receiver = [&](int i) {
   569      return [i, &msgs, &queue]() {
   570        const msgbuf& target = msgs[i];
   571        msgbuf rcv;
   572        EXPECT_THAT(RetryEINTR(msgrcv)(queue.get(), &rcv,
   573                                       sizeof(target.mtext) + 1, target.mtype, 0),
   574                    SyscallSucceedsWithValue(sizeof(target.mtext)));
   575        EXPECT_EQ(rcv.mtype, target.mtype);
   576        EXPECT_EQ(0, memcmp(rcv.mtext, target.mtext, sizeof(target.mtext)));
   577      };
   578    };
   579  
   580    ScopedThread r1(receiver(0));
   581    ScopedThread r2(receiver(1));
   582    ScopedThread r3(receiver(2));
   583    ScopedThread r4(receiver(3));
   584    ScopedThread r5(receiver(4));
   585    ScopedThread r6(receiver(0));
   586    ScopedThread r7(receiver(1));
   587    ScopedThread r8(receiver(2));
   588    ScopedThread r9(receiver(3));
   589    ScopedThread r10(receiver(4));
   590  
   591    auto sender = [&](int i) {
   592      return [i, &msgs, &queue]() {
   593        const msgbuf& target = msgs[i];
   594        EXPECT_THAT(
   595            RetryEINTR(msgsnd)(queue.get(), &target, sizeof(target.mtext), 0),
   596            SyscallSucceeds());
   597      };
   598    };
   599  
   600    ScopedThread s1(sender(0));
   601    ScopedThread s2(sender(1));
   602    ScopedThread s3(sender(2));
   603    ScopedThread s4(sender(3));
   604    ScopedThread s5(sender(4));
   605    ScopedThread s6(sender(0));
   606    ScopedThread s7(sender(1));
   607    ScopedThread s8(sender(2));
   608    ScopedThread s9(sender(3));
   609    ScopedThread s10(sender(4));
   610  }
   611  
   612  void empty_sighandler(int sig, siginfo_t* info, void* context) {}
   613  
   614  TEST(MsgqueueTest, InterruptRecv) {
   615    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   616    char buf[64];
   617  
   618    absl::Notification done, exit;
   619  
   620    // Thread calling msgrcv with no corresponding send. It would block forever,
   621    // but we'll interrupt with a signal below.
   622    ScopedThread t([&] {
   623      struct sigaction sa = {};
   624      sa.sa_sigaction = empty_sighandler;
   625      sigfillset(&sa.sa_mask);
   626      sa.sa_flags = SA_SIGINFO;
   627      auto cleanup_sigaction =
   628          ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(kInterruptSignal, sa));
   629      auto sa_cleanup = ASSERT_NO_ERRNO_AND_VALUE(
   630          ScopedSignalMask(SIG_UNBLOCK, kInterruptSignal));
   631  
   632      EXPECT_THAT(msgrcv(queue.get(), &buf, sizeof(buf), 0, 0),
   633                  SyscallFailsWithErrno(EINTR));
   634  
   635      done.Notify();
   636      exit.WaitForNotification();
   637    });
   638  
   639    const DisableSave ds;  // Too many syscalls.
   640  
   641    // We want the signal to arrive while msgrcv is blocking, but not after the
   642    // thread has exited. Signals that arrive before msgrcv are no-ops.
   643    do {
   644      EXPECT_THAT(kill(getpid(), kInterruptSignal), SyscallSucceeds());
   645      absl::SleepFor(absl::Milliseconds(100));  // Rate limit.
   646    } while (!done.HasBeenNotified());
   647  
   648    exit.Notify();
   649    t.Join();
   650  }
   651  
   652  TEST(MsgqueueTest, InterruptSend) {
   653    Queue queue = ASSERT_NO_ERRNO_AND_VALUE(Msgget(IPC_PRIVATE, 0600));
   654    msgmax buf{1, ""};
   655    // Number of messages that can be sent without blocking.
   656    const size_t msgCount = msgMnb / msgMax;
   657  
   658    // Fill the queue.
   659    for (size_t i = 0; i < msgCount; i++) {
   660      ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   661                  SyscallSucceeds());
   662    }
   663  
   664    absl::Notification done, exit;
   665  
   666    // Thread calling msgsnd on a full queue. It would block forever, but we'll
   667    // interrupt with a signal below.
   668    ScopedThread t([&] {
   669      struct sigaction sa = {};
   670      sa.sa_sigaction = empty_sighandler;
   671      sigfillset(&sa.sa_mask);
   672      sa.sa_flags = SA_SIGINFO;
   673      auto cleanup_sigaction =
   674          ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(kInterruptSignal, sa));
   675      auto sa_cleanup = ASSERT_NO_ERRNO_AND_VALUE(
   676          ScopedSignalMask(SIG_UNBLOCK, kInterruptSignal));
   677  
   678      EXPECT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   679                  SyscallFailsWithErrno(EINTR));
   680  
   681      done.Notify();
   682      exit.WaitForNotification();
   683    });
   684  
   685    const DisableSave ds;  // Too many syscalls.
   686  
   687    // We want the signal to arrive while msgsnd is blocking, but not after the
   688    // thread has exited. Signals that arrive before msgsnd are no-ops.
   689    do {
   690      EXPECT_THAT(kill(getpid(), kInterruptSignal), SyscallSucceeds());
   691      absl::SleepFor(absl::Milliseconds(100));  // Rate limit.
   692    } while (!done.HasBeenNotified());
   693  
   694    exit.Notify();
   695    t.Join();
   696  }
   697  
   698  // Test msgctl with IPC_STAT option.
   699  TEST(MsgqueueTest, MsgCtlIpcStat) {
   700    // The timestamps only have a resolution of seconds; slow down so we actually
   701    // see the timestamps change.
   702    auto start = absl::Now();
   703    absl::SleepFor(absl::Milliseconds(1010));
   704  
   705    Queue queue(msgget(IPC_PRIVATE, 0600));
   706    ASSERT_THAT(queue.get(), SyscallSucceeds());
   707  
   708    const uid_t uid = getuid();
   709    const gid_t gid = getgid();
   710    const pid_t pid = getpid();
   711  
   712    struct msqid_ds ds;
   713    ASSERT_THAT(msgctl(queue.get(), IPC_STAT, &ds), SyscallSucceeds());
   714  
   715    EXPECT_EQ(ds.msg_perm.__key, IPC_PRIVATE);
   716    EXPECT_EQ(ds.msg_perm.uid, uid);
   717    EXPECT_EQ(ds.msg_perm.gid, gid);
   718    EXPECT_EQ(ds.msg_perm.cuid, uid);
   719    EXPECT_EQ(ds.msg_perm.cgid, gid);
   720    EXPECT_EQ(ds.msg_perm.mode, 0600);
   721  
   722    EXPECT_EQ(ds.msg_stime, 0);
   723    EXPECT_EQ(ds.msg_rtime, 0);
   724    EXPECT_GE(ds.msg_ctime, absl::ToTimeT(start));
   725  
   726    EXPECT_EQ(ds.msg_cbytes, 0);
   727    EXPECT_EQ(ds.msg_qnum, 0);
   728    EXPECT_EQ(ds.msg_qbytes, msgMnb);
   729    EXPECT_EQ(ds.msg_lspid, 0);
   730    EXPECT_EQ(ds.msg_lrpid, 0);
   731  
   732    auto pre_send = absl::Now();
   733    absl::SleepFor(absl::Milliseconds(1010));
   734  
   735    msgbuf buf{1, "A message."};
   736    ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   737                SyscallSucceeds());
   738  
   739    ASSERT_THAT(msgctl(queue.get(), IPC_STAT, &ds), SyscallSucceeds());
   740  
   741    EXPECT_GE(ds.msg_stime, absl::ToTimeT(pre_send));
   742    EXPECT_EQ(ds.msg_rtime, 0);
   743    EXPECT_GE(ds.msg_ctime, absl::ToTimeT(start));
   744  
   745    EXPECT_EQ(ds.msg_cbytes, msgSize);
   746    EXPECT_EQ(ds.msg_qnum, 1);
   747    EXPECT_EQ(ds.msg_qbytes, msgMnb);
   748    EXPECT_EQ(ds.msg_lspid, pid);
   749    EXPECT_EQ(ds.msg_lrpid, 0);
   750  
   751    auto pre_receive = absl::Now();
   752    absl::SleepFor(absl::Milliseconds(1010));
   753  
   754    ASSERT_THAT(msgrcv(queue.get(), &buf, sizeof(buf.mtext), 0, 0),
   755                SyscallSucceedsWithValue(msgSize));
   756  
   757    ASSERT_THAT(msgctl(queue.get(), IPC_STAT, &ds), SyscallSucceeds());
   758  
   759    EXPECT_GE(ds.msg_stime, absl::ToTimeT(pre_send));
   760    EXPECT_GE(ds.msg_rtime, absl::ToTimeT(pre_receive));
   761    EXPECT_GE(ds.msg_ctime, absl::ToTimeT(start));
   762  
   763    EXPECT_EQ(ds.msg_cbytes, 0);
   764    EXPECT_EQ(ds.msg_qnum, 0);
   765    EXPECT_EQ(ds.msg_qbytes, msgMnb);
   766    EXPECT_EQ(ds.msg_lspid, pid);
   767    EXPECT_EQ(ds.msg_lrpid, pid);
   768  }
   769  
   770  // Test msgctl with IPC_STAT option on a write-only queue.
   771  TEST(MsgqueueTest, MsgCtlIpcStatWriteOnly) {
   772    // Drop CAP_IPC_OWNER which allows us to bypass permissions.
   773    AutoCapability cap(CAP_IPC_OWNER, false);
   774  
   775    Queue queue(msgget(IPC_PRIVATE, 0200));
   776    ASSERT_THAT(queue.get(), SyscallSucceeds());
   777  
   778    struct msqid_ds ds;
   779    ASSERT_THAT(msgctl(queue.get(), IPC_STAT, &ds),
   780                SyscallFailsWithErrno(EACCES));
   781  }
   782  
   783  // Test msgctl with IPC_SET option.
   784  TEST(MsgqueueTest, MsgCtlIpcSet) {
   785    Queue queue(msgget(IPC_PRIVATE, 0600));
   786    ASSERT_THAT(queue.get(), SyscallSucceeds());
   787  
   788    struct msqid_ds ds;
   789    ASSERT_THAT(msgctl(queue.get(), IPC_STAT, &ds), SyscallSucceeds());
   790    EXPECT_EQ(ds.msg_perm.mode, 0600);
   791  
   792    ds.msg_perm.mode = 0777;
   793    ASSERT_THAT(msgctl(queue.get(), IPC_SET, &ds), SyscallSucceeds());
   794  
   795    ASSERT_THAT(msgctl(queue.get(), IPC_STAT, &ds), SyscallSucceeds());
   796    EXPECT_EQ(ds.msg_perm.mode, 0777);
   797  }
   798  
   799  // Test increasing msg_qbytes beyond limit with IPC_SET.
   800  TEST(MsgqueueTest, MsgCtlIpcSetMaxBytes) {
   801    // Drop CAP_SYS_RESOURCE which allows us to increase msg_qbytes beyond the
   802    // system parameter MSGMNB.
   803    AutoCapability cap(CAP_SYS_RESOURCE, false);
   804  
   805    Queue queue(msgget(IPC_PRIVATE, 0600));
   806    ASSERT_THAT(queue.get(), SyscallSucceeds());
   807  
   808    struct msqid_ds ds;
   809    ASSERT_THAT(msgctl(queue.get(), IPC_STAT, &ds), SyscallSucceeds());
   810    EXPECT_EQ(ds.msg_qbytes, msgMnb);
   811  
   812    ds.msg_qbytes = msgMnb - 10;
   813    ASSERT_THAT(msgctl(queue.get(), IPC_SET, &ds), SyscallSucceeds());
   814  
   815    ASSERT_THAT(msgctl(queue.get(), IPC_STAT, &ds), SyscallSucceeds());
   816    EXPECT_EQ(ds.msg_qbytes, msgMnb - 10);
   817  
   818    ds.msg_qbytes = msgMnb + 10;
   819    EXPECT_THAT(msgctl(queue.get(), IPC_SET, &ds), SyscallFailsWithErrno(EPERM));
   820  }
   821  
   822  // Test msgctl with IPC_INFO option.
   823  TEST(MsgqueueTest, MsgCtlIpcInfo) {
   824    struct msginfo info;
   825    ASSERT_THAT(msgctl(0, IPC_INFO, reinterpret_cast<struct msqid_ds*>(&info)),
   826                SyscallSucceeds());
   827  
   828    EXPECT_GT(info.msgmax, 0);
   829    EXPECT_GT(info.msgmni, 0);
   830    EXPECT_GT(info.msgmnb, 0);
   831    EXPECT_EQ(info.msgpool, msgPool);
   832    EXPECT_EQ(info.msgmap, msgMap);
   833    EXPECT_EQ(info.msgssz, msgSsz);
   834    EXPECT_EQ(info.msgtql, msgTql);
   835  }
   836  
   837  // Test msgctl with MSG_INFO option.
   838  TEST(MsgqueueTest, MsgCtlMsgInfo) {
   839    struct msginfo info;
   840    ASSERT_THAT(msgctl(0, MSG_INFO, reinterpret_cast<struct msqid_ds*>(&info)),
   841                SyscallSucceeds());
   842  
   843    EXPECT_GT(info.msgmax, 0);
   844    EXPECT_GT(info.msgmni, 0);
   845    EXPECT_GT(info.msgmnb, 0);
   846    EXPECT_EQ(info.msgpool, 0);  // Number of queues in the system.
   847    EXPECT_EQ(info.msgmap, 0);   // Total number of messages in all queues.
   848    EXPECT_EQ(info.msgtql, 0);   // Total number of bytes in all messages.
   849    EXPECT_EQ(info.msgssz, msgSsz);
   850  
   851    // Add a queue and a message.
   852    Queue queue(msgget(IPC_PRIVATE, 0600));
   853    ASSERT_THAT(queue.get(), SyscallSucceeds());
   854  
   855    msgbuf buf{1, "A message."};
   856    ASSERT_THAT(msgsnd(queue.get(), &buf, sizeof(buf.mtext), 0),
   857                SyscallSucceeds());
   858  
   859    ASSERT_THAT(msgctl(0, MSG_INFO, reinterpret_cast<struct msqid_ds*>(&info)),
   860                SyscallSucceeds());
   861  
   862    EXPECT_GT(info.msgmax, 0);
   863    EXPECT_GT(info.msgmni, 0);
   864    EXPECT_GT(info.msgmnb, 0);
   865    EXPECT_EQ(info.msgpool, 1);       // Number of queues in the system.
   866    EXPECT_EQ(info.msgmap, 1);        // Total number of messages in all queues.
   867    EXPECT_EQ(info.msgtql, msgSize);  // Total number of bytes in all messages.
   868    EXPECT_EQ(info.msgssz, msgSsz);
   869  }
   870  
   871  }  // namespace
   872  }  // namespace testing
   873  }  // namespace gvisor
   874  
   875  int main(int argc, char** argv) {
   876    // Some tests depend on delivering a signal to the main thread. Block the
   877    // target signal so that any other threads created by TestInit will also have
   878    // the signal blocked.
   879    sigset_t set;
   880    sigemptyset(&set);
   881    sigaddset(&set, gvisor::testing::kInterruptSignal);
   882    TEST_PCHECK(sigprocmask(SIG_BLOCK, &set, nullptr) == 0);
   883  
   884    gvisor::testing::TestInit(&argc, &argv);
   885    return gvisor::testing::RunAllTests();
   886  }