[DragonFlyBSD - Bug #3252] tcsetattr/tcgetattr set errno incorrectly on non-TTY
jpipkin
bugtracker-admin at leaf.dragonflybsd.org
Sun Jun 28 12:48:51 PDT 2026
Issue #3252 has been updated by jpipkin.
Category set to Kernel
I have a possible solution for this, or at least for the test program provided - I did not check the additional 4 routines, but I cannot say whether it is a correct solution as I do not understand all of the code path, and therefore cannot determine what else might be impacted by the change, and at present I seem to lack the kernel debugging skill to determine this.
What I can say:
1. tc[sg]etattr() live in lib/libc/gen/termios.c, and both basically just call ioctl(2).
2. sys_ioctl(), which is of course in sys/kern/sys_generic.c, is just a call to mapped_ioctl() with a null 4th argument ("map"). mapped_ioctl() immediately follows sys_ioctl() in the same source file.
3. The incorrect ENODEV comes from the call to fo_ioctl() on line 724:
<pre><code class="c">
716 default:
717 /*
718 * If there is a override function,
719 * call it instead of directly routing the call
720 */
721 if (map != NULL && iomc->wrapfunc != NULL)
722 error = iomc->wrapfunc(fp, com, ocom, data, cred);
723 else
724 error = fo_ioctl(fp, com, data, cred, msg);
</code></pre>
4. fo_ioctl() is defined in sys/sys/file2.h; the relevant line is 84:
<pre><code class="c">
84 error = (*fp->f_ops->fo_ioctl)(fp, com, data, cred, msg);
</code></pre>
5. The *fp->f_ops->fo_ioctl apparently points to devfs_fo_ioctl() in sys/vfs/devfs/devfs_vnops.c.
6. The ENODEV here comes from the call to dev_dioctl on line 1569:
<pre><code class="c">
1569 error = dev_dioctl(dev, com, data, fp->f_flag, ucred, msg, fp);
</code></pre>
7. dev_dioctl() is defined in sys/kern/kern_device.c, and the relevant line is 255:
<pre><code class="c">
255 error = dev->si_ops->d_ioctl(&ap);
</code></pre>
8. The particular d_ioctl in question is apparently mmioctl() defined in sys/kern/kern_memio.c.
9. The incorrect ENODEV at this point comes from the default case, line 506:
<pre><code class="c">
495 switch (minor(dev)) {
496 case 0:
497 error = mem_ioctl(dev, ap->a_cmd, ap->a_data,
498 ap->a_fflag, ap->a_cred);
499 break;
500 case 3:
501 case 4:
502 error = random_ioctl(dev, ap->a_cmd, ap->a_data,
503 ap->a_fflag, ap->a_cred);
504 break;
505 default:
506 error = ENODEV;
507 break;
508 }
</code></pre>
10. Changing line 506 to read "error = ENOTTY;" and recompiling the kernel causes the test program to behave correctly.
The problem is that at present I have no idea how this is going from step 7 to step 8; I have no idea why mmioctl is the contents of the dev->si_ops->d_ioctl variable in step 7. In fact, I have no idea how anything ever is getting set to mmioctl resulting in that function being called, and thus have no idea from where else it might be getting called.
That said, I am running with this change in place at present, and I haven't noticed any ill effects. All the programs I normally use run fine, I am able to build world (and obviously the kernel), as well as various dports, without issue.
----------------------------------------
Bug #3252: tcsetattr/tcgetattr set errno incorrectly on non-TTY
http://bugs.dragonflybsd.org/issues/3252#change-14673
* Author: tonyc
* Status: New
* Priority: Normal
* Category: Kernel
* Target version: 6.4
* Start date: 2020-10-26
----------------------------------------
tcsetattr() and tcgetattr() are documented to fail as follows:
Upon successful completion, the functions tcgetattr() and tcsetattr()
return a value of 0. Otherwise, they return -1 and the global variable
errno is set to indicate the error, as follows:
...
[ENOTTY] The file associated with the fd argument to
tcgetattr() or tcsetattr() is not a terminal.
which matches POSIX, but they do not set errno correctly:
$ cc -otcerror tcerror.c
$ ./tcerror
OK: tcgetattr on /dev/null failed as expected
FAIL: tcgetattr on /dev/null set errno incorrectly: Operation not supported by device
OK: tcsetattr failed as expected
FAIL: tcsetattr failure set errno incorrectly: Operation not supported by device
$ uname -a
DragonFly 5.8-RELEASE DragonFly v5.8.3-RELEASE #10: Thu Sep 24 19:19:45 EDT 2020 root at www.shiningsilence.com:/usr/obj/home/justin/release/5_8/sys/X86_64_GENERIC x86_64
This was discovered while diagnosing perl test failures.
---Files--------------------------------
tcerror.c (1.03 KB)
--
You have received this notification because you have either subscribed to it, or are involved in it.
To change your notification preferences, please click here: http://bugs.dragonflybsd.org/my/account
More information about the Bugs
mailing list