ioctl: do the job right this time I hope
authorAlan Cox <alan@linux.intel.com>
Sun, 24 Jul 2016 11:11:36 +0000 (12:11 +0100)
committerAlan Cox <alan@linux.intel.com>
Sun, 24 Jul 2016 11:11:36 +0000 (12:11 +0100)
We now have four ioctl classes but don't yet use the write only class

Kernel/include/kernel.h
Kernel/syscall_fs.c

index 88173c2..ef0f878 100644 (file)
@@ -588,7 +588,14 @@ struct s_argblk {
 #define SELECT_BEGIN           0x8000
 #define SELECT_END             0x8001
 
-#define IOCTL_SUPER            0x4000  /* superuser needed */
+#define IOCTL_NORMAL           0x0000  /* No special rules */
+#define IOCTL_SUPER            0x4000  /* Superuser needed */
+#define IOCTL_KERNEL           0x8000  /* Kernel side only */
+#define IOCTL_WRONLY           0xC000  /* Write handle needed */
+
+#define IOCTL_CLASS_SUPER      0x40
+#define IOCTL_CLASS_KERNEL     0x80
+#define IOCTL_CLASS_WRONLY     0xC0
 
 /*
  *     Ioctl ranges
index 43d1334..10d7c55 100644 (file)
@@ -251,27 +251,29 @@ arg_t _ioctl(void)
 {
        inoptr ino;
        uint16_t dev;
+       uint8_t rclass = ((uint8_t)(request >> 8)) & 0xC0;
+       struct oft *oftp;
 
        if ((ino = getinode(fd)) == NULLINODE)
                return -1;
 
-       if (!(isdevice(ino))) {
+       oftp = of_tab + udata.u_files[fd];
+
+       if (!(isdevice(ino)) || rclass == IOCTL_CLASS_KERNEL) {
                udata.u_error = ENOTTY;
                return -1;
        }
 
-       if ((request & IOCTL_SUPER) && esuper())
+       if (rclass == IOCTL_CLASS_SUPER && esuper())
                return -1;
-
-       if (!(getperm(ino) & OTH_WR)) {
+       if (rclass == IOCTL_CLASS_WRONLY && O_ACCMODE(oftp->o_access) == O_RDONLY) {
                udata.u_error = EPERM;
                return -1;
        }
 
        dev = ino->c_node.i_addr[0];
 
-       /* top bit of request is reserved for kernel originated magic */
-       return d_ioctl(dev, request & 0x7FFF, data);
+       return d_ioctl(dev, request, data);
 }
 
 #undef fd