Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

compat_ioctl: move rtc handling into drivers/rtc/dev.c

We no longer need the rtc compat handling to be in common code, now that
all drivers are either moved to the rtc-class framework, or (rarely)
exist in drivers/char for architectures without compat mode (m68k,
alpha and ia64, respectively).

I checked the list of ioctl commands in drivers, and the ones that are
not already handled are all compatible, again with the one exception of
m68k driver, which implements RTC_PLL_GET and RTC_PLL_SET, but has no
compat mode.

Unlike earlier versions of this patch, I'm now adding a separate
compat_ioctl handler that takes care of RTC_IRQP_READ32/RTC_IRQP_SET32
and treats all other commands as compatible, leaving the native
behavior unchanged.

The old conversion handler also deals with RTC_EPOCH_READ and
RTC_EPOCH_SET, which are not handled in rtc-dev.c but only in a single
device driver (rtc-vr41xx), so I'm adding the compat version in the same
place. I don't expect other drivers to need those commands in the future.

Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Reviewed-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
v4: handle RTC_EPOCH_SET32 in rtc_dev_compat_ioctl
v3: handle RTC_IRQP_READ32/RTC_IRQP_SET32 in rtc_dev_compat_ioctl
v2: merge compat handler into ioctl function to avoid the
compat_alloc_user_space() roundtrip, based on feedback
from Al Viro.

+40 -54
+32 -1
drivers/rtc/dev.c
··· 10 10 11 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 12 13 + #include <linux/compat.h> 13 14 #include <linux/module.h> 14 15 #include <linux/rtc.h> 15 16 #include <linux/sched/signal.h> ··· 361 360 case RTC_IRQP_SET: 362 361 err = rtc_irq_set_freq(rtc, arg); 363 362 break; 364 - 365 363 case RTC_IRQP_READ: 366 364 err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); 367 365 break; ··· 399 399 return err; 400 400 } 401 401 402 + #ifdef CONFIG_COMPAT 403 + #define RTC_IRQP_SET32 _IOW('p', 0x0c, __u32) 404 + #define RTC_IRQP_READ32 _IOR('p', 0x0b, __u32) 405 + #define RTC_EPOCH_SET32 _IOW('p', 0x0e, __u32) 406 + 407 + static long rtc_dev_compat_ioctl(struct file *file, 408 + unsigned int cmd, unsigned long arg) 409 + { 410 + struct rtc_device *rtc = file->private_data; 411 + void __user *uarg = compat_ptr(arg); 412 + 413 + switch (cmd) { 414 + case RTC_IRQP_READ32: 415 + return put_user(rtc->irq_freq, (__u32 __user *)uarg); 416 + 417 + case RTC_IRQP_SET32: 418 + /* arg is a plain integer, not pointer */ 419 + return rtc_dev_ioctl(file, RTC_IRQP_SET, arg); 420 + 421 + case RTC_EPOCH_SET32: 422 + /* arg is a plain integer, not pointer */ 423 + return rtc_dev_ioctl(file, RTC_EPOCH_SET, arg); 424 + } 425 + 426 + return rtc_dev_ioctl(file, cmd, (unsigned long)uarg); 427 + } 428 + #endif 429 + 402 430 static int rtc_dev_fasync(int fd, struct file *file, int on) 403 431 { 404 432 struct rtc_device *rtc = file->private_data; ··· 462 434 .read = rtc_dev_read, 463 435 .poll = rtc_dev_poll, 464 436 .unlocked_ioctl = rtc_dev_ioctl, 437 + #ifdef CONFIG_COMPAT 438 + .compat_ioctl = rtc_dev_compat_ioctl, 439 + #endif 465 440 .open = rtc_dev_open, 466 441 .release = rtc_dev_release, 467 442 .fasync = rtc_dev_fasync,
+8
drivers/rtc/rtc-vr41xx.c
··· 4 4 * 5 5 * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org> 6 6 */ 7 + #include <linux/compat.h> 7 8 #include <linux/err.h> 8 9 #include <linux/fs.h> 9 10 #include <linux/init.h> ··· 66 65 67 66 #define rtc2_read(offset) readw(rtc2_base + (offset)) 68 67 #define rtc2_write(offset, value) writew((value), rtc2_base + (offset)) 68 + 69 + /* 32-bit compat for ioctls that nobody else uses */ 70 + #define RTC_EPOCH_READ32 _IOR('p', 0x0d, __u32) 69 71 70 72 static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */ 71 73 ··· 183 179 switch (cmd) { 184 180 case RTC_EPOCH_READ: 185 181 return put_user(epoch, (unsigned long __user *)arg); 182 + #ifdef CONFIG_64BIT 183 + case RTC_EPOCH_READ32: 184 + return put_user(epoch, (unsigned int __user *)arg); 185 + #endif 186 186 case RTC_EPOCH_SET: 187 187 /* Doesn't support before 1900 */ 188 188 if (arg < 1900)
-53
fs/compat_ioctl.c
··· 32 32 #include <linux/vt_kern.h> 33 33 #include <linux/raw.h> 34 34 #include <linux/blkdev.h> 35 - #include <linux/rtc.h> 36 35 #include <linux/pci.h> 37 36 #include <linux/serial.h> 38 37 #include <linux/ctype.h> ··· 435 436 #define HCIUARTSETFLAGS _IOW('U', 203, int) 436 437 #define HCIUARTGETFLAGS _IOR('U', 204, int) 437 438 438 - #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) 439 - #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) 440 - #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) 441 - #define RTC_EPOCH_SET32 _IOW('p', 0x0e, compat_ulong_t) 442 - 443 - static int rtc_ioctl(struct file *file, 444 - unsigned cmd, void __user *argp) 445 - { 446 - unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp)); 447 - int ret; 448 - 449 - if (valp == NULL) 450 - return -EFAULT; 451 - switch (cmd) { 452 - case RTC_IRQP_READ32: 453 - case RTC_EPOCH_READ32: 454 - ret = do_ioctl(file, (cmd == RTC_IRQP_READ32) ? 455 - RTC_IRQP_READ : RTC_EPOCH_READ, 456 - (unsigned long)valp); 457 - if (ret) 458 - return ret; 459 - return convert_in_user(valp, (unsigned int __user *)argp); 460 - case RTC_IRQP_SET32: 461 - return do_ioctl(file, RTC_IRQP_SET, (unsigned long)argp); 462 - case RTC_EPOCH_SET32: 463 - return do_ioctl(file, RTC_EPOCH_SET, (unsigned long)argp); 464 - } 465 - 466 - return -ENOIOCTLCMD; 467 - } 468 - 469 439 /* 470 440 * simple reversible transform to make our table more evenly 471 441 * distributed after sorting. ··· 471 503 /* Big V (don't complain on serial console) */ 472 504 IGNORE_IOCTL(VT_OPENQRY) 473 505 IGNORE_IOCTL(VT_GETMODE) 474 - /* Little p (/dev/rtc, /dev/envctrl, etc.) */ 475 - COMPATIBLE_IOCTL(RTC_AIE_ON) 476 - COMPATIBLE_IOCTL(RTC_AIE_OFF) 477 - COMPATIBLE_IOCTL(RTC_UIE_ON) 478 - COMPATIBLE_IOCTL(RTC_UIE_OFF) 479 - COMPATIBLE_IOCTL(RTC_PIE_ON) 480 - COMPATIBLE_IOCTL(RTC_PIE_OFF) 481 - COMPATIBLE_IOCTL(RTC_WIE_ON) 482 - COMPATIBLE_IOCTL(RTC_WIE_OFF) 483 - COMPATIBLE_IOCTL(RTC_ALM_SET) 484 - COMPATIBLE_IOCTL(RTC_ALM_READ) 485 - COMPATIBLE_IOCTL(RTC_RD_TIME) 486 - COMPATIBLE_IOCTL(RTC_SET_TIME) 487 - COMPATIBLE_IOCTL(RTC_WKALM_SET) 488 - COMPATIBLE_IOCTL(RTC_WKALM_RD) 489 506 /* 490 507 * These two are only for the sbus rtc driver, but 491 508 * hwclock tries them on every rtc device first when ··· 850 897 case MTIOCPOS32: 851 898 return mt_ioctl_trans(file, cmd, argp); 852 899 #endif 853 - /* Not implemented in the native kernel */ 854 - case RTC_IRQP_READ32: 855 - case RTC_IRQP_SET32: 856 - case RTC_EPOCH_READ32: 857 - case RTC_EPOCH_SET32: 858 - return rtc_ioctl(file, cmd, argp); 859 900 } 860 901 861 902 /*