parisc: Add wrapper syscalls to fix O_NONBLOCK flag usage
authorHelge Deller <deller@gmx.de>
Thu, 22 Oct 2020 16:40:07 +0000 (18:40 +0200)
committerHelge Deller <deller@gmx.de>
Fri, 23 Oct 2020 18:14:07 +0000 (20:14 +0200)
The commit 75ae04206a4d ("parisc: Define O_NONBLOCK to become
000200000") changed the O_NONBLOCK constant to have only one bit set
(like all other architectures). This change broke some existing
userspace code (e.g.  udevadm, systemd-udevd, elogind) which called
specific syscalls which do strict value checking on their flag
parameter.

This patch adds wrapper functions for the relevant syscalls. The
wrappers masks out any old invalid O_NONBLOCK flags, reports in the
syslog if the old O_NONBLOCK value was used and then calls the target
syscall with the new O_NONBLOCK value.

Fixes: 75ae04206a4d ("parisc: Define O_NONBLOCK to become 000200000")
Signed-off-by: Helge Deller <deller@gmx.de>
Tested-by: Meelis Roos <mroos@linux.ee>
Tested-by: Jeroen Roovers <jer@xs4all.nl>
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/syscalls/syscall.tbl

index 5d458a4..9549496 100644 (file)
@@ -6,7 +6,7 @@
  *    Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
  *    Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
  *    Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
- *    Copyright (C) 1999-2014 Helge Deller <deller@gmx.de>
+ *    Copyright (C) 1999-2020 Helge Deller <deller@gmx.de>
  */
 
 #include <linux/uaccess.h>
@@ -23,6 +23,7 @@
 #include <linux/utsname.h>
 #include <linux/personality.h>
 #include <linux/random.h>
+#include <linux/compat.h>
 
 /* we construct an artificial offset for the mapping based on the physical
  * address of the kernel mapping variable */
@@ -373,3 +374,73 @@ long parisc_personality(unsigned long personality)
 
        return err;
 }
+
+/*
+ * Up to kernel v5.9 we defined O_NONBLOCK as 000200004,
+ * since then O_NONBLOCK is defined as 000200000.
+ *
+ * The following wrapper functions mask out the old
+ * O_NDELAY bit from calls which use O_NONBLOCK.
+ *
+ * XXX: Remove those in year 2022 (or later)?
+ */
+
+#define O_NONBLOCK_OLD         000200004
+#define O_NONBLOCK_MASK_OUT    (O_NONBLOCK_OLD & ~O_NONBLOCK)
+
+static int FIX_O_NONBLOCK(int flags)
+{
+       if (flags & O_NONBLOCK_MASK_OUT) {
+               struct task_struct *tsk = current;
+               pr_warn_once("%s(%d) uses a deprecated O_NONBLOCK value.\n",
+                       tsk->comm, tsk->pid);
+       }
+       return flags & ~O_NONBLOCK_MASK_OUT;
+}
+
+asmlinkage long parisc_timerfd_create(int clockid, int flags)
+{
+       flags = FIX_O_NONBLOCK(flags);
+       return sys_timerfd_create(clockid, flags);
+}
+
+asmlinkage long parisc_signalfd4(int ufd, sigset_t __user *user_mask,
+       size_t sizemask, int flags)
+{
+       flags = FIX_O_NONBLOCK(flags);
+       return sys_signalfd4(ufd, user_mask, sizemask, flags);
+}
+
+#ifdef CONFIG_COMPAT
+asmlinkage long parisc_compat_signalfd4(int ufd,
+       compat_sigset_t __user *user_mask,
+       compat_size_t sizemask, int flags)
+{
+       flags = FIX_O_NONBLOCK(flags);
+       return compat_sys_signalfd4(ufd, user_mask, sizemask, flags);
+}
+#endif
+
+asmlinkage long parisc_eventfd2(unsigned int count, int flags)
+{
+       flags = FIX_O_NONBLOCK(flags);
+       return sys_eventfd2(count, flags);
+}
+
+asmlinkage long parisc_userfaultfd(int flags)
+{
+       flags = FIX_O_NONBLOCK(flags);
+       return sys_userfaultfd(flags);
+}
+
+asmlinkage long parisc_pipe2(int __user *fildes, int flags)
+{
+       flags = FIX_O_NONBLOCK(flags);
+       return sys_pipe2(fildes, flags);
+}
+
+asmlinkage long parisc_inotify_init1(int flags)
+{
+       flags = FIX_O_NONBLOCK(flags);
+       return sys_inotify_init1(flags);
+}
index 38c63e5..f375ea5 100644 (file)
 304    common  eventfd                 sys_eventfd
 305    32      fallocate               parisc_fallocate
 305    64      fallocate               sys_fallocate
-306    common  timerfd_create          sys_timerfd_create
+306    common  timerfd_create          parisc_timerfd_create
 307    32      timerfd_settime         sys_timerfd_settime32
 307    64      timerfd_settime         sys_timerfd_settime
 308    32      timerfd_gettime         sys_timerfd_gettime32
 308    64      timerfd_gettime         sys_timerfd_gettime
-309    common  signalfd4               sys_signalfd4                   compat_sys_signalfd4
-310    common  eventfd2                sys_eventfd2
+309    common  signalfd4               parisc_signalfd4                parisc_compat_signalfd4
+310    common  eventfd2                parisc_eventfd2
 311    common  epoll_create1           sys_epoll_create1
 312    common  dup3                    sys_dup3
-313    common  pipe2                   sys_pipe2
-314    common  inotify_init1           sys_inotify_init1
+313    common  pipe2                   parisc_pipe2
+314    common  inotify_init1           parisc_inotify_init1
 315    common  preadv  sys_preadv      compat_sys_preadv
 316    common  pwritev sys_pwritev     compat_sys_pwritev
 317    common  rt_tgsigqueueinfo       sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo
 341    common  bpf                     sys_bpf
 342    common  execveat                sys_execveat                    compat_sys_execveat
 343    common  membarrier              sys_membarrier
-344    common  userfaultfd             sys_userfaultfd
+344    common  userfaultfd             parisc_userfaultfd
 345    common  mlock2                  sys_mlock2
 346    common  copy_file_range         sys_copy_file_range
 347    common  preadv2                 sys_preadv2                     compat_sys_preadv2