Bug 243103 - fork fails to clone open message queue handles into the child process (in violation of POSIX std.)
Summary: fork fails to clone open message queue handles into the child process (in vio...
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: standards (show other bugs)
Version: 12.0-RELEASE
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-standards mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-01-05 04:53 UTC by Ronald F. Guilmette
Modified: 2020-01-27 22:37 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ronald F. Guilmette 2020-01-05 04:53:41 UTC
POSIX POSIX 1003.1b-1993 in Section Section 3.1.1.2(14) requires that the fork() system call must clone all currently open message queue descriptors into the child process.  Currently, the FreeBSD kernel is evidently failing to do this, as is illustrated by the following simple test program:

https://pastebin.com/raw/Dya0XEhf

(Note that the test program works fine and produces the desired and expected results when compiled and run under Ubuntu 18.04 LTS.)

I am NOT the first person to have noticed this very serious and fundamental kernel non-conformance with the POSIX standard:

https://stackoverflow.com/questions/19500194/freebsd-doesnt-preserve-posix-message-queue-descriptions-over-forks

https://forums.freebsd.org/threads/fork-does-not-properly-copy-posix-message-queue-descriptions.42678/


P.S.  If it were possible to do so, I would mark this as "URGENT".  For me, this particular non-feature in the kernel is likely to cause great difficulties.
Comment 1 Warner Losh freebsd_committer 2020-01-05 05:28:12 UTC
Try

diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index b738dbc77b4..913f03e12d5 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -229,7 +229,7 @@ static uma_zone_t           mqueue_zone;
 static uma_zone_t              mvdata_zone;
 static uma_zone_t              mqnoti_zone;
 static struct vop_vector       mqfs_vnodeops;
-static struct fileops          mqueueops;
+static struct fileops          mqueueops = {.fo_flags = DFLAG_PASSABLE};
 static unsigned                        mqfs_osd_jail_slot;

 /*
Comment 2 Ronald F. Guilmette 2020-01-05 05:42:28 UTC
Wow!  Thanks!  I had not anticipated quite such a quick turaround on a kernel bug.  And on a Saturday night no less!  Seriously, thanks much.

I do not wish to be impertinent, and I certainly intend to try this out, but it is much more important to me to have the bug fixed for everyone, than just for me, personally, so that I can, in future, give people either sources or pre-compiled binaries and say to them "Here, just run this on your FreeBSD system." and have faith that it will work.  So I have to ask, is it your intention to do a commit on this fix?
Comment 3 Warner Losh freebsd_committer 2020-01-05 06:07:21 UTC
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index b738dbc77b4..07346701857 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -2669,6 +2669,7 @@ static struct fileops mqueueops = {
        .fo_chown               = mqf_chown,
        .fo_sendfile            = invfo_sendfile,
        .fo_fill_kinfo          = mqf_fill_kinfo,
+       .fo_flags               = DFLAG_PASSABLE,
 };

 static struct vop_vector mqfs_vnodeops = {


may work better... It compiles, but I've not tested it.
Comment 4 Warner Losh freebsd_committer 2020-01-05 06:17:13 UTC
(In reply to Ronald F. Guilmette from comment #2)
My intent is to commit a verified working fix that passes the review process.
Since I only have your simple test caee, I can get that working, but if it fails in your more complex application, only you can tell me that. I posted my fix quickly so you can test while I sort out a minor snafu with my testing machine
Comment 5 Warner Losh freebsd_committer 2020-01-05 06:22:25 UTC
snafu sorted, my patch makes the test case work.
Comment 6 Warner Losh freebsd_committer 2020-01-05 06:38:50 UTC
This bug appears to date back to r110908 (2003) where alfred failed to tag mqueue as a passable fd type and then r223866 (2011) by jonathan used the new flag in fdcopy, which fork uses which is where mqueuefs actually broke this test case. so FreeBSD 8 had it still working but FreeBSD 9 and newer didn't.
Comment 7 Warner Losh freebsd_committer 2020-01-05 06:44:39 UTC
https://reviews.freebsd.org/D23038
Comment 8 Ronald F. Guilmette 2020-01-05 06:48:23 UTC
Amazing.  I guess that there aren't a lot of people out there using these message queues to try to pass messages between related familial processes.
Comment 9 Warner Losh freebsd_committer 2020-01-05 06:56:23 UTC
Ah, my mistake. Alfred didn't miss this, but it was this way from when it was committed in r152825 in 2005.
Comment 10 commit-hook freebsd_committer 2020-01-27 22:37:37 UTC
A commit references this bug:

Author: imp
Date: Mon Jan 27 22:36:54 UTC 2020
New revision: 357183
URL: https://svnweb.freebsd.org/changeset/base/357183

Log:
  Make mqueue objects work across a fork again.

  In r110908 (2003) alfred added DFLAG_PASSABLE to tag those types of FD
  that can be passed via unix pipes, but mqueuefs didn't exist
  yet. Later, in r152825 (2005) davidxu neglected to include
  DFLAG_PASSABLE since people don't normally pass these things via unix
  sockets (it's a FreeBSD implementation detail that it's a file
  descriptor, nobody noticed). Then r223866 (2011) by jonathan used the
  new flag in fdcopy, which fork uses. Due to that, mqueuefs actually
  broke mqueue objects being propagated by fork. No mention of mqueuefs
  was made in r223866, so I think it was an unintended consequence.

  Fix this by tagging mqueuefs as passable as well. They were prior to
  alfred's change (and it's clear there's no intent in his change to
  change this behavior), and POSIX requires this to be the case as well.

  PR: 243103
  Reviewed by: kib@, jiles@
  Differential Revision: https://reviews.freebsd.org/D23038

Changes:
  head/sys/kern/uipc_mqueue.c