diff options
author | Zhaoming Luo <zhmingluo@163.com> | 2025-03-10 16:44:09 +0800 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2025-04-18 02:27:26 +0200 |
commit | e150ee870907e1c5ded4aad8d22a92a98f59d243 (patch) | |
tree | e7628ee9a2114eb5b1356430eddb090678fa0476 | |
parent | 1c9ac027a5deb6c3e026be0e88d38959529e6102 (diff) | |
download | glibc-e150ee870907e1c5ded4aad8d22a92a98f59d243.zip glibc-e150ee870907e1c5ded4aad8d22a92a98f59d243.tar.gz glibc-e150ee870907e1c5ded4aad8d22a92a98f59d243.tar.bz2 |
hurd: Check return value of mach_port_mod_refs() in the dup routine of fcntl()
Message-ID: <20250310084409.24177-1-zhmingluo@163.com>
-rw-r--r-- | sysdeps/mach/hurd/dup3.c | 62 | ||||
-rw-r--r-- | sysdeps/mach/hurd/fcntl.c | 53 |
2 files changed, 87 insertions, 28 deletions
diff --git a/sysdeps/mach/hurd/dup3.c b/sysdeps/mach/hurd/dup3.c index 22af45b..49545ae 100644 --- a/sysdeps/mach/hurd/dup3.c +++ b/sysdeps/mach/hurd/dup3.c @@ -69,6 +69,7 @@ __dup3 (int fd, int fd2, int flags) { /* Get a hold of the destination descriptor. */ struct hurd_fd *d2; + error_t err; __mutex_lock (&_hurd_dtable_lock); @@ -107,22 +108,51 @@ __dup3 (int fd, int fd2, int flags) } else { - /* Give the ports each a user ref for the new descriptor. */ - __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 slot. */ - __spin_lock (&d2->port.lock); - if (flags & O_CLOEXEC) - d2->flags = d_flags | FD_CLOEXEC; - else - /* dup clears FD_CLOEXEC. */ - d2->flags = d_flags & ~FD_CLOEXEC; - _hurd_port_set (&d2->ctty, ctty); - _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */ + /* Give the io server port a user ref for the new descriptor. */ + err = __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_SEND, 1); + + if (err == KERN_UREFS_OVERFLOW) + fd2 = __hurd_fail (EMFILE); + else if (err) + fd2 = __hurd_fail (EINVAL); + else if (ctty != MACH_PORT_NULL) + { + /* We have confirmed the io server port has got a user ref + count, now give ctty port a user ref for the new + descriptor. */ + err = __mach_port_mod_refs (__mach_task_self (), ctty, + MACH_PORT_RIGHT_SEND, 1); + + if (err) + { + /* In this case the io server port has got a ref count + but the ctty port failed to get one, so we need to + clean the ref count we just assigned. */ + __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_SEND, -1); + + if (err == KERN_UREFS_OVERFLOW) + fd2 = __hurd_fail (EMFILE); + else + fd2 = __hurd_fail (EINVAL); + } + } + + if (!err) + { + /* The ref counts of the ports are incremented + successfully. */ + /* Install the ports and flags in the new descriptor slot. */ + __spin_lock (&d2->port.lock); + if (flags & O_CLOEXEC) + d2->flags = d_flags | FD_CLOEXEC; + else + /* dup clears FD_CLOEXEC. */ + d2->flags = d_flags & ~FD_CLOEXEC; + _hurd_port_set (&d2->ctty, ctty); + _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */ + } } } diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c index a65c190..de576af 100644 --- a/sysdeps/mach/hurd/fcntl.c +++ b/sysdeps/mach/hurd/fcntl.c @@ -83,18 +83,47 @@ __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, - 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. */ + /* Give the io server port a user ref for the new descriptor. */ + err = __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_SEND, 1); + + if (err == KERN_UREFS_OVERFLOW) + result = __hurd_fail (EMFILE); + else if (err) + result = __hurd_fail (EINVAL); + else if (ctty != MACH_PORT_NULL) + { + /* We have confirmed the io server port has got a user ref + count, now give ctty port a user ref for the new + descriptor. */ + err = __mach_port_mod_refs (__mach_task_self (), ctty, + MACH_PORT_RIGHT_SEND, 1); + + if (err) + { + /* In this case the io server port has got a ref count + but the ctty port fails to get one, so we need to clean + the ref count we just assigned. */ + __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_SEND, -1); + + if (err == KERN_UREFS_OVERFLOW) + result = __hurd_fail (EMFILE); + else + result = __hurd_fail (EINVAL); + } + } + + if (!err) + { + /* The ref counts of the ports are incremented successfully. */ + /* Install the ports and flags in the new descriptor. */ + if (ctty != MACH_PORT_NULL) + _hurd_port_set (&new->ctty, ctty); + new->flags = flags; + /* Unlocks NEW. */ + _hurd_port_locked_set (&new->port, port); + } } HURD_CRITICAL_END; |