[PATCH] rtc subsystem: add capability checks
Alessandro Zummo [Sun, 25 Jun 2006 12:48:20 +0000 (05:48 -0700)]
Centralize CAP_SYS_XXX checks to avoid duplicate code and missing checks in
the drivers.

Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

drivers/rtc/class.c
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-sa1100.c
drivers/rtc/rtc-vr41xx.c
include/linux/rtc.h

index 413c7d5..5396bee 100644 (file)
@@ -69,6 +69,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
        rtc->id = id;
        rtc->ops = ops;
        rtc->owner = owner;
+       rtc->max_user_freq = 64;
        rtc->class_dev.dev = dev;
        rtc->class_dev.class = rtc_class;
        rtc->class_dev.release = rtc_device_release;
index 07387c9..61a5825 100644 (file)
@@ -214,6 +214,28 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
        struct rtc_wkalrm alarm;
        void __user *uarg = (void __user *) arg;
 
+       /* check that the calles has appropriate permissions
+        * for certain ioctls. doing this check here is useful
+        * to avoid duplicate code in each driver.
+        */
+       switch (cmd) {
+       case RTC_EPOCH_SET:
+       case RTC_SET_TIME:
+               if (!capable(CAP_SYS_TIME))
+                       return -EACCES;
+               break;
+
+       case RTC_IRQP_SET:
+               if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE))
+                       return -EACCES;
+               break;
+
+       case RTC_PIE_ON:
+               if (!capable(CAP_SYS_RESOURCE))
+                       return -EACCES;
+               break;
+       }
+
        /* avoid conflicting IRQ users */
        if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
                spin_lock(&rtc->irq_task_lock);
@@ -272,9 +294,6 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
                break;
 
        case RTC_SET_TIME:
-               if (!capable(CAP_SYS_TIME))
-                       return -EACCES;
-
                if (copy_from_user(&tm, uarg, sizeof(tm)))
                        return -EFAULT;
 
@@ -290,10 +309,6 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
                        err = -EINVAL;
                        break;
                }
-               if (!capable(CAP_SYS_TIME)) {
-                       err = -EACCES;
-                       break;
-               }
                rtc_epoch = arg;
                err = 0;
 #endif
index a997529..ab486fb 100644 (file)
@@ -229,8 +229,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
                spin_unlock_irq(&sa1100_rtc_lock);
                return 0;
        case RTC_PIE_ON:
-               if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
-                       return -EACCES;
                spin_lock_irq(&sa1100_rtc_lock);
                OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
                OIER |= OIER_E1;
@@ -242,8 +240,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
        case RTC_IRQP_SET:
                if (arg < 1 || arg > TIMER_FREQ)
                        return -EINVAL;
-               if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
-                       return -EACCES;
                rtc_freq = arg;
                return 0;
        }
index 277596c..33e0292 100644 (file)
@@ -81,7 +81,6 @@ MODULE_LICENSE("GPL");
 
 #define RTC_FREQUENCY          32768
 #define MAX_PERIODIC_RATE      6553
-#define MAX_USER_PERIODIC_RATE 64
 
 static void __iomem *rtc1_base;
 static void __iomem *rtc2_base;
@@ -240,9 +239,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
                if (arg > MAX_PERIODIC_RATE)
                        return -EINVAL;
 
-               if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0)
-                       return -EACCES;
-
                periodic_frequency = arg;
 
                count = RTC_FREQUENCY;
@@ -263,10 +259,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
                /* Doesn't support before 1900 */
                if (arg < 1900)
                        return -EINVAL;
-
-               if (capable(CAP_SYS_TIME) == 0)
-                       return -EACCES;
-
                epoch = arg;
                break;
        default:
index 4331076..c12cbc1 100644 (file)
@@ -155,6 +155,7 @@ struct rtc_device
        struct rtc_task *irq_task;
        spinlock_t irq_task_lock;
        int irq_freq;
+       int max_user_freq;
 #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
        struct work_struct uie_task;
        struct timer_list uie_timer;