Bug 202933

Summary: unwanted behaviour change when writing to revoked terminals
Product: Base System Reporter: Alexandre Fenyo <fbsd.bugzilla>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: New ---    
Severity: Affects Some People Keywords: regression
Priority: ---    
Version: 10.2-RELEASE   
Hardware: Any   
OS: Any   

Description Alexandre Fenyo 2015-09-06 17:04:01 UTC
Hi,

When a terminal is revoked, writing to it sets errno to:
- ENXIO until FreeBSD 10.1 kernel
- EIO with FreeBSD 10.2 kernel

The following program can be used to see this behaviour change:
------------------------------------------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
extern int errno;
int main() {
  int id = open("/dev/console", O_RDWR);
  revoke("/dev/console");
  int ret = write(id, "X", 1);
  if (ret < 0) printf("errno=%d\n", errno);
  return 0;
}
------------------------------------------------------------------
It returns 6 (ENXIO) on FreeBSD 10.1 and 5 (EIO) on FreeBSD 10.2.

I wonder if this new behaviour would not be an unwanted side-effect due to kernel changes.

For instance, this leads to bug ID 202932 for the rsyslog8 port, that loops endlessly after /dev/console is revoked since the errno code tested to handle correctly this case is now EIO instead of ENXIO.

This could happen to some other tools for the same reason.

Sincerely,
Comment 1 Alexandre Fenyo 2015-09-13 23:48:32 UTC
Hi,

I've found the kernel sources change that has modified this behaviour:

this is relative to base revision 273131 - https://svnweb.freebsd.org/base?view=revision&revision=273131

This revision modifies /usr/src/sys/fs/devfs/devfs_vnops.c:devfs_write_f():

-------------------------------------------------------------------
        error = devfs_fp_check(fp, &dev, &dsw, &ref);
        if (error != 0)
                return (error);
-------------------------------------------------------------------
is replaced by:
-------------------------------------------------------------------
        error = devfs_fp_check(fp, &dev, &dsw, &ref);
        if (error != 0) {
                error = vnops.fo_write(fp, uio, cred, flags, td);
                return (error);
        }
-------------------------------------------------------------------

When a terminal is revoked, devfs_fp_check() returns ENXIO (6).
This is for instance the value used by rsyslog8 to handle this case correctly.

But with this modification, the kernel now returns EIO (5), that is the generic error value returned by vnops.fo_write(), since fo_write() does not handle specifically revoked terminals.

This behaviour change seems to be wanted, reading the svn log message:

    > read/write/poll/ioctl, call standard vnode filedescriptor fop.  This
    > restores the special handling for terminals by calling the deadfs VOP,
    > instead of always returning ENXIO for destroyed devices or revoked
    > terminals.
    >
    > Since destroyed (and not revoked) device would use devfs_specops VOP
    > vector, make dead_read/write/poll non-static and fill VOP table with
    > pointers to the functions, to instead of VOP_PANIC.

But some ports, at least, are waiting for ENXIO to reopen a device that has been revoked, and they no longer work correctly because this kernel behaviour changed (for instance, rsyslog8 now loops endlessly at end of boot sequence, when /dev/console is revoked by getty).

So, this seems to be an ABI change between FreeBSD 10.1 and 10.2, but I wonder if ABI changes should really occur in the same major branch (10-Release branch).

I wonder if a special handling for revoked terminals, in devfs_write_f(), should be made to continue to return ENXIO for revoked terminals, in 10-Release branch at least.

What do you think of this proposal ?

Sincerely,
Comment 2 Alexandre Fenyo 2016-01-10 14:01:00 UTC
Hi,

This is about my previous proposal:

> So, this seems to be an ABI change between FreeBSD 10.1 and 10.2, but I wonder
> if ABI changes should really occur in the same major branch (10-Release branch).
> I wonder if a special handling for revoked terminals, in devfs_write_f(),
> should be made to continue to return ENXIO for revoked terminals, in 10-Release
> branch at least.

What do you think of this proposal ?
Many thanks,
Comment 3 Alexandre Fenyo 2016-01-10 14:09:14 UTC
One more information about this problem:

This kernel change, that has modified the error number returned by a syscall trying to write to a revoked console, that seems to me to be an ABI change in the 10-Release major branch, breaks the rsyslogd port.

So, depending on the response to this bug ID (bug ID 202933) by FreeBSD kernel maintainers, I will have, or not, to report a patch proposal for rsyslogd:

- if this kernel change will stay with this new syscall return value, I'll propose a patch in bug ID 202932 to let rsyslogd adapt itself to this new return value of the kernel,

- and on the contrary, If kernel is to be patched, I will propose to close bug ID 202932.

So, your answer is important for me to be able to work on BUG ID 202932.

Many thanks,