Skip to contentSkip to conversation

syscalls/msgctl13: fix error when run on the new system

PATCH Superseded Cui Bixuan 2 participants 7 messages Apr 9, 2016 – Apr 14, 2016

lore
Share & tools
lore

Cui Bixuan

author
#0 lore raw

PATCH 1/1 syscalls/msgctl13: fix error when run on the new system

The msqid is 0 when a new message queue is created by msgget() on the new system. Then 'TEST(msgget(msg_q, MSG_RW))' succeed unexpectedly.

Run 'msg_q = msgget(IPC_PRIVATE, MSG_RW)', we get:
msgget(IPC_PRIVATE, 0600) = 0
The msg_q is 0 when create it on the new system.Next:

	msgctl(0, IPC_RMID, 0)                  = 0
	msgget(IPC_PRIVATE, 0600)               = 32768

The msg_q is equal to IPC_PRIVATE which is defined at kernel, So msgget() will create a new message queue again and return success unexpectedly.

---
 testcases/kernel/syscalls/ipc/msgctl/msgctl13.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
testcases/kernel/syscalls/ipc/msgctl/msgctl13.c +5 -3
index e170d6b..721dd88 100644
@@ -60,9 +60,11 @@ static void msgctl_verify(void)
 {
 	int msg_q;
 
-	msg_q = msgget(IPC_PRIVATE, MSG_RW);
-	if (msg_q == -1)
-		tst_brkm(TBROK, cleanup, "Can't create message queue");
+	do {
+		msg_q = msgget(IPC_PRIVATE, MSG_RW);
+		if (msg_q == -1)
+			tst_brkm(TBROK, cleanup, "Can't create message queue");
+	} while (!msg_q);
 
 	TEST(msgctl(msg_q, IPC_RMID, NULL));
 
Signature · 1 line
1.8.3.4
#1 lore raw

PATCH 1/1 syscalls/msgctl13: fix error when run on the new system

Hi!

Quoted 7 lines

The msqid is 0 when a new message queue is created by msgget() on the new system. Then 'TEST(msgget(msg_q, MSG_RW))' succeed unexpectedly.

Run 'msg_q = msgget(IPC_PRIVATE, MSG_RW)', we get:
msgget(IPC_PRIVATE, 0600) = 0
The msg_q is 0 when create it on the new system.Next:

Quoted 6 lines
	msgctl(0, IPC_RMID, 0)                  = 0
	msgget(IPC_PRIVATE, 0600)               = 32768

The msg_q is equal to IPC_PRIVATE which is defined at kernel, So msgget() will create a new message queue again and return success unexpectedly.

I've been able to reproduce the failure, for me the test failed on first attempt after machine reboot then continued to work fine as the ID returned from kernel seems to start at 0 and increases slowly.

I guess that we do not see the failure in LTP since there are other msgctl() testcases executed before it.

Also running the testcase about 7000 times wraps around the msgid and makes the test fail (you have to remove the message queue with key 0 by hand since the test leaves it on the system).

Quoted 13 lines
---
 testcases/kernel/syscalls/ipc/msgctl/msgctl13.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
testcases/kernel/syscalls/ipc/msgctl/msgctl13.c +0 -0
index e170d6b..721dd88 100644
@@ -60,9 +60,11 @@ static void msgctl_verify(void)
 {
 	int msg_q;
 

testcases/kernel/syscalls/ipc/msgctl/msgctl13.c static void msgctl_verify(void) · line 69

Quoted 10 lines
testcases/kernel/syscalls/ipc/msgctl/msgctl13.c +5 -3
-	msg_q = msgget(IPC_PRIVATE, MSG_RW);
-	if (msg_q == -1)
-		tst_brkm(TBROK, cleanup, "Can't create message queue");
+	do {
+		msg_q = msgget(IPC_PRIVATE, MSG_RW);
+		if (msg_q == -1)
+			tst_brkm(TBROK, cleanup, "Can't create message queue");
+	} while (!msg_q);
 
 	TEST(msgctl(msg_q, IPC_RMID, NULL));

This change leaks memory (leaves the message queue with key = 0 on the system) and relies on a fact that IPC_PRIVATE == 0 which may not be necessarilly true. Can't we instead do IPC_STAT on the msg_q and expect it to fail?

Signature · 2 lines
Cyril Hrubis
[email protected]
author
#2 lore raw

PATCH v2 1/1 syscalls/msgctl13: fix error when run on the new system

The msqid is 0 when a new message queue is created by msgget() on the new system. Then 'TEST(msgget(msg_q, MSG_RW))' succeed unexpectedly.

Run 'msg_q = msgget(IPC_PRIVATE, MSG_RW)', we get:
msgget(IPC_PRIVATE, 0600) = 0
The msg_q is 0 when create it on the new system.Next:

	msgctl(0, IPC_RMID, 0)                  = 0
	msgget(IPC_PRIVATE, 0600)               = 32768

The msg_q is equal to IPC_PRIVATE which is defined at kernel, So msgget() will create a new message queue again and return success unexpectedly.

Use msgctl with IPC_STAT to check it.

---
 testcases/kernel/syscalls/ipc/msgctl/msgctl13.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
testcases/kernel/syscalls/ipc/msgctl/msgctl13.c +4 -2
index e170d6b..50d48d4 100644
@@ -28,6 +28,8 @@
 
 char *TCID = "msgctl13";
 int TST_TOTAL = 1;
+static struct msqid_ds buf;
+
 static void msgctl_verify(void);
 
 int main(int argc, char *argv[])
@@ -72,8 +74,8 @@ static void msgctl_verify(void)
 		return;
 	}
 
-	TEST(msgget(msg_q, MSG_RW));
-	if (TEST_ERRNO == ENOENT)
+	TEST(msgctl(msg_q, IPC_STAT, &buf));
+	if (TEST_ERRNO == EINVAL)
 		tst_resm(TPASS, "msgctl() test IPC_RMID succeeded");
 	else
 		tst_resm(TFAIL, "msgctl() test IPC_RMID failed unexpectedly");
Signature · 1 line
1.8.3.4
#3 lore raw

PATCH v2 1/1 syscalls/msgctl13: fix error when run on the new system

Hi!
I've reworded the commit description a bit and pushed, thanks.

Signature · 2 lines
Cyril Hrubis
[email protected]
author
#4 lore raw

PATCH 1/1 syscalls/msgctl13: fix error when run on the new system

In reply to Cyril Hrubis
Quoted 4 lines · Cyril Hrubis

This change leaks memory (leaves the message queue with key = 0 on the system) and relies on a fact that IPC_PRIVATE == 0 which may not be necessarilly true. Can't we instead do IPC_STAT on the msg_q and expect it to fail?

Use msgctl with IPC_STAT to check it is better :-);

But why it return EINVAL, instead of EIDRM?

Thanks
Cui Bixuan

Quoted 2 lines
Signature · 2 lines
Cyril Hrubis
[email protected]
#5 lore raw

PATCH 1/1 syscalls/msgctl13: fix error when run on the new system

Hi!

Quoted 1 line

But why it return EINVAL, instead of EIDRM?

Since at the point we do the IPC_STAT the ID is allready unused hence it's not valid anymore. You get EIDRM only in case that process is waiting in kernel (for example in msgrcv()) while another process removes the queue.

Signature · 2 lines
Cyril Hrubis
[email protected]
author
#6 lore raw

PATCH 1/1 syscalls/msgctl13: fix error when run on the new system

Quoted 7 lines · Cyril Hrubis

Hi!

Quoted 1 line

But why it return EINVAL, instead of EIDRM?

Since at the point we do the IPC_STAT the ID is allready unused hence it's not valid anymore. You get EIDRM only in case that process is waiting in kernel (for example in msgrcv()) while another process removes the queue.

Get it, Thank you.

Quoted 1 line