Ignoring the return value of mach_port_mod_ref() causes the situation that when the reference count of the io server port is full, the caller of dup() still supposes a new file discriptor is allocated. In this patch we check the return value of mach_port_mod_ref() and return an error when it fails.
Signed-off-by: Zhaoming Luo <zhming...@163.com> --- sysdeps/mach/hurd/fcntl.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c index a65c190c..d97226cd 100644 --- a/sysdeps/mach/hurd/fcntl.c +++ b/sysdeps/mach/hurd/fcntl.c @@ -83,18 +83,34 @@ __libc_fcntl (int fd, int cmd, ...) result = -1; else { - /* Give the ports each a user ref for the new descriptor. */ - __mach_port_mod_refs (__mach_task_self (), port, + /* Give the ports (i.e. `ctty` and `port`) each a user ref for + the new descriptor. */ + err = __mach_port_mod_refs (__mach_task_self (), port, MACH_PORT_RIGHT_SEND, 1); - if (ctty != MACH_PORT_NULL) - __mach_port_mod_refs (__mach_task_self (), ctty, - MACH_PORT_RIGHT_SEND, 1); - - /* Install the ports and flags in the new descriptor. */ - if (ctty != MACH_PORT_NULL) - _hurd_port_set (&new->ctty, ctty); - new->flags = flags; - _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */ + + if (err) + { + /* When an error occurs during giving a user ref to the + io server port */ + result = -1; + + if (err == KERN_UREFS_OVERFLOW) + errno = EMFILE; + else + errno = EINVAL; + } + else + { + if (ctty != MACH_PORT_NULL) + __mach_port_mod_refs (__mach_task_self (), ctty, + MACH_PORT_RIGHT_SEND, 1); + + /* Install the ports and flags in the new descriptor. */ + if (ctty != MACH_PORT_NULL) + _hurd_port_set (&new->ctty, ctty); + new->flags = flags; + _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */ + } } HURD_CRITICAL_END; -- 2.47.2