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 }