[LinuxPPS] [PATCH 11/11] PPS: Make permission checking more sensible.

George Spelvin linux at horizon.com
Fri Feb 6 14:36:24 CET 2009


Rather that play with CAP_SYS_TIME and all that, just require the file be
opened with read access (which requires read permission on the device) to
get timestamps, and write permission to alter the global parameters.

---
 drivers/pps/pps.c |   50 ++++++++++++++++++++++++++------------------------
 1 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index 8e3ef56..7a32920 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -36,6 +36,7 @@
 
 static dev_t pps_devt;
 static struct class *pps_class;
+#define PPS_ECHOBOTH (PPS_ECHOASSERT | PPS_ECHOCLEAR)
 
 /*
  * Local functions
@@ -148,12 +149,12 @@ static long pps_cdev_ioctl(struct file *file,
 {
 	struct pps_device *pps = container_of(file->f_dentry->d_inode->i_cdev,
 						struct pps_device, cdev);
+	struct pps_kinfo *info = file->private_data;
+	void __user *uarg = (void __user *) arg;
+	struct pps_fdata __user *fuarg = uarg;
 	struct pps_kparams params;
-	struct pps_kinfo *info;
 	struct pps_fdata fdata;
 	unsigned long ticks;
-	void __user *uarg = (void __user *) arg;
-	struct pps_fdata __user *fuarg = uarg;
 	u32 seq1, seq2;
 	int err;
 
@@ -168,9 +169,7 @@ static long pps_cdev_ioctl(struct file *file,
 		pr_debug("PPS_GETPARAMS: source %d\n", pps->id);
 
 		/* Return current parameters */
-		info = file->private_data;
-		params.mode = info->current_mode &
-				~(PPS_ECHOASSERT | PPS_ECHOCLEAR);
+		params.mode = info->current_mode & ~PPS_ECHOBOTH;
 		params.assert_off_tu = info->assert_tu;
 		params.clear_off_tu = info->clear_tu;
 
@@ -187,17 +186,11 @@ static long pps_cdev_ioctl(struct file *file,
 	case PPS_SETPARAMS:
 		pr_debug("PPS_SETPARAMS: source %d\n", pps->id);
 
-		/* Check the capabilities */
-		if (!capable(CAP_SYS_TIME))
-			return -EPERM;
-
 		/* Sanity checks */
-		if (!uarg)
-			return -EINVAL;
 		err = copy_from_user(&params, uarg, sizeof params);
 		if (err)
 			return -EFAULT;
-		if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
+		if (!(params.mode & PPS_CAPTUREBOTH)) {
 			pr_debug("capture mode unspecified (%x)\n",
 								params.mode);
 			return -EINVAL;
@@ -219,16 +212,23 @@ static long pps_cdev_ioctl(struct file *file,
 		}
 		params.mode |= pps->info.mode & (PPS_CANWAIT | PPS_CANPOLL);
 
+		/* Change the global parameters? */
+		if ((pps->echo_mode ^ params.mode) & PPS_ECHOBOTH) {
+			/* Write permission required */
+			if (!(file->f_mode & FMODE_WRITE)) {
+				pr_debug("no permission to set echo (%x)\n",
+								params.mode);
+				return -EBADF;	/* Not open for write */
+			}
+			spin_lock(&pps->lock);
+			pps->echo_mode = params.mode & PPS_ECHOBOTH;
+			spin_unlock(&pps->lock);
+		}
+
 		/* Save the new parameters in the local version */
-		info = file->private_data;
 		pps_norm_offset(&info->assert_tu, &params.assert_off_tu);
 		pps_norm_offset(&info->clear_tu, &params.clear_off_tu);
-		info->current_mode = params.mode;
-
-		/* Save the global parameters (only the echo bits count) */
-		spin_lock(&pps->lock);
-		pps->echo_mode = params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR);
-		spin_unlock(&pps->lock);
+		info->current_mode = params.mode & ~PPS_ECHOBOTH;
 
 		break;
 
@@ -244,15 +244,13 @@ static long pps_cdev_ioctl(struct file *file,
 	case PPS_FETCH:
 		pr_debug("PPS_FETCH: source %d\n", pps->id);
 
-		if (!uarg)
-			return -EINVAL;
+		if (!(file->f_mode & FMODE_READ))
+			return -EBADF;	/* Not open for read */
 		err = copy_from_user(&fdata.timeout, &fuarg->timeout,
 			sizeof fdata.timeout);
 		if (err)
 			return -EFAULT;
 
-		info = file->private_data;
-
 		/* Manage the timeout */
 		if (fdata.timeout.flags & PPS_TIME_INVALID)
 			err = wait_event_interruptible(pps->queue,
@@ -269,6 +267,10 @@ static long pps_cdev_ioctl(struct file *file,
 						pps->queue,
 						pps_is_ready(pps, info),
 						ticks);
+				/*
+				 * RFC 2783 requires this error, although
+				 * it really should be EAGAIN.
+				 */
 				if (err == 0)
 					return -ETIMEDOUT;
 			}
-- 
1.6.0.6




More information about the LinuxPPS mailing list